跳转到内容

多 Agent 编排:Manager、Handoff、并行与群聊

决定要拆多个 Agent 之后,最容易做错的一步是先给角色起名。更该先画出来的是:谁还在和用户说话,谁能决定下一步,谁有资格宣布任务结束。

设想这样一个场景:研究 Worker 找到三条来源,写作 Worker 生成草稿,验证 Worker 报告一处事实冲突。结果回到哪里?谁裁决冲突?是重试其中一个节点,还是让整组 Agent 从头再聊?这些问题合起来就是编排。Manager、Handoff、并行、群聊看起来都能组织多个角色,实际却把上下文、责任和失败放在完全不同的位置。

先画控制权,再写角色 Prompt。 如果画不出哪个节点拥有会话、状态和终态,系统的真实控制流就还藏在模型对话里。

一个可运行的多 Agent 系统至少包含五类对象:

Task:原始目标和完成条件
State:当前事实、产物、预算、版本
Agent:在局部上下文中作出决策
Message:跨边界传递的结构化信息
Orchestrator:决定谁在何时运行

角色说明只回答“这个 Agent 应该做什么”。编排还必须回答:输入从哪里来、允许读取哪些状态、输出必须满足什么 Schema、谁接受或拒绝结果、超时和重复怎样处理、整个任务由谁宣布结束。

这些问题一旦留给自然语言临场协商,控制流就藏进了模型对话,既难重放也难测试。先写清输入、输出和 Owner,才有资格讨论“几个角色比较聪明”。

Manager 模式中,一个主 Agent 保留用户对话和全局任务所有权。专业 Agent 被当作工具或 Worker 调用,结果返回 Manager,再由它决定下一步。

User -> Manager -> Researcher -> Manager
-> Coder -> Manager -> User
-> Verifier -> Manager

OpenAI Agents SDK 把这种方式称为“Agents as tools”:中心 Agent 调用专业 Agent,但不交出会话控制权。[1]

图 1 适合看清 Manager 模式的两面:所有分支都会回到中心,所以它最容易统一口径,也最容易变成上下文瓶颈。

  • 用户始终面对一个统一入口;
  • 全局政策和语气容易集中管理;
  • 子任务可以按需调用;
  • 汇总与最终责任清楚;
  • 适合一个任务需要多个领域专家的场景。
  • Manager 容易成为上下文和延迟瓶颈;
  • 专业结果经过二次总结可能失真;
  • 中心节点一旦误判,所有 Worker 都被错误调度;
  • 如果 Manager 看见所有原始材料,上下文隔离形同虚设。

所以 Worker 最好返回证据卡,而不是一大段聊天记录:

{
"claim": "当前稳定规范为 2025-11-25",
"evidence_url": "https://...",
"confidence": "high",
"unresolved": []
}

OpenAI Agents SDK GitHub 页面

图 1:OpenAI Agents SDK 用 Agent、Tool、Handoff、Session 和 Trace 等少量原语表达编排。来源见文末。

Handoff 比“调用另一个 Agent”更进一步:当前 Agent 把后续会话交给专业 Agent,接收者成为新的控制者。典型例子是客服分流,入口 Agent 判断用户需要售后,交给售后 Agent,售后 Agent 从此直接追问订单号、解释规则并处理流程。

User <-> Triage Agent
|
+-- handoff --> Billing Agent <-> User
  • 专业 Agent 需要直接与用户多轮澄清;
  • 后续流程长期处在同一领域;
  • 转交边界清晰,例如销售、售后、技术支持;
  • 接收者应拥有不同工具和政策。

Handoff 最容易丢的是上下文和责任。交接包至少应包含:

  • 任务目标与用户已确认事项;
  • 已收集的事实和证据来源;
  • 已执行动作及其副作用;
  • 当前权限、预算和期限;
  • 未解决问题;
  • 回退或升级路径。

有个诱惑是直接把完整聊天历史塞给接收者,这不可取。完整历史往往包含无关信息、过期指令和不应跨域传播的敏感数据。交接包要足够让接收者工作,也要足够小,才能守住原来的权限边界。

并行适合相互独立的子问题。Orchestrator 先把任务分解,再同时启动 Worker,最后由 Aggregator 合并。

-> Worker A -\
Task -> Decompose -> Worker B --> Aggregate -> Verify
-> Worker C -/

并行主要降低墙钟时间和隔离上下文,它并不自动降低费用:三个 Worker 仍然会产生三份计算量。只有输入和输出都相互独立的任务,才值得同时发出去。

  • 每个 Worker 有唯一 task_id
  • 输入包含明确范围和输出 Schema;
  • Worker 不共享可变状态,或通过版本控制写入;
  • 超时可以单独标记,不拖死全部分支;
  • Aggregator 能表示“缺一项”而不是假装完整;
  • 冲突结论保留来源,由验证器或规则裁决。

对于代码修改,多个 Worker 不应直接写同一工作区。更安全的方式是独立分支或工作树,提交不可变 Diff,再由唯一协调者串行接收。

Group Chat 通常让多个 Agent 围绕同一问题轮流发言,由调度器选择下一位。Microsoft Agent Framework 提供 Group Chat、Handoff、Concurrent、Sequential 和 Magentic 等编排模式。[2]

群聊适合需要观点探索、方案评审或角色协商的任务,但它常被误用成“多说几遍就更可靠”。

  • 角色拥有不同信息、工具或评价函数;
  • 发言轮次有终止条件;
  • 决策不靠简单多数表决;
  • 关键主张要落到外部证据;
  • 反对意见有固定处理规则;
  • 最终 Owner 明确。

所有角色都使用同一模型、同一上下文和同一提示、只换角色名的时候,它们的错误高度相关,三个 Agent 同意并不等于三个独立证据一致。群聊要有轮次上限和反对意见的处理规则,否则很容易从协作退化成循环。

