9.6 KiB
多智能体协调 API 接口文档
后端路由:offline-backend-20260512/backend/app/gateway/routers/multi_agent.py
路由前缀:/api/multi-agent
概览
提供一个"总控 + 多个子智能体"的协调编排接口。
- 总控(leader) 智能体:通过
agent_orchestration技能给子智能体派活 - 子智能体(special):执行被派到的具体任务,完成后把交付内容广播给其他线程
调用方按下面顺序使用:
- 调
POST /api/multi-agent/init一次性创建协调智能体 + 给每个子智能体建thread,拿到thread_ids映射 - 客户端把
thread_ids保管好,后续每次调POST /api/multi-agent/run/stream时回传 - 先调用
agent_type="leader"拿派活清单,再针对清单里每个子智能体调用agent_type="special"
1. 初始化多智能体集群
POST /api/multi-agent/init
创建协调智能体并为列表中的每个子智能体建立独立的 thread,同时把"职责说明"广播到所有子智能体线程作为初始上下文。
请求体
{
"agent_names": ["taiwan-intelligence-gathering-agent", "us-intelligence-gathering-agent"],
"main_agent_name": "main-controller",
"model": "deepseek-chat"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
agent_names |
string[] |
是 | 已有子智能体的 id 列表(kebab-case,区分大小写不敏感,自动转小写) |
main_agent_name |
string |
否 | 要创建的协调智能体名,默认 main-agent。重名时会复用已存在的同名智能体 |
model |
string |
否 | 协调智能体使用的模型名。不传则用后端默认模型 |
响应(200)
{
"status": "success",
"main_agent_name": "main-controller",
"thread_ids": {
"main-controller": "thread-uuid-xxx",
"taiwan-intelligence-gathering-agent": "thread-uuid-yyy",
"us-intelligence-gathering-agent": "thread-uuid-zzz"
}
}
thread_ids 是一个 {agent_name: thread_id} 字典。前端必须把这个对象完整保管下来,后续调用 stream 接口需要原样回传。
错误
| 状态码 | 触发条件 |
|---|---|
400 |
agent_names 为空 |
401 |
未携带 Authorization 头 |
500 |
协调智能体创建失败且不是"已存在"错误 |
2. 流式调度
POST /api/multi-agent/run/stream
通过 SSE(Server-Sent Events)流式驱动一个 leader 或 special 智能体跑一轮对话。
请求体
{
"agent_type": "leader",
"d_agent_thread_id": {
"main-controller": "thread-uuid-xxx",
"taiwan-intelligence-gathering-agent": "thread-uuid-yyy"
},
"agent_name": "main-controller",
"new_message": "请分析特朗普的支持率",
"skill_stop_names": [],
"model": "deepseek-chat"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
agent_type |
"leader" | "special" |
否 | 默认 leader。leader 调用协调智能体,special 调用子智能体 |
d_agent_thread_id |
object |
是 | 由 /init 接口返回的 thread_ids 映射,原样回传 |
agent_name |
string |
是 | 本轮要驱动的智能体名(必须存在于 d_agent_thread_id 中) |
new_message |
string |
是 | 这轮发给智能体的用户消息 |
skill_stop_names |
string[] |
否 | 触发后中断执行的技能名列表(默认空) |
model |
string |
否 | 本轮 LLM 模型名,默认 deepseek-chat |
响应
Content-Type: text/event-stream 的 SSE 长连接,按到达顺序产出多种数据:
a. 透传上游事件
原样转发底层 POST /api/threads/{thread_id}/runs/stream 的事件帧(LangGraph 协议),包含 event:、data: 等行。前端按 LangGraph SDK 既有方式渲染即可。
b. 最后一帧:调度状态
流结束前会额外产出一帧 data: 行,结构因 agent_type 而异:
agent_type == "leader":
data: {"status": [["us-intelligence-gathering-agent", "收集美国民众对特朗普的看法"], ["taiwan-intelligence-gathering-agent", "..."]]}
status 是一个 [agent_name, task_text] 二元组数组,代表协调智能体本轮派出去的任务清单。前端拿到后应当对每个元素再调用一次本接口(agent_type="special")来执行子智能体。如果数组为空,说明 leader 觉得已有信息足够,不再派活,可以直接展示 leader 的最终文本回答。
agent_type == "special":
data: {"status": "子智能体xxx完成yyy工作"}
代表子智能体完成本轮工作并已把交付内容广播给其他线程。
副作用(重要)
- leader 调用:自动把"总控智能体收到用户消息: …"广播到所有非自己的线程;派活后再把"总控智能体给 X 派活, 内容为: …"广播到所有非派活双方的线程
- special 调用:完成后把"子智能体 X 完成 Y 工作, 交付内容为: …"广播到所有非自己的线程
这意味着每个线程的对话历史里会逐步累积出全局上下文,无需前端再做合并。
错误
| 状态码 | 触发条件 |
|---|---|
400 |
agent_name 缺失或未在 d_agent_thread_id 中 |
401 |
未携带 Authorization 头 |
502 |
上游 runs/stream 返回非 200 / SSE 解析失败 |
3. 前端调用流程示例
// 1. 拿 token
const loginResp = await fetch("/api/v1/auth/login/username", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username: "yourname" }),
});
const { access_token } = await loginResp.json();
const authHeaders = {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
};
// 2. 初始化
const initResp = await fetch("/api/multi-agent/init", {
method: "POST",
headers: authHeaders,
body: JSON.stringify({
agent_names: [
"taiwan-intelligence-gathering-agent",
"us-intelligence-gathering-agent",
],
main_agent_name: "main-controller",
model: "deepseek-chat",
}),
});
const { thread_ids } = await initResp.json();
// 3. 流式调用 leader
async function streamLeader(message: string, model = "deepseek-chat") {
const resp = await fetch("/api/multi-agent/run/stream", {
method: "POST",
headers: authHeaders,
body: JSON.stringify({
agent_type: "leader",
d_agent_thread_id: thread_ids,
agent_name: "main-controller",
new_message: message,
skill_stop_names: [],
model,
}),
});
const reader = resp.body!.getReader();
const decoder = new TextDecoder();
let buf = "";
let dispatched: [string, string][] = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
const lines = buf.split("\n");
buf = lines.pop() ?? "";
for (const line of lines) {
if (!line.startsWith("data:")) continue;
try {
const payload = JSON.parse(line.slice(5).trim());
if (Array.isArray(payload.status)) {
dispatched = payload.status;
}
// 其余事件按 LangGraph SDK 协议自行渲染
} catch {
/* 非 JSON 帧,可忽略或交给现有渲染器 */
}
}
}
return dispatched;
}
// 4. 对派活清单逐个调用 special
async function streamSpecial(agentName: string, task: string, model = "deepseek-chat") {
return fetch("/api/multi-agent/run/stream", {
method: "POST",
headers: authHeaders,
body: JSON.stringify({
agent_type: "special",
d_agent_thread_id: thread_ids,
agent_name: agentName,
new_message: task,
skill_stop_names: [],
model,
}),
});
// 同样按 SSE 解析
}
// 5. 编排:先 leader 派活 → 依次执行 special → 再让 leader 汇总
const dispatched = await streamLeader("请分析特朗普的支持率");
for (const [agentName, task] of dispatched) {
await streamSpecial(agentName, task);
}
const next = await streamLeader("根据上面收集到的信息出最终结论");
// 当 leader 返回 status: [] 时,意味着汇报完毕,可结束循环
4. 注意事项
model字段的取值:必须是后端config.yaml中models[]已配置的模型名(如deepseek-chat、glm-4、gpt-4o等)。传错会导致上游 502thread_ids必须每次回传:后端不存储这个映射,是无状态接口- 协调智能体必须装有
agent_orchestration技能:/init创建时会自动指定skills=["agent_orchestration"]。后端skills/目录里必须存在该技能定义,否则 leader 无法派活 - 同名协调智能体冲突:
main_agent_name重名时后端不会报错("already exists" 走兼容分支),会复用既有智能体——所以同一个用户多次 init 用同一个名字是安全的,但 SOUL 不会被覆盖 - SSE 断连:本接口底层
on_disconnect: "continue",断连后上游 run 会继续跑到结束(不会取消) - 并发广播:广播消息使用
asyncio.gather并发更新所有线程 state,性能上不会随子智能体数线性变慢
5. 相关接口(底层依赖)
本接口内部转发以下 Gateway 原生接口,了解细节可查:
| 接口 | 路由 | 用途 |
|---|---|---|
| 创建 thread | POST /api/threads |
为每个智能体建立独立会话 |
| 读 thread state | GET /api/threads/{id}/state |
广播前取当前消息列表 |
| 写 thread state | POST /api/threads/{id}/state |
把广播消息追加到 messages |
| 取 agent 详情 | GET /api/agents/{id} |
init 时读取子智能体的 name/description |
| 建 agent | POST /api/agents |
init 时创建协调智能体 |
| 流式 run | POST /api/threads/{id}/runs/stream |
leader/special 的实际执行 |