- 引入AgentTeamOrchestrator支持多agent协同任务执行 - 增加第三方swarms库依赖并配置git协议替换以改善包管理 - 扩展DelegationManager支持团队任务调度和进度跟踪 - 实现中文bigram分词算法提升中文任务检索准确性 - 调整A2AClient和DelegationManager超时时间从30秒增至600秒 - 优化AgentRunResult状态判断逻辑增加有意义摘要检测 - 修改Dockerfile配置npm仓库镜像地址和git协议映射 - 更新CLI命令行接口支持网关端口配置传递 - 调整提供者超时配置机制增强请求稳定性 - 移除过时的support_group字段简化agent描述符结构 - 增强错误处理和进度事件报告机制改进用户体验
12 KiB
https://d3qpg7p2n3hazf.cloudfront.net/api/v1/client/subscribe?token=2185761c5925a800c2d2c1ec44449b65
nano_project
单机部署版运行结构:
auth-portal- 用户入口页,提供登录、注册、跳转。
authz-service- AuthZ 服务。
- 现在负责注册编排:
auth-portal -> authz-service -> deploy-control -> app-instance -> authz-service
deploy-control- 部署机控制面。
- 负责创建实例、解析实例、刷新反向代理。
router-proxy- 统一入口代理。
- 按 Host 把
<slug>.<base_domain>转发到对应实例容器。
app-instance- 真正的单用户实例。
- 一个容器里同时包含前端、后端和 Nginx。
请求链路
注册:
Browser
-> auth-portal
-> authz-service POST /portal/register
-> deploy-control POST /api/instances/register
-> create-instance.sh
-> app-instance POST /api/auth/register
-> authz-service /oauth/register or /backends/register
登录:
Browser
-> auth-portal
-> deploy-control POST /api/instances/resolve
-> app-instance POST /api/auth/login
这份部署指南的前提
这份 README 只覆盖一套基准方案:
- 一台 Linux 服务器
- 用 Docker 运行
auth-portal、authz-service、deploy-control、router-proxy deploy-control通过 Docker socket 在同一台机器上创建app-instance- 所有容器共用一个 Docker network:
nano-instance-edge - 测试域名先用
nip.io
如果你后面要接 HTTPS、外部 LB、Kubernetes、真实 DNS,这份流程仍然适合作为最小可运行基线。
可直接参考这些模板文件:
.env.exampleauth-portal/src/.env.exampleauthz-service/.env.exampledeploy-control/.env.examplerouter-proxy/.env.example
注意:
- 这些文件是模板,不会被现有脚本自动加载
- 你可以手动
export,或者在docker run时使用--env-file
部署前必须先定好的值
先准备这些值:
PROJECT_ROOT- 仓库根目录。
NANO_NET- Docker network 名。
- 推荐固定成
nano-instance-edge。
NANO_DEPLOY_TOKENauth-portal/authz-service调deploy-control时用的 Bearer token。
NANO_AUTHZ_INTERNAL_TOKEN- AuthZ 内部接口 token。
NANO_SERVER_IP- 服务器公网 IP,供
nip.io测试使用。
- 服务器公网 IP,供
NANO_BASE_DOMAIN- 实例基域名。
- 测试环境推荐
<SERVER_IP>.nip.io
NANO_PROVIDER- 默认 provider,例如
openai
- 默认 provider,例如
NANO_MODEL- 默认模型,例如
openai/gpt-5
- 默认模型,例如
NANO_API_KEY- 默认分发给新实例的 provider API key
NANO_API_BASE- 可空,自定义 provider base URL
NANO_AUTHZ_URL- 这个值必须是
app-instance容器能访问到的 AuthZ 地址
- 这个值必须是
NANO_OUTLOOK_MCP_URL- 可空。
- 如果配置了,所有新创建的
app-instance都会默认带一个 Outlook MCP HTTP 工具配置。
NANO_OUTLOOK_MCP_SERVER_ID- Outlook MCP 默认 server id。
- 推荐固定成
outlook_mcp。
NANO_DEPLOY_URLauth-portal和authz-service在容器网络里访问 deploy-control 的地址
直接导出一套最小配置:
export PROJECT_ROOT=/home/ivan/xuan/nano_project
export NANO_NET=nano-instance-edge
export NANO_DEPLOY_TOKEN="$(openssl rand -hex 32)"
export NANO_AUTHZ_INTERNAL_TOKEN="$(openssl rand -hex 32)"
export NANO_SERVER_IP=203.0.113.10
export NANO_BASE_DOMAIN="${NANO_SERVER_IP}.nip.io"
export NANO_PROVIDER=openai
export NANO_MODEL=openai/gpt-5
export NANO_API_KEY='sk-xxxxxxxx'
export NANO_API_BASE=''
export NANO_AUTHZ_URL='http://nano-authz-service:19090'
export NANO_OUTLOOK_MCP_URL=''
export NANO_OUTLOOK_MCP_SERVER_ID='outlook_mcp'
export NANO_DEPLOY_URL='http://nano-deploy-control:8090'
变量到底是什么
最容易混淆的是下面这几组:
DEPLOY_API_TOKEN- 调用方带出去的 token。
auth-portal和authz-service会用它请求deploy-control。
DEPLOY_CONTROL_API_TOKENdeploy-control服务端校验的 token。- 它必须和
DEPLOY_API_TOKEN相等。
AUTHZ_ISSUER- 当前实现里它既是 AuthZ 的 issuer,也是新实例要访问的 AuthZ base URL。
- 所以不要乱写
127.0.0.1,要写成实例容器能访问到的地址。
APP_INSTANCE_PROVIDER- 新实例默认 provider。
APP_INSTANCE_MODEL- 新实例默认模型。
APP_INSTANCE_API_KEY- 新实例默认 API key。
APP_INSTANCE_API_BASE- 新实例默认 API base。
DEFAULT_AUTHZ_BASE_URLdeploy-control在没收到显式authz_base_url时,给新实例写入的兜底 AuthZ 地址。
当前版本里,provider 配置不是从 AuthZ setting 下发的。
它是在创建实例时由 deploy-control 写入 app-instance 的 config.json。
目录持久化
至少保留这几个目录:
authz-service/runtime/dataapp-instance/runtimerouter-proxy/runtime
建议先创建:
mkdir -p \
"$PROJECT_ROOT/authz-service/runtime/data" \
"$PROJECT_ROOT/app-instance/runtime/instances" \
"$PROJECT_ROOT/app-instance/runtime/registry" \
"$PROJECT_ROOT/router-proxy/runtime/conf.d"
1. 构建镜像
先把四个镜像都构建好。虽然 deploy-control 在镜像缺失时也能触发构建,但上线前先显式构建更容易排错。
cd "$PROJECT_ROOT"
docker build -t nano/app-instance:latest app-instance
docker build -t nano/authz-service:latest authz-service
docker build -t nano/deploy-control:latest deploy-control
docker build -t nano/auth-portal:latest auth-portal/src
2. 创建共享网络
docker network inspect "$NANO_NET" >/dev/null 2>&1 || docker network create "$NANO_NET"
3. 启动 router-proxy
cd "$PROJECT_ROOT"
PROXY_NETWORK_NAME="$NANO_NET" \
PROXY_HTTP_PORT=8088 \
./router-proxy/start-proxy.sh --replace
默认对外入口:
router-proxy:http://<slug>.<base_domain>:8088
4. 启动 authz-service
docker rm -f nano-authz-service >/dev/null 2>&1 || true
docker run -d \
--name nano-authz-service \
--restart unless-stopped \
--network "$NANO_NET" \
-p 19090:19090 \
-v "$PROJECT_ROOT/authz-service/runtime/data:/var/lib/authz-service/data" \
-e AUTHZ_ISSUER="$NANO_AUTHZ_URL" \
-e AUTHZ_INTERNAL_TOKEN="$NANO_AUTHZ_INTERNAL_TOKEN" \
-e DEPLOY_API_BASE_URL="$NANO_DEPLOY_URL" \
-e DEPLOY_API_TOKEN="$NANO_DEPLOY_TOKEN" \
nano/authz-service:latest
这里最重要的是:
AUTHZ_ISSUER现在不能只按“外部访问地址”理解- 它必须是后续
app-instance容器也能访问到的地址 - 这套单机 Docker 方案里直接用
http://nano-authz-service:19090
5. 启动 deploy-control
deploy-control 需要高权限:
- 读写 Docker socket
- 访问
app-instance/ - 访问
router-proxy/
docker rm -f nano-deploy-control >/dev/null 2>&1 || true
docker run -d \
--name nano-deploy-control \
--restart unless-stopped \
--network "$NANO_NET" \
-p 8090:8090 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PROJECT_ROOT/app-instance:$PROJECT_ROOT/app-instance" \
-v "$PROJECT_ROOT/router-proxy:$PROJECT_ROOT/router-proxy" \
-e APP_INSTANCE_DIR="$PROJECT_ROOT/app-instance" \
-e ROUTER_PROXY_DIR="$PROJECT_ROOT/router-proxy" \
-e DEPLOY_CONTROL_API_TOKEN="$NANO_DEPLOY_TOKEN" \
-e APP_INSTANCE_IMAGE="nano/app-instance:latest" \
-e APP_INSTANCE_NETWORK_NAME="$NANO_NET" \
-e APP_INSTANCE_PROVIDER="$NANO_PROVIDER" \
-e APP_INSTANCE_MODEL="$NANO_MODEL" \
-e APP_INSTANCE_API_KEY="$NANO_API_KEY" \
-e APP_INSTANCE_API_BASE="$NANO_API_BASE" \
-e DEFAULT_AUTHZ_BASE_URL="$NANO_AUTHZ_URL" \
-e DEFAULT_AUTHZ_OUTLOOK_MCP_URL="$NANO_OUTLOOK_MCP_URL" \
-e DEFAULT_OUTLOOK_MCP_SERVER_ID="$NANO_OUTLOOK_MCP_SERVER_ID" \
-e DEPLOY_PUBLIC_SCHEME="http" \
-e DEPLOY_PUBLIC_BASE_DOMAIN="$NANO_BASE_DOMAIN" \
-e DEPLOY_PUBLIC_PORT="8088" \
-e DEPLOY_AUTO_START_PROXY="1" \
nano/deploy-control:latest
这里不要把宿主机目录挂到容器内的另一个短路径,比如 /app-instance。
原因是 deploy-control 会通过挂载进来的 Docker socket 再去创建 app-instance 容器;这时传给 Docker 的 bind mount 源路径必须是宿主机真实路径。如果你把宿主机目录映射成容器内短路径,create-instance.sh 生成的挂载源就会变成错误路径,最终表现为:
- 注册接口超时
app-instance容器反复重启- 日志里出现
Missing Boardware Genius config: /root/.nanobot/config.json
当前版本里,新实例的默认大模型配置就是从这里分发的:
APP_INSTANCE_PROVIDERAPP_INSTANCE_MODELAPP_INSTANCE_API_KEYAPP_INSTANCE_API_BASE
如果 APP_INSTANCE_API_KEY 没配,新用户注册时创建实例会直接失败。
6. 启动 auth-portal
docker rm -f nano-auth-portal >/dev/null 2>&1 || true
docker run -d \
--name nano-auth-portal \
--restart unless-stopped \
--network "$NANO_NET" \
-p 3081:3081 \
-e AUTHZ_API_BASE_URL="$NANO_AUTHZ_URL" \
-e DEPLOY_API_BASE_URL="$NANO_DEPLOY_URL" \
-e DEPLOY_API_TOKEN="$NANO_DEPLOY_TOKEN" \
nano/auth-portal:latest
当前页面入口:
http://<server-ip>:3081
7. 上线前健康检查
先确认四个基础组件都起来了:
curl http://127.0.0.1:19090/healthz
curl http://127.0.0.1:8090/healthz
curl -I http://127.0.0.1:3081
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
再确认 router-proxy 在跑:
docker logs --tail=50 nano-router-proxy
8. 首次注册验收
打开:
http://<server-ip>:3081/register
注册一个新用户后,预期结果是:
auth-portal调authz-service /portal/registerauthz-service调deploy-control /api/instances/registerdeploy-control创建一个新的app-instanceapp-instance回调 AuthZ 完成 backend 身份初始化- 浏览器被跳转到该实例自己的 URL
同时你应该能看到:
cd "$PROJECT_ROOT"
./app-instance/list-instances.sh --json
新实例 URL 形如:
http://<instance-slug>.<base-domain>:8088
如果你前面用的是:
NANO_BASE_DOMAIN=<server-ip>.nip.io
那么实例地址会像:
http://alice.203.0.113.10.nip.io:8088
9. 常见问题
1. 为什么不要把 AUTHZ_ISSUER 写成 http://127.0.0.1:19090
因为 app-instance 容器里访问 127.0.0.1 只会打到它自己,不会打到 AuthZ 容器。
在当前实现里,AUTHZ_ISSUER 会被直接传给新实例当作 authz_base_url。
2. DEPLOY_API_TOKEN 和 DEPLOY_CONTROL_API_TOKEN 为什么要一样
因为一个是客户端发出去的 token,一个是服务端拿来校验的 token。
3. 这些 provider 配置是写到哪里
写到每个实例自己的:
app-instance/runtime/instances/<slug>/nanobot-home/config.json
不是写在 AuthZ 的某个 setting 里。
4. 现在支持每个用户注册时填自己的 API key 吗
后端请求模型已经支持 provider/model/api_key/api_base 字段,但当前 auth-portal 页面没有把这些字段暴露出来。
当前上线流程默认是:所有新实例先继承 deploy-control 上配置的默认 provider 凭证。
5. 现在内置 HTTPS 吗
没有。
当前内置 router-proxy 是 HTTP 入口。如果你要公网 HTTPS:
- 在外面再放一层 Nginx / Caddy / LB 做 TLS 终止
- 再把流量转给
router-proxy:8088和auth-portal:3081
10. 仓库结构
/home/ivan/xuan/nano_project
├── README.md
├── app-instance/
├── auth-portal/
├── authz-service/
├── deploy-control/
└── router-proxy/
各子目录更细的实现说明见: