Add dedicated template agent contract doc
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
# Heicode Template Agent Runtime 对接文档
|
||||
|
||||
更新时间:2026-06-04
|
||||
|
||||
本文档只描述 **模板 Agent (`/agents`)** 这一条联调链路,适用于 Heicode Manager 创建常驻 A2A Agent、查询状态、停止、删除,以及客户端直连 Agent 的场景。
|
||||
|
||||
这不是 `/api/agent/sub-agile/*` 或 `/api/swarms/*` 的 sub-mode runtime 文档。
|
||||
如果你们对接的是普通 sub 模式 Runtime,请看 [HEICODE_API_INTEGRATION.md](/Users/mac/Projects/agent-manager/tools/agent-manager/docs/HEICODE_API_INTEGRATION.md)。
|
||||
|
||||
## 1. 场景说明
|
||||
|
||||
模板 Agent 的典型链路如下:
|
||||
|
||||
1. HM 调 `POST /agents` 创建一个模板 Agent。
|
||||
2. AM 返回 `runtime_id` / `agent_id` / `id`、`subdomain`、`status`。
|
||||
3. HM 轮询 `GET /agents/{agent_name}` 获取生命周期状态。
|
||||
4. 客户端拿到 `subdomain` 后,直连 Agent 的 A2A 接口:
|
||||
- `POST /message/send`
|
||||
- `POST /message/stream`
|
||||
- `GET /.well-known/agent.json`
|
||||
- `GET /health`
|
||||
5. 如需停止或删除:
|
||||
- `POST /agents/{agent_name}/stop`
|
||||
- `DELETE /agents/{agent_name}`
|
||||
|
||||
## 2. Agent Manager 生命周期接口
|
||||
|
||||
### 2.1 接口列表
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| `POST` | `/agents` | 创建模板 Agent |
|
||||
| `GET` | `/agents/{agent_name}` | 查询模板 Agent 生命周期状态 |
|
||||
| `POST` | `/agents/{agent_name}/stop` | 幂等停止模板 Agent |
|
||||
| `DELETE` | `/agents/{agent_name}` | 删除模板 Agent |
|
||||
| `GET` | `/agents/{agent_name}/status` | 查询详细 Pod/容器状态 |
|
||||
| `GET` | `/agents/{agent_name}/metrics` | 查询资源使用情况 |
|
||||
|
||||
### 2.2 创建接口
|
||||
|
||||
```http
|
||||
POST /agents
|
||||
```
|
||||
|
||||
最小请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "dep-b5fab27e9255",
|
||||
"template": "coding_a2a_agent",
|
||||
"framework": "A2A",
|
||||
"config": {
|
||||
"user_id": "22",
|
||||
"manager_deployment_id": "dep_b5fab27e9255",
|
||||
"callback_url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events"
|
||||
},
|
||||
"env": {
|
||||
"OPENAI_BASE_URL": "https://code.xinghanlab.com/v1",
|
||||
"OPENAI_API_KEY": "sk-xxxx",
|
||||
"MODEL_NAME": "gpt-5.4",
|
||||
"AGENT_ROLE_NAME": "architect",
|
||||
"AGENT_INSTRUCTION_TEXT": "# Role\nYou are architect",
|
||||
"AGENT_ACCESS_TOKEN": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"HEICODE_AGENT_ID": "dep-b5fab27e9255"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当前响应中,HM 重点关心这些字段:
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `runtime_id` | 当前等于 Agent 名称,可用于后续状态/停止/删除 |
|
||||
| `agent_id` | 当前等于 Agent 名称 |
|
||||
| `id` | 当前等于 Agent 名称 |
|
||||
| `status` | 当前生命周期状态 |
|
||||
| `runtime_status` | `status` 的兼容别名 |
|
||||
| `state` | `status` 的兼容别名 |
|
||||
| `subdomain` | 优先取 `access_info.domain`,否则回退到 `access_info.external_ip` |
|
||||
| `access_info` | 访问地址详情 |
|
||||
|
||||
响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "dep-b5fab27e9255",
|
||||
"runtime_id": "dep-b5fab27e9255",
|
||||
"agent_id": "dep-b5fab27e9255",
|
||||
"id": "dep-b5fab27e9255",
|
||||
"namespace": "agent-dep-b5fab27e9255",
|
||||
"status": "running",
|
||||
"runtime_status": "running",
|
||||
"state": "running",
|
||||
"framework": "A2A",
|
||||
"subdomain": "dep-b5fab27e9255.taijiagnet.com",
|
||||
"access_token": null,
|
||||
"access_info": {
|
||||
"domain": "dep-b5fab27e9255.taijiagnet.com",
|
||||
"domain_url": "http://dep-b5fab27e9255.taijiagnet.com",
|
||||
"external_ip": "20.212.121.126"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 状态接口
|
||||
|
||||
### 3.1 生命周期状态
|
||||
|
||||
```http
|
||||
GET /agents/{agent_name}
|
||||
```
|
||||
|
||||
这个接口给 HM 轮询用,返回平铺生命周期字段,便于直接解析:
|
||||
|
||||
```json
|
||||
{
|
||||
"runtime_id": "dep-b5fab27e9255",
|
||||
"agent_id": "dep-b5fab27e9255",
|
||||
"id": "dep-b5fab27e9255",
|
||||
"name": "dep-b5fab27e9255",
|
||||
"namespace": "agent-dep-b5fab27e9255",
|
||||
"status": "running",
|
||||
"runtime_status": "running",
|
||||
"state": "running",
|
||||
"framework": "A2A",
|
||||
"template": "coding_a2a_agent",
|
||||
"subdomain": "dep-b5fab27e9255.taijiagnet.com",
|
||||
"access_token": null,
|
||||
"access_info": {
|
||||
"domain": "dep-b5fab27e9255.taijiagnet.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当前 `status` / `runtime_status` / `state` 可能值:
|
||||
|
||||
- `pending`
|
||||
- `running`
|
||||
- `stopped`
|
||||
- `failed`
|
||||
|
||||
### 3.2 详细 Pod 状态
|
||||
|
||||
```http
|
||||
GET /agents/{agent_name}/status
|
||||
```
|
||||
|
||||
这个接口偏排障用途,除了生命周期状态外,还会返回:
|
||||
|
||||
- `health_status`
|
||||
- `containers`
|
||||
- `resources`
|
||||
- `conditions`
|
||||
- `access_info`
|
||||
|
||||
适合 AM / 运维 / 联调同学排查“为什么 agent 没 ready”这类问题。
|
||||
|
||||
### 3.3 资源指标
|
||||
|
||||
```http
|
||||
GET /agents/{agent_name}/metrics
|
||||
```
|
||||
|
||||
返回请求/限制和实时资源使用信息。
|
||||
|
||||
## 4. 停止与删除
|
||||
|
||||
### 4.1 停止
|
||||
|
||||
```http
|
||||
POST /agents/{agent_name}/stop
|
||||
```
|
||||
|
||||
响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "Agent dep-b5fab27e9255 已停止"
|
||||
}
|
||||
```
|
||||
|
||||
约定:
|
||||
|
||||
- 这是 **幂等** 的停止接口。
|
||||
- 停止时会删除当前运行 Pod,并把数据库状态收敛为 `stopped`。
|
||||
- 停止后仍可继续查询 `GET /agents/{agent_name}`。
|
||||
|
||||
### 4.2 删除
|
||||
|
||||
```http
|
||||
DELETE /agents/{agent_name}
|
||||
```
|
||||
|
||||
约定:
|
||||
|
||||
- 会清理 DNS、K8s namespace 和数据库记录。
|
||||
- 当前已修复旧版本里模板 Agent 删除时可能触发的 `UnboundLocalError` 500。
|
||||
|
||||
## 5. 客户端直连 Agent 的鉴权
|
||||
|
||||
模板 Agent 当前支持 HM 约定的 **本地校验** 访问鉴权。
|
||||
|
||||
### 5.1 规则
|
||||
|
||||
- HM 创建 Agent 时,会把 `AGENT_ACCESS_TOKEN` 注入到 Agent env。
|
||||
- 客户端访问 Agent 时,请把这把令牌放到请求头:
|
||||
|
||||
```http
|
||||
X-Agent-Access-Token: <AGENT_ACCESS_TOKEN>
|
||||
```
|
||||
|
||||
- Agent 本地使用常量时间比较校验:
|
||||
|
||||
```text
|
||||
X-Agent-Access-Token == AGENT_ACCESS_TOKEN
|
||||
```
|
||||
|
||||
- 命中则放行,不命中拒绝。
|
||||
|
||||
### 5.2 当前生效范围
|
||||
|
||||
以下 Agent 直连接口会做本地校验:
|
||||
|
||||
| 方法 | 路径 |
|
||||
|------|------|
|
||||
| `POST` | `/message/send` |
|
||||
| `POST` | `/message/stream` |
|
||||
| `GET` | `/tasks/{task_id}` |
|
||||
|
||||
### 5.3 返回约定
|
||||
|
||||
- 缺少 `X-Agent-Access-Token`:返回 `401`
|
||||
- `X-Agent-Access-Token` 不匹配:返回 `403`
|
||||
- 如果实例没有注入 `AGENT_ACCESS_TOKEN`:继续兼容放行
|
||||
|
||||
### 5.4 和模型 `api_key` 的区别
|
||||
|
||||
- `X-Agent-Access-Token`:控制“谁有权访问这个 agent”
|
||||
- A2A body 里的 `api_key`:控制“本次请求用谁的模型额度”
|
||||
|
||||
两者职责分离,不互相替代。
|
||||
|
||||
## 6. Agent 直连接口
|
||||
|
||||
客户端从 HM 拿到 `subdomain` 后,可以直连这些 Agent 接口:
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| `GET` | `/health` | 健康检查 |
|
||||
| `GET` | `/.well-known/agent.json` | A2A agent card |
|
||||
| `POST` | `/message/send` | 同步 A2A 调用 |
|
||||
| `POST` | `/message/stream` | 流式 A2A 调用 |
|
||||
| `GET` | `/tasks/{task_id}` | 查询任务状态 |
|
||||
|
||||
如果实例启用了访问鉴权,`/health` 和 `/.well-known/agent.json` 仍可访问;响应中会带:
|
||||
|
||||
- `auth_required`
|
||||
- `agent_id`
|
||||
- `authentication`(agent card 中)
|
||||
|
||||
## 7. 当前建议
|
||||
|
||||
1. HM 轮询状态时优先用 `GET /agents/{agent_name}`。
|
||||
2. 排障时再看 `GET /agents/{agent_name}/status`。
|
||||
3. 客户端直连前,先确认 HM 已拿到 `subdomain` 和 `access_token`。
|
||||
4. 若模板 Agent 对外公网暴露,建议始终注入 `AGENT_ACCESS_TOKEN`,不要依赖兼容放行。
|
||||
Reference in New Issue
Block a user