Files
deerflow-code/frontend-web/docs/multi-agent-backend-dev.md
T
2026-05-25 18:19:16 +08:00

18 KiB
Raw Blame History

多智能体圆桌研讨 · 后端开发文档

本文档面向需要维护或扩展「多智能体圆桌研讨」功能后端的开发者。前端 API 速查见 multi-agent-api.md、multi-agent-step1-api.md、multi-agent-step3-api.md;推荐弹窗见 recommend-agents-progress.md;前端实现见 multi-agent-frontend-dev.md。本文关注实现细节、协议帧、设计取舍。

源码内另有中文模块级注释(app/gateway/routers/intent.py、recommend.py、multi_agent.py 及 clarification_utils.py),与本文互为补充。


1. 功能定位与三步数据流

对应前端页面:/page/roundtable/planning(RoundtablePlanningPage.tsx)的三个步骤。

Step 1  任务意图理解
  POST /api/intent/init          → 建 thread,绑定内置 roundtable-intent
  POST /api/intent/stream (多轮)  → 澄清对话,终态 [INTENT_READY] + summary

        ↓ intentReady { objective, constraints, assumptions }

推荐弹窗(Step 1 → Step 2 之间,可选)
  POST /api/recommend/stream      → 从候选池选 2–6 个席位,[RECOMMEND_READY] + picks

        ↓ selectedAgents[]

Step 2  多智能体圆桌研讨
  POST /api/multi-agent/init (SSE) → 协调智能体 + 各席位 thread(席位列表由前端传入)
  POST /api/multi-agent/run/stream → leader 派活 / special 执行 / 澄清

        ↓ lastLeaderContent、各席位交付、hasConsensus

Step 3  最终方案展示
  GET  /api/threads/{tid}/artifacts     → 列出 outputs/ 产出文件
  GET  /api/threads/{tid}/artifacts/{path} → 预览或下载
  (总控结论、席位文本主要来自 Step 2 前端内存,一般不再调 run/stream)
步骤 前端 currentStep 专属 Router 内置 Agent
1 1 intent.py roundtable-intent(固定 id,复用)
1→2 推荐弹窗 recommend.py roundtable-recommender(每请求新建 thread)
2 2 multi_agent.py 协调智能体(每次新建)+ 用户选定的 roundtable-* 席位
3 3 artifacts.py(通用) 无新 agent

所有接口需 Authorization: Bearer <JWT>。Loopback 调用统一 trust_env=False,避免本机 HTTP_PROXY 把 127.0.0.1 指到不可达代理(症状:单次请求卡住 40s+)。


2. 涉及的后端文件

offline-backend-20260512/backend/
├── app/gateway/
│   ├── app.py                          # include_router: multi_agent, intent, recommend
│   └── routers/
│       ├── multi_agent.py              # Step 2:init(SSE) + run/stream
│       ├── intent.py                   # Step 1:init + stream
│       ├── recommend.py                # Step 1→2:推荐 stream
│       └── artifacts.py                # Step 3:列出/下载 thread 产出
└── .deer-flow/agents/
    ├── roundtable-intent/              # Step 1 任务理解(SOUL 含完整工作流,可不挂 Skill)
    ├── roundtable-recommender/        # 推荐智能体
    ├── roundtable-intelligence/       # 默认可选席位(6 个,前端可替换)
    ├── roundtable-environment/
    ├── roundtable-solution-design/
    ├── roundtable-risk-review/
    ├── roundtable-execution-plan/
    └── roundtable-summary/

内置 agent 注册:各 roundtable-* 目录通过 _sync_legacy_agents()(app/gateway/routers/agents.py)在下次 /api/agents 请求时 upsert 进 agents 表,user_id IS NULL 表示内置。

共享工具逻辑:packages/harness/deerflow/tools/builtins/clarification_utils.py 中的 resolve_allow_multiple() 被 intent.py、multi_agent.py 与 ClarificationMiddleware 共用,决定选项卡片默认单选还是多选。


3. 接口总览

方法 路径 步骤 用途
POST /api/intent/init 1 创建意图澄清 thread
POST /api/intent/stream 1 SSE,一轮用户对话
POST /api/recommend/stream 1→2 SSE,一次性推荐席位
POST /api/multi-agent/init 2 SSE,并行拉起席位 + 协调智能体
POST /api/multi-agent/run/stream 2 SSE,leader 或 special 一轮
GET /api/threads/{thread_id}/artifacts 3 列出该 thread 的 outputs 文件
GET /api/threads/{thread_id}/artifacts/{path} 3 预览/下载单个产出

字段级请求/响应见各 step 的 API 文档;下文只写后端实现语义。


4. Step 1:任务理解(intent.py)