CAMEL 的 RolePlaying、Societies 和 Workforce 把角色、协调者、任务分解与 Critic 当作研究和工程对象。[3][4] 这类设计更适合探索协作机制,不代表每个生产任务都需要开放式讨论。

CAMEL GitHub 页面

图 3:CAMEL 把 Agent Societies 和多 Agent 协作作为核心研究方向。来源见文末。

复杂业务往往混合前几种模式,这时可以把编排显式化为图或事件流。LangGraph 以共享 State 和节点/边表达控制流,支持检查点、人工介入和长时运行。[5]

LangGraph GitHub 页面

图 2:LangGraph 的核心抽象是带状态的图,不是预设一组拟人角色。来源见文末。

另一种思路是黑板架构:多个 Worker 不直接相互聊天,而是读取任务板、提交结构化产物,协调器根据状态决定下一项工作。事件驱动 Flow 则由“资料已齐全”“审批已通过”“测试失败”这类事件触发节点。这两种做法都让控制流能被检查、重放和测试,不必从聊天顺序里推断发生了什么。

模式 控制权 最适合 主要风险
Manager 始终在中心 Agent 多领域协助、统一回答 中心瓶颈、摘要失真
Handoff 转移到接收 Agent 分流后的长期专业对话 上下文与责任丢失
Parallel 编排器分发,汇总器接收 独立研究、批量检查 冲突、资源峰值、缺失分支
Group Chat 调度器轮转或角色协商 观点探索、评审 相关错误、无休止讨论

真实系统通常组合使用:入口先 Handoff 给领域 Manager,Manager 再并行调用检索 Worker,最后把高风险决定交给独立审批节点。

每次跨 Agent 传递内容时,至少区分四类信息:

  1. 任务事实:用户目标、输入数据、业务约束;
  2. 中间产物:检索结果、代码 Diff、草稿;
  3. 控制信息:预算、截止时间、重试次数、状态版本;
  4. 信任信息:内容来源、是否已验证、允许的用途。

一个来自网页的字符串不能因为进入了 Agent 消息就自动升级成系统指令,一个 Worker 的“我已完成”也不能直接成为终态证据。最小交接格式可以是:

{
"task_id": "research-03",
"artifact_ref": "sha256:...",
"claims": [],
"evidence": [],
"status": "ready_for_review",
"permissions_used": ["web.read"],
"next_owner": "editor"
}

结构化交接让消息能做 Schema 校验、版本检查和权限审计,也让后续 Worker 知道哪些内容只是外部材料、哪些结论已经经过验证。

多 Agent 常见的死循环是:Worker 说资料不足,Manager 让它继续;Worker 返回相同结果,Manager 再次重试。

每个节点至少需要最大尝试次数、绝对或相对截止时间、可重试错误集合、幂等键、局部失败是否允许整体降级,以及明确的 success / failed / needs_human / partial 终态。

重试应该针对可恢复的节点,而不是让全体角色从头复述。产生副作用的工具还要先查询真实状态,避免重复发送、扣款或提交。

从本讲目录执行:

Terminal window
python3 experiments/orchestration_patterns.py

orchestration_patterns.py 使用 Python 标准库 ThreadPoolExecutor 同时运行三个 Worker:课程、协议和可靠性。每个 Worker 只保留自己需要的私有上下文,Manager 只接收结构化汇总。

每个 Worker 保留 100 单位私有上下文,Manager 保留 150 单位共享上下文,结果估算总量为 450;如果三个 Worker 都复制 400 单位完整共享历史,则为 1200。

{
"pattern": "parallel_workers_with_manager",
"estimated_total_context_units": 450,
"naive_shared_history_units": 1200,
"terminal": "success"
}

完整运行结果见 experiment-result.json4501200 都是教学估算,不是 Token Benchmark,它们只是在相同假设下显示“完整历史复制给每个 Worker”会怎样放大上下文。实验想说明的是:并行本身不保证节省上下文,私有上下文加结构化汇总才产生隔离收益。

把实验中的一个 Worker 改成超时失败,再实现两种策略:

  1. fail_fast:任一关键 Worker 失败,整体进入 failed
  2. allow_partial:保留成功分支,输出缺失清单,进入 partial

然后给每个 Worker 增加 task_idattempt,验证相同任务重试不会生成两个汇总项。最后故意让两个 Worker 对同一事实给出相反结论,要求 Aggregator 保留双方证据,而不是自行拼成一个模糊答案。这组练习能直接暴露编排系统里最麻烦的三件事:局部失败、重复执行和结论冲突。

Manager 解决统一所有权,Handoff 解决专业会话接管,并行解决独立子任务的时延,群聊解决受约束的观点交互,图与事件流把复杂组合变成可检查状态。

选择模式时先问控制权在哪里、上下文怎样裁剪、失败由谁承担。不要从“想要几个角色”开始,先找最小可行的交接边界,再决定用哪种编排原语。

下一讲讨论工具生态的标准接口 MCP。它不解决多 Agent 协作,管的是应用怎样以一致方式发现、读取和调用外部能力。


[1] OpenAI, Agent orchestration. https://openai.github.io/openai-agents-python/multi_agent/

[2] Microsoft, Agent Framework Orchestrations. https://learn.microsoft.com/en-us/agent-framework/workflows/orchestrations/

[3] CAMEL, Societies. https://docs.camel-ai.org/key_modules/societies

[4] CAMEL, Workforce. https://docs.camel-ai.org/key_modules/workforce

[5] LangChain, Multi-agent systems. https://docs.langchain.com/oss/python/langchain/multi-agent

[6] CrewAI, Flows. https://docs.crewai.com/concepts/flows