docs(integration): update AM contract to current state + real-test results

- new §0.1 联调结果: real production test outcomes — create POST /agents works
  (returns access_info.domain/namespace), DELETE /agents/{id} 500s (AM
  UnboundLocalError bug), POST /agents/{id}/stop 404 (no endpoint), agent stays
  Pending / subdomain unreachable. The 3 AM-side blockers listed up top.
- OPENAI_API_KEY is now injected (a minted user new-api sk-, billed to the user,
  revoked on delete; verified working at /v1) — §1.1 env + §2 updated.
- §3 client<->agent: now documents AM's A2A protocol (message/send · stream),
  api_key auth, and flags the per-user isolation security gap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 17:36:23 +08:00
co-authored by Claude Opus 4.8
parent d19920d1d0
commit b7d1927a5b
+27 -7
View File
@@ -2,13 +2,28 @@
> 更新时间:2026-06-04
> 角色:**HM** = Heicode Manager(网关/控制面/模型网关)。**AM** = agent_management(云端 agent 运行时,你们)。
> 现状:HM 侧已全部实现并生产验证;**等 AM 实现本文 4 个接口 + agent 直连端**,整条链路即打通。HM 调 AM 的代码全部隔离在 `heicode/controller/agent_template_runtime.go`,字段/路径可按本文对齐;路径都支持环境变量覆盖(见末尾)。
> 现状(2026-06-04 真实联调):**创建 agent 已打通**(HM→`POST /agents`→AM 返回 subdomain);**剩 3 条阻断在 AM 侧**(删除 500 bug / 缺 stop 端点 / agent 不就绪),见 §0.1。HM 调 AM 的代码全部隔离在 `heicode/controller/agent_template_runtime.go`,字段/路径可按本文对齐;路径都支持环境变量覆盖(见末尾)。
---
## 0. 模型一句话
用户在 HM 网页台选「资源 + agent 模板」部署 → **HM 把 agent 定义(.md)+ 解好的资源 env 交给 AM 启动** → AM 起一个**常驻 agent**、分配**唯一子域名 + 访问 token** 返回 → 桌面客户端从 HM 拿到地址+token 后**直连 agent(SSE)对话**。HM 不在对话回路;agent 用模型走 HM `/v1/*`。
用户在 HM 网页台选「资源 + agent 模板」部署 → **HM 把 agent 定义(.md)+ 解好的资源 env 交给 AM 启动** → AM 起一个**常驻 agent**、分配**唯一子域名** 返回 → 桌面客户端从 HM 拿到地址后**直连 agent(A2A)对话**。HM 不在对话回路;agent 用模型走 HM `/v1/*`。
---
## 0.1 联调结果(2026-06-04 真实测试,账号在生产实跑)
| 接口 | 结果 | 需 AM |
|---|---|---|
| **创建** `POST /agents` | ✅ **通**:返回 `namespace` + `access_info.domain`,HM 已解析成 subdomain;agent 记录建立 | — |
| **删除** `DELETE /agents/{id}` | ❌ **HTTP 500**:`{"detail":"cannot access local variable 'd...'"}`(Python `UnboundLocalError`)。端点存在、id 正确,是**你们删除函数的 bug** | 🔴 修删除函数 |
| **停止** `POST /agents/{id}/stop` | ❌ **404**:你们没有这个端点 | 🔴 补 stop 端点(或确认只支持删除) |
| **取状态** `GET /agents/{id}` | ✅ 可达(HM 拉到 `status`) | 确认字段/路径 |
| **agent 直连(A2A)** | ⚠️ **连不上**:agent 一直 `Pending`、子域名 `*.taijiagnet.com` 外网 `/health` 超时/TLS 失败 | 🔴 排查 agent 为何不就绪 / 公网可达性 |
| **模型调用** | ✅ HM 现签的 `OPENAI_API_KEY` 实测能打通 `/v1`(gpt-5.4) | — |
> **AM 侧待办(三条阻断完整链路)**:① 修 `DELETE /agents/{id}` 的 500;② 提供 `stop` 端点;③ 让 agent 真正起来、子域名外网可达。HM 侧已就绪,这三条 OK 后端到端即通。
---
@@ -34,6 +49,7 @@ HM 用 `Authorization: Bearer <service_token>` 调 AM。统一响应信封建议
"AGENT_ROLE_NAME": "architect",
"AGENT_INSTRUCTION_TEXT": "---\nname: architect\n---\n<Agent_Prompt>...</Agent_Prompt>",
"OPENAI_BASE_URL": "https://code.xinghanlab.com/v1",
"OPENAI_API_KEY": "sk-xxxx",
"MODEL_NAME": "gpt-5.4",
"GIT_PROVIDER": "github", "GIT_REPO_URL": "...", "GIT_TOKEN": "…",
"MYSQL_HOST": "...", "MYSQL_PASSWORD": "…"
@@ -79,7 +95,10 @@ HM 把用户绑定的资源按**资源类型 + provider**解成固定 env 名(
| database | postgres | `POSTGRES_HOST` `POSTGRES_PORT` `POSTGRES_DATABASE` `POSTGRES_USER` · `POSTGRES_PASSWORD`(密) |
| storage | azure blob | `AZURE_BLOB_ACCOUNT_NAME` `AZURE_BLOB_CONTAINER` · `AZURE_BLOB_ACCOUNT_KEY`(密) |
另外随启动注入(模型网关):`OPENAI_BASE_URL`(= HM `/v1`)、`MODEL_NAME`(**默认 `gpt-5.4`**,可用 env `AGENT_RUNTIME_DEFAULT_MODEL` 覆盖;模板 frontmatter 里的 `opus/sonnet` 只是角色提示,**不会**当作网关模型传)。**`OPENAI_API_KEY` 不在启动时注入** —— 由客户端在 A2A 请求里带 `api_key`(你们文档 §7);后续若走 V2 解密路径再调整。
另外随启动注入(模型网关,3 个都传):
- `OPENAI_BASE_URL` = HM `/v1`(`https://code.xinghanlab.com/v1`)。
- `MODEL_NAME` = **默认 `gpt-5.4`**(可用 env `AGENT_RUNTIME_DEFAULT_MODEL` 覆盖;模板 frontmatter 里的 `opus/sonnet` 只是角色提示,**不会**当作网关模型传)。
- `OPENAI_API_KEY` = **HM 为该用户现签的一把 new-api sk(`sk-…`)**,计费到该用户账上;**删 agent 时自动吊销**。已实测:用它打 `/v1/chat/completions`(gpt-5.4)能真实返回、计入用户用量。客户端在 A2A 请求里也可带自己的 `api_key`(你们文档 §7);请求级会覆盖启动级。
- 缺失的可选字段不会出现在 env 里(agent 自行容错)。
- 同类型资源 HM 限制只挂一个(避免 env 名冲突)。
@@ -87,11 +106,12 @@ HM 把用户绑定的资源按**资源类型 + provider**解成固定 env 名(
---
## 3. 客户端 ↔ agent 直连(AM 的 agent 端要定义)
## 3. 客户端 ↔ agent 直连(A2A,已对齐你们文档)
- 客户端从 HM 拿到 `subdomain + access_token`,**直连 agent 子域名、SSE 双向通信**。HM 不在回路。
- **agent 端必须校验 access_token**(请求头携带);token 错/缺则拒绝(防公网裸奔)。
- **请由 AM 定义并回复 HM:** SSE 握手方式、token 放哪个请求头、消息/事件格式。HM 会把这段补进客户端文档 `heicode-desktop-client-api.md` §6。
客户端从 HM 拿到 `subdomain` 后**直连 agent**,走你们的 **A2A 协议**(`POST {subdomain}/message/send` 同步、`POST {subdomain}/message/stream` 流式、`GET {subdomain}/.well-known/agent.json`、`GET {subdomain}/health`)。HM 不在回路。HM 已据此写好客户端文档 `heicode-desktop-client-api.md` §6。
- **鉴权 = A2A 请求里的 `api_key`**(模型 sk-)。你们当前**不返回专属 access_token**,所以 HM 列表里 `access_token` 为空,客户端用 `api_key` 连。
- ⚠️ **安全缺口(请你们确认/补)**:agent 端 env 里挂着用户的 git token / db 密码 / blob key,工具能 `run_database_query`/`read_blob_text`。若子域名公网可达、且只要任一有效 sk 就能驱动它,**别的用户可经此读走该用户的资源**。需要**按用户隔离**(per-agent 专属令牌,或网络隔离 + 校验 api_key 属于该 agent 的所有者)。HM 侧规划后续提供 V2 解密接口(客户端加密、agent 解密拿 key)配合。
---