如何设计多 Agent 的协作与动态切换机制?
多 Agent 系统真正难的不是“多几个角色”,而是让这些角色有秩序地传信息、换任务、收敛结果。 开篇:多 Agent 协作不是“几个 Prompt 互相调用” 很多人讲 Multi-Agent,容易停留在“一个负责搜索,一个负责写代码,一
多 Agent 系统真正难的不是“多几个角色”,而是让这些角色有秩序地传信息、换任务、收敛结果。
开篇:多 Agent 协作不是“几个 Prompt 互相调用”
很多人讲 Multi-Agent,容易停留在“一个负责搜索,一个负责写代码,一个负责评审”这一层。分工当然重要,但分工只解决了“谁来做什么”。真正落到工程里,还有两个更关键的问题:一个 Agent 做完之后,结果怎么给下一个 Agent?当前任务进展发生变化后,下一步又该由谁接棒?
这两个问题分别对应“协作机制”和“切换机制”。协作机制解决信息流,切换机制解决控制流。信息流设计不好,Agent 之间会互相污染、互相覆盖;控制流设计不好,系统会乱跳、死循环、成本失控。
一、稳定系统一定是混合设计
多 Agent 协作可以拆成两层:
第一层是 Agent 之间怎么传信息。常见方式有消息传递和共享状态。消息传递像发邮件,发送方只负责发布结果,下游自己订阅;共享状态像共享白板,所有 Agent 都围绕同一个 State 读写任务进度和中间结果。
第二层是下一步交给谁。常见方式有静态路由、动态路由和 Handoff。静态路由靠规则,稳定、便宜、可预测;动态路由靠 LLM 判断,灵活但成本更高;Handoff 则是当前 Agent 自己决定把任务交给谁,像接力赛一样。
工程上最稳的答案通常不是二选一,而是混合:主流程用静态路由,保证可控;边缘情况交给 LLM 动态判断;强依赖步骤用共享状态;弱耦合、并行任务用消息传递。
二、消息传递,适合低耦合和并行任务
消息传递的核心思想是:Agent 不直接调用下游 Agent,而是把自己的结果发布出去。谁需要这个结果,谁自己去订阅。它像公司里的邮件系统,也像事件驱动架构里的消息队列。
例如,一个“资料收集 Agent”完成检索后,把 evidence_ready 事件发到队列里。写作 Agent、审校 Agent、引用检查 Agent 都可以按需订阅这个事件。资料收集 Agent 不需要知道后面到底有几个消费者,这就是解耦。
这种方式适合并行调研、批量内容生成、异步工具调用、长耗时任务。缺点是系统复杂度更高,要处理消息顺序、幂等、重试、超时、死信队列和结果汇总。
三、共享状态,适合强依赖流水线
共享状态的核心思想是:多个 Agent 读写同一个 State。前一个 Agent 把结果写入 State,后一个 Agent 直接从 State 里读取。它像团队项目里的共享白板,上面记录原始需求、当前步骤、关键产出、错误信息和最终结果。
LangGraph 这类图工作流框架就很适合这种模式:每个节点执行完,返回一段增量更新,框架把它合并进全局状态。这样 Orchestrator 可以清楚看到任务进度,也方便恢复、重试和审计。
但共享状态不能粗暴地把所有东西都塞进去。生产环境里,通常要区分全局状态和局部状态。全局状态只放所有 Agent 都需要的事实,局部状态放每个 Agent 自己的草稿、候选结果和中间过程。
四、状态管理:多 Agent 最容易出 Bug 的地方
多 Agent 系统里,共享状态最容易出现三个问题:覆盖、污染和读到半成品。覆盖是 Agent A 写入的结果被 Agent B 改掉;污染是某个 Agent 的临时草稿进入全局上下文;半成品是下游 Agent 读到了尚未完成的状态。
比较稳的做法是“只追加,不覆盖”。每个 Agent 不直接修改已有字段,而是追加一条事件。事件里记录 agent_name、输入摘要、输出、置信度、错误、时间戳和 trace_id。这样就算结果错了,也能追溯是谁在什么时候写进去的。
五、静态路由,便宜、稳定、好调试
静态路由就是提前写好规则。比如任务类型是 search,就交给 Researcher Agent;代码已经生成完,就交给 Reviewer Agent;检测到高风险操作,就交给 Human Review。
静态路由最大的好处是稳定。你能预测系统会走哪条路径,日志也容易排查。缺点是它只覆盖你预先想到的情况,一旦用户问题很模糊、任务状态异常、多个 Agent 都可能处理,规则就会变得越来越复杂。
六、动态路由,灵活但不能滥用
动态路由是让 LLM 判断下一步该调用哪个 Agent。Orchestrator 把当前任务、已经完成的步骤、可用 Agent 列表和每个 Agent 的职责说明传给模型,让模型返回 selected_agent。
动态路由适合边缘情况和复杂意图,但它有三类成本:第一,多一次 LLM 调用,延迟和费用增加;第二,LLM 可能选错 Agent,行为不可预测;第三,路由决策很难像规则那样完全解释。
七、推荐做法:静态路由打底,动态路由兜边界
一个好用的多 Agent 系统,不应该一上来就把所有路由都交给 LLM。更稳的做法是:先用规则覆盖 80% 高频路径,只有规则无法判断时,才进入 LLM Router。
LLM Router 返回结果后,还必须做白名单校验。比如它返回了一个不存在的 Agent,或者把金融任务交给了写作 Agent,系统不能直接执行,而应该回到 fallback Agent 或要求人工确认。
def route_task(task, state, available_agents):
"""静态规则优先,LLM Router 兜底。"""
# 1. 高频路径:直接走规则,便宜且稳定
if task.type == "search":
return "researcher"
if state.get("code_status") == "generated":
return "reviewer"
if state.get("risk_level") == "high":
return "human_review"
# 2. 低频边缘情况:交给 LLM 判断
selected = llm_router(task, state, available_agents)
# 3. 路由结果必须校验,不能模型说什么就执行什么
if selected not in available_agents:
return "fallback_agent"
return selected八、Handoff:Agent 之间的接力棒
Handoff 是一种更去中心化的切换方式。不是由一个中央 Orchestrator 决定下一步找谁,而是当前 Agent 自己判断:“我的职责完成了,接下来应该交给哪个 Agent。”
Handoff 适合职责边界非常清楚的场景。例如客服系统里,Triage Agent 判断用户要退款,就把控制权交给 Refund Agent;Refund Agent 发现涉及异常金额,再交给 Human Review。
OpenAI Agents SDK 把 handoff 表达为模型可选择的工具:如果有一个 Refund Agent,模型看到的可能是 transfer_to_refund_agent 这样的工具。这个设计让“转交控制权”变成可审计、可限制、可插入回调的动作。
from agents import Agent, handoff
billing_agent = Agent(
name="Billing Agent",
instructions="只处理账单、扣费、发票相关问题。"
)
refund_agent = Agent(
name="Refund Agent",
instructions="只处理退款申请、退款状态、退款失败原因。"
)
triage_agent = Agent(
name="Triage Agent",
instructions="判断用户问题类型,并在必要时转交给专业 Agent。",
handoffs=[billing_agent, handoff(refund_agent)]
)九、Handoff 的最大风险:循环交接
Handoff 很灵活,但它也最容易失控。Agent A 觉得该交给 Agent B,Agent B 又觉得不属于自己,再交给 Agent C,最后 Agent C 又交回 Agent A,就形成了死循环。
所以 Handoff 必须加护栏:记录 visited_agents,限制 max_handoff_steps,每次交接必须写 handoff_reason,超过次数后回到 Orchestrator 或人工确认。没有这些机制,Handoff 只是“看起来优雅”,实际很难上线。
def safe_handoff(current_agent, next_agent, state):
visited = state.setdefault("visited_agents", [])
max_steps = state.get("max_handoff_steps", 5)
if next_agent in visited:
return "orchestrator", "检测到重复交接,回到中央调度器"
if len(visited) >= max_steps:
return "human_review", "超过最大交接次数,转人工复核"
visited.append(next_agent)
state["handoff_trace"].append({
"from": current_agent,
"to": next_agent,
"reason": state.get("handoff_reason", "未说明"),
})
return next_agent, "handoff_ok"十、MCP 与 A2A:多 Agent 协作走向协议化
当系统从“一个应用里的多个 Agent”走向“不同团队、不同框架、不同供应商的 Agent 协作”时,光靠自定义函数调用就不够了。这时要区分两个协议层的问题。
MCP 主要解决 Agent 如何连接外部工具、数据源和工作流。它更像 AI 应用的“USB-C 接口”,让 Agent 可以用统一方式访问数据库、搜索、文件系统、业务 API。
A2A 主要解决 Agent 与 Agent 之间如何互相发现、委托任务、交换结果。简单说:MCP 是 Agent-to-Tool,A2A 是 Agent-to-Agent。
十一、生产级架构:把不确定性关进平台层
生产级多 Agent 系统不要让每个 Agent 随意调用、随意写状态、随意交接。更好的架构是:平台层统一负责身份、权限、路由、状态、消息、日志、成本预算和错误兜底。
Agent 本身只负责专业能力,比如检索、写代码、评审、生成报告。它们不应该直接拿到所有工具权限,也不应该能任意修改全局状态。所有关键动作都要经过 Orchestrator 或平台层记录。
class AgentState(dict):
"""生产环境建议把状态当成事件流,而不是随意可改的字典。"""
def append_event(self, agent_name, event_type, payload, trace_id):
self.setdefault("events", []).append({
"agent": agent_name,
"type": event_type,
"payload": payload,
"trace_id": trace_id,
})
def latest(self, event_type):
events = [e for e in self.get("events", []) if e["type"] == event_type]
return events[-1] if events else None十二、怎么选:看依赖、看复杂度、看可控性
如果任务步骤固定、前后依赖强,优先用共享状态和静态路由。比如“需求分析 → 代码生成 → 单测 → 评审”这种流程,动态路由反而会增加不确定性。
如果任务可以并行,或者多个 Agent 不需要互相知道对方存在,优先用消息传递。比如多个研究 Agent 同时查不同资料源,最后由汇总 Agent 合并。
如果是客服、助手、企业流程自动化这类任务,常见做法是 Orchestrator + 静态规则 + 动态路由 + Handoff 混合。确定路径稳定执行,不确定路径让模型判断,高风险路径人工确认。
十三、上线前的工程检查清单
多 Agent 系统不是 Agent 越多越强。Agent 数量增加后,问题会从“模型有没有答对”变成“系统有没有失控”。上线前至少要检查八件事。
十四、面试和项目复盘时怎么回答
如果被问“多 Agent 之间怎么协作”,不要只说“一个 Agent 做完传给下一个”。更完整的回答应该分成三层。
第一层,协作方式:强依赖流程用共享状态,低耦合并行任务用消息传递。共享状态要分全局状态和局部状态,写入尽量只追加不覆盖。
第二层,切换方式:高频确定路径用静态路由,未知边界场景用 LLM 动态路由,职责边界清晰时可以用 Handoff。动态路由必须做候选白名单校验和 fallback。
第三层,生产护栏:记录路由日志、状态变更、Agent 轨迹、最大交接次数、错误状态、成本预算和人工确认入口。多 Agent 的核心不是“更智能”,而是“更可控地协作”。
要点速读
多 Agent 系统真正难的不是“多几个角色”,而是让这些角色有秩序地传信息、换任务、收敛结果。 开篇:多 Agent
- 多 Agent 系统真正难的不是“多几个角色”,而是让这些角色有秩序地传信息、换任务、收敛结果
- 开篇:多 Agent
- 更多细节仍在持续更新中