4.1 定位

轻量包装 Lead Agent 运行时,固定跑内置 roundtable-intent。不做 broadcast、不派活;每轮用户消息对应一次 /stream。

4.2 POST /api/intent/init

  1. _create_thread() → LangGraph thread
  2. 返回固定 agent_id: "roundtable-intent"(不每次新建 agent)

与 Step 2 /init 的区别:无协调智能体、无 agent_names 列表。

4.3 POST /api/intent/stream

上游:_run_payload(agent_name=roundtable-intent, excluded_tools=[...]),硬排除 agent_orchestration、write_file、web_search 等,仅保留 ask_clarification 等澄清能力,防止模型写方案文档。

流式:透传 LangGraph SSE → 解析 _parse_last_messages(captured)。

终态帧判定顺序(重要):

  1. 先扫描全部 AI 消息中的 [INTENT_READY]\n\``json {...}```(正则 _INTENT_READY_PATTERN`)

    • 命中 → status: "done",summary 为解析后的 JSON,content 为含标记的整段文本
    • 优先于 ask_clarification,避免「已汇总仍被当成待澄清」
  2. 否则查最后一则带 tool_calls 的 AIMessage 是否含 ask_clarification

    • 命中 → status: "clarification",附带结构化字段供前端选项卡片:
{
  "status": "clarification",
  "content": "<引导语/前言>",
  "question": "...",
  "clarification_type": "missing_info",
  "clarification_context": "...",
  "options": ["..."],
  "allow_custom": true,
  "allow_multiple": false,
  "summary": null
}

allow_multiple 由 resolve_allow_multiple(cargs) 决定:默认单选(点击即发送);仅模型显式传 allow_multiple: true 时为多选。

  1. 否则 → status: "asking"(继续对话,无结构化澄清)

summary 形状(done 时):

{
  "objective": "一句话目标",
  "constraints": ["硬约束 1", "..."],
  "assumptions": ["可选假设"]
}

4.4 内置 Agent:roundtable-intent

  • 配置:.deer-flow/agents/roundtable-intent/config.yaml + SOUL.md
  • SOUL 内写清:工作流、ask_clarification 用法、[INTENT_READY] 格式、禁止派活/写文件
  • 可不配置 skills;若配置 Skill,SOUL 要求不得偏离澄清与结束协议

5. 推荐智能体(recommend.py,Step 1 → 2)

5.1 定位

无状态单次调用:每次请求内部 _create_thread(),不暴露 /init。前端传入 Step 1 的 intent + 过滤后的 candidates(排除 roundtable-intent、roundtable-recommender、历史 roundtable-coordinator-*)。

5.2 POST /api/recommend/stream

入参校验:

  • intent.objective 必填
  • candidates 非空,且至少一个有效 agent_id

Prompt 拼装(_build_prompt):把 objective/constraints/assumptions 与候选池格式化为一条 user message。

上游:roundtable-recommender,excluded_tools 含 ask_clarification、agent_orchestration 等(纯判断,不调工具)。

终态:

  • 解析 [RECOMMEND_READY]\n\``json {"picks":[{"agent_id","reason"},...]}````
  • _validate_picks():只保留候选池内的 id、去重、数量 clamp 到 2–6
  • 有效 picks ≥ 2 → status: "done",picks 有值
  • 否则 → status: "asking"(前端回退默认席位列表)
{
  "status": "done",
  "content": "<自然语言推荐理由>",
  "picks": [{"agent_id": "roundtable-risk-review", "reason": "..."}]
}

前端流式展示:自然语言理由与 JSON 由 [RECOMMEND_READY] 分界;TitleMiddleware 产生的标题增量会在客户端过滤,避免污染推荐理由区。


6. Step 2:多智能体研讨(multi_agent.py)

6.1 /init 内部流程(SSE,非一次性 JSON)

当前实现为 流式 init,便于前端按席位点亮 UI:

asyncio.as_completed(各席位 _prepare_sub_agent)
  每完成一个 → data: {"event":"seat_ready","agent_name","thread_id","display_name","description"}

协调智能体:
  POST /api/threads → coord_thread
  POST /api/agents(skills=[agent_orchestration],SOUL 动态拼入可调度列表)
  → data: {"event":"coordinator_ready","main_agent_name","thread_id"}

→ data: {"event":"init_done","main_agent_name","thread_ids":{...}}
失败 → data: {"event":"error","detail":"..."}

席位列表:由前端 agent_names 传入(推荐弹窗确认后的 2–6 个 id),不再写死 6 个。

协调智能体 SOUL(动态拼接)包含:只负责协调汇总、通过 agent_orchestration 派活、agent_name 必须用英文 id(不要用中文显示名)。

6.2 /run/stream — agent_type = "leader"

1. (可选)pre_broadcast:总控收到用户消息 → 广播到非自己的 thread
2. POST /api/threads/{coordinator}/runs/stream
   - excluded_tools: ["web_search"]
3. 透传 LangGraph 事件
4. 解析 messages → tool_calls

分支 A — ask_clarification:
  status: "clarification"
  + question / options / allow_multiple / clarification_type / clarification_context
  (空 dispatched 不等于共识,前端展示澄清卡片并暂停自动派活循环)

分支 B — 有 agent_orchestration 派活:
  并发 _broadcast 派活消息到相关 thread
  status: [["sub_agent_id", "task_text"], ...]

分支 C — 无 tool_calls:
  status: []   // 共识达成,content 为总控最终文本

6.3 /run/stream — agent_type = "special"

1. POST /api/threads/{sub}/runs/stream
   - excluded_tools: web_search, ask_clarification, present_files, view_image, agent_orchestration
2. 透传 + 解析最后 AI 文本
3. post_broadcast:子智能体完成交付 → 广播到非自己的 thread
4. status: "<完成提示字符串>" 或业务自定义;content 为交付正文;agent_name 为子 agent id

6.4 _broadcast 机制

async def _broadcast(client, base, headers, message, agent_threads, skip):
    targets = [tid for name, tid in agent_threads.items() if name not in skip]
    # 对每个 target: GET state → append human message → POST state

目的:各 thread 对话历史里保留「谁派活、谁交付」的群聊上下文。skip 通常含发起方与接收方,避免回声。

6.5 终态帧协议(leader / special / clarification)

前端 streamMultiAgent 用 isFinalStatusFrame() 识别:同时存在 status 与 content。

status 类型 含义
[["agent","task"],...] 派活列表;[] = 共识
"clarification" 总控追问,需用户回复后再 leader
"子智能体 X 完成..." special 完成(字符串)
"error" 异常

与 Step 1 的 clarification 帧字段对齐(question、options、allow_multiple 等),便于复用选项卡片组件。


7. Step 3:产出文件(artifacts.py,通用 Thread API)

Step 3 没有 单独的 multi_agent 路由;使用既有 artifacts 能力。

7.1 GET /api/threads/{thread_id}/artifacts

  • 鉴权:threads:read,owner 校验
  • 扫描:users/{user_id}/threads/{thread_id}/user-data/outputs/(collect_outputs_listing)
  • 目录不存在 → files: [](非 404)
{
  "thread_id": "...",
  "files": [
    {
      "path": "mnt/user-data/outputs/report.md",
      "name": "report.md",
      "size_bytes": 12480,
      "mime_type": "text/markdown",
      "modified_at": "2026-05-23T14:32:30.123Z"
    }
  ]
}

前端 listSessionArtifacts(threadId) 封装此接口;Step 3 可对协调 thread 与各席位 thread 分别拉取,合并为下载清单。

7.2 GET /api/threads/{thread_id}/artifacts/{path}

  • 虚拟路径前缀 mnt/user-data/outputs/...
  • 路径穿越防护;download=true 强制附件下载
  • HTML/XHTML/SVG 等 active content 始终按下载处理

总控结论、各席位最终段落:主要来自 Step 2 已缓存的 lastLeaderContent、step2RoundtableDialogues;无需为 Step 3 新增聚合接口(可选优化见 multi-agent-step3-api.md 中的 sessions/summary 草案)。


8. 内置席位 SOUL 设计要点

每个 roundtable-*(除 intent / recommender)遵循统一结构:角色定位、核心职责、输出风格(emoji + 简短结论)、边界(只产出本席位、等总控派活)。

席位 agent_id emoji 核心职责
情报收集 roundtable-intelligence 📢 同类案例 + 历史风险
环境评估 roundtable-environment 🌍 硬件容量 + 承载力
方案设计 roundtable-solution-design 📐 主备方案 + 关键路径
风险审查 roundtable-risk-review ⚠️ 合规红线 + 收敛建议
执行规划 roundtable-execution-plan 📅 里程碑 + 资源
总结陈述 roundtable-summary 🎤 归纳 + 冲突标记

子智能体不安装 agent_orchestration;仅协调智能体安装,保证单调度源。


9. 关键设计决策

9.1 HTTP loopback

三个 router 均通过 httpx 调本机 Gateway(127.0.0.1),复用鉴权与 LangGraph 路由,代价是额外 HTTP 开销;init 已用 asyncio.as_completed 并行化席位准备。

9.2 协调智能体每次新建

main_agent_name 形如 roundtable-coordinator-{timestamp36},会话隔离;长期会累积 agent 目录,需后续 GC 策略。

9.3 澄清协议统一

Step 1 与 Step 2 leader 均通过 ask_clarification + 终态 clarification 帧驱动选项卡片;[INTENT_READY] / 派活列表 / [] 各自表示阶段结束语义,互不混用。

9.4 选项单选默认

resolve_allow_multiple():未传则 false(单选、点击发送);仅显式 allow_multiple: true 时多选。降低模型把 missing_info 全标成多选导致 UX 混乱的概率。

9.5 SSE 末尾状态帧

LangGraph 原生流不含「派活结果 / 意图 summary / 推荐 picks」;各 router 在流末追加 JSON data: 帧,前端与 LangGraph 帧区分解析。


10. 性能特征

阶段 已做优化 典型耗时
Step 2 /init 席位 as_completed + 去掉 intro 广播 约 0.5–1.2s(视席位数)
LLM /run/stream — 数百 ms~数十秒(主因)
Step 1/推荐 单 thread,无 broadcast 与模型相关

仍存在的开销:GET /api/agents/{id} 触发 legacy sync 扫目录、GET/POST /state 广播等。未来可考虑 loopback 改内部函数调用(见原 B/D 优化项)。


11. 依赖与扩展点

11.1 agent_orchestration 技能

协调智能体派活依赖此技能;正则 _TOOL_CALL_PATTERN 从 tool 输出提取 agent_name 与 task。技能缺失时 leader 易变成「无 tool_calls → 空 status → 前端误判共识」。

11.2 模型

model 写入 run 的 context.model_name;前端可按席位覆盖 special 调用的模型。

11.3 新增席位

  1. .deer-flow/agents/roundtable-xxx/ 增加 config.yaml + SOUL.md
  2. 前端候选池 / 推荐逻辑纳入该 id
  3. Step 2 agent_names 传入即可 — multi_agent 路由无需改

11.4 新增 Step 1 工具

若需新工具,须同步修改 intent.py 的 excluded_tools 白名单逻辑(当前为黑名单,仅 ask_clarification 实际可用)。


12. 故障排查

现象 可能原因 排查
Step 1 一直有澄清、无法进入 Step 2 未产出 [INTENT_READY] 或终态被 clarification 覆盖 看 SOUL、最后一帧 status;确认 intent 先扫 READY
选项全是多选 旧前端默认 allow_multiple !== false 确认 allow_multiple 字段与 resolve_allow_multiple
Step 2 init SSE error 协调 agent 创建失败 / agent_orchestration 缺失 Network + 后端 multi_agent 日志
leader 立即 status: [] 未调用 orchestration 技能 换模型或加强 SOUL
推荐 picks 为空 未输出 [RECOMMEND_READY] 或 picks 不在候选池 看 recommend 终态帧
Step 3 无文件 子 agent 未写 outputs GET .../artifacts 对子 thread_id 逐个查

日志关键字

grep "intent stream" .runtime/logs/*.log
grep "multi_agent\|multi-agent" .runtime/logs/*.log
grep "recommend stream" .runtime/logs/*.log
grep "dispatch failed" .runtime/logs/*.log

13. 测试建议

backend/tests/test_intent.py          # init、INTENT_READY、clarification 优先级
backend/tests/test_recommend.py       # picks 校验、候选池过滤
backend/tests/test_multi_agent.py     # init SSE 事件、leader/special 终态、clarification

可用 httpx.MockTransport 模拟 loopback,不依赖真实 Gateway。


14. 路径速查

资源 路径
Step 1 路由 offline-backend-20260512/backend/app/gateway/routers/intent.py
推荐路由 offline-backend-20260512/backend/app/gateway/routers/recommend.py
Step 2 路由 offline-backend-20260512/backend/app/gateway/routers/multi_agent.py
Step 3 列出/下载 offline-backend-20260512/backend/app/gateway/routers/artifacts.py
路由注册 offline-backend-20260512/backend/app/gateway/app.py
澄清单选/多选 packages/harness/deerflow/tools/builtins/clarification_utils.py
任务理解 Agent .deer-flow/agents/roundtable-intent/
推荐 Agent .deer-flow/agents/roundtable-recommender/
圆桌席位 .deer-flow/agents/roundtable-*/
前端 Step 1 API frontend-web/src/roundtable-planning/api/intent.ts
前端推荐 API frontend-web/src/roundtable-planning/api/recommend.ts
前端 Step 2 API frontend-web/src/roundtable-planning/api/multi-agent.ts
前端页面 frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx
API 速查 frontend-web/docs/multi-agent-api.md
Step 1 API 说明 frontend-web/docs/multi-agent-step1-api.md
Step 3 API 说明 frontend-web/docs/multi-agent-step3-api.md