大家好,我是程序员小策。
多 Agent 该怎么协作?
Supervisor、Swarm、Handoff 这几个词到底什么区别?
什么场景该用哪种?动态切换又该怎么设计?
一、多 Agent 协作的核心问题:责任分配 + 状态流转
[问题定义] 表面上看,"多 Agent"只是把单 Agent 拆成几个。但实际跑起来你会发现两个隐藏难题:
第一是责任分配。谁来当"管事的"?Supervisor 模式让一个 Agent 当"经理"统一调度,其他人都是"员工";Swarm 模式让所有 Agent 平级,谁都能主动转给别人;Handoff 模式更激进——当前 Agent 直接"交班"给下一个 Agent,自己就退场。LangGraph 官方文档把这 3 种叫multi-agent patterns,每种对应不同的责任拓扑。
第二是状态流转。Agent 切换时,Context 怎么交接?如果交接不干净,下一个 Agent 不知道"用户上一轮说了什么",整个协作就崩。这是为什么上两篇聊 Context 工程的原因——多 Agent 协作的瓶颈 70% 在状态管理。
langchain-ai/langgraph 的 0.2 版本专门引入了langgraph-swarm和langgraph-supervisor两个官方库,把这 3 种模式封装成开箱即用的 API。AutoGen 走的是另一条路——基于 GroupChat + Speaker Selection 动态选人。本质都是"协作 + 切换"。
动态切换的真正难点不是"能不能切",是"什么时候切、切完状态怎么办、切错了怎么回退"。下面 4 段代码逐个拆解。
二、4 大核心概念 + 引用块定义(餐厅分工主类比)
多 Agent 协作模式:将任务拆给多个 LLM Agent 协同完成的责任拓扑,由 4 大主流模式组成。
- Supervisor 模式:中心化调度,一个"经理 Agent"根据当前状态决定下一步交给谁
- Swarm 模式:去中心化自组织,每个 Agent 都能主动"转交"给最合适的同事
- Handoff 模式:当前 Agent 直接"交班"给下一个 Agent,自己退场(OpenAI Swarm 主推)
- Subgraph 子图:把"专家 Agent"封装成可复用的子图,主图按需调用
类比时间。我把这 4 种映射成"餐厅分工":
- Supervisor = 餐厅经理:客人坐下后经理统一安排——点单交给服务员、复杂需求交给主厨、投诉升级到大堂经理。所有任务经过经理这个单一调度点
- Handoff = 换岗位:服务员接到"包厢预定"请求,自己处理不了,直接把工牌交给"包厢专员"。原服务员退场
- Swarm = 自助餐厅:没有统一经理,每个厨师站都是独立的,客人走到哪个窗口就由哪个窗口服务(Agent 主动"喊"下一个)
- Subgraph = 中央厨房订单板:每道菜由专门厨师做(专家 Agent),前厅只跟订单板交互(主图)。主图不知道厨师具体怎么干,只看输入输出
选型金句:协作模式决定"责任拓扑",动态切换决定"时序与状态"。两者是独立的——你可以用 Supervisor + Handoff,也可以用 Swarm + Subgraph。
三、代码实现:4 种模式逐个上手
下面 4 段代码全部基于 langgraph ,可直接pip install langgraph langgraph-supervisor langgraph-swarm跑起来。
3.1 Supervisor 模式(最主流)
# Supervisor:中心化调度fromtypingimportLiteralfromlangchain_openaiimportChatOpenAIfromlanggraph.graphimportStateGraph,MessagesState,START,ENDfromlanggraph.typesimportCommand# 1) 定义专家 Agentdefresearch_agent(state:MessagesState)->Command[Literal["supervisor"]]:llm=ChatOpenAI(model="gpt-4o-mini")result=llm.invoke(state["messages"]+[("system","你是调研专家,专注查证事实")])returnCommand(goto="supervisor",update={"messages":[result]})defwriter_agent(state:MessagesState)->Command[Literal["supervisor"]]:llm=ChatOpenAI(model="gpt-4o-mini")result=llm.invoke(state["messages"]+[("system","你是写作专家,专注输出文章")])returnCommand(goto="supervisor",update={"messages":[result]})# 2) Supervisor 节点:决定下一个 Agentdefsupervisor_node(state:MessagesState)->Command[Literal["research_agent","writer_agent",END]]:# 简单版:LLM 决策(生产建议 rule-first)llm=ChatOpenAI(model="gpt-4o-mini").with_structured_output(NextAgent)decision=llm.invoke(state["messages"]+[("system","你是调度经理。下一个该给 research_agent 还是 writer_agent?""如果都做完了,回 FINISH")])goto="FINISH"ifdecision.next=="FINISH"elsedecision.nextreturnCommand(goto=gotoifgotoin["research_agent","writer_agent"]elseEND)# 3) 构图graph=StateGraph(MessagesState)graph.add_node("supervisor",supervisor_node)graph.add_node("research_agent",research_agent)graph.add_node("writer_agent",writer_agent)graph.add_edge(START,"supervisor")app=graph.compile()适用:任务阶段清晰、流程固定(调研 → 写稿 → 校对)。优势:决策可观测,调度全在一个节点。坑:Supervisor 是单点瓶颈,LLM 决策成本高。
3.2 Handoff 模式(OpenAI Swarm 主推)
# Handoff:当前 Agent 直接"交班"fromlanggraph.prebuiltimportcreate_react_agentfromlanggraph_swarmimportcreate_handoff_tool,create_swarm# 1) 创建能"交班"的 Agentdefbook_hotel(query:str)->str:returnf"已为您预订酒店:{query}"defbook_flight(query:str)->str:returnf"已为您预订航班:{query}"hotel_agent=create_react_agent("openai:gpt-4o-mini",[book_hotel,create_handoff_tool(agent_name="flight_agent")],system_prompt="你是酒店预订专员。处理酒店需求,机票转 flight_agent。",)flight_agent=create_react_agent("openai:gpt-4o-mini",[book_flight,create_handoff_tool(agent_name="hotel_agent")],system_prompt="你是机票预订专员。处理机票需求,酒店转 hotel_agent。",)# 2) 组合成 Swarmworkflow=create_swarm([hotel_agent,flight_agent],default_active_agent="hotel_agent")app=workflow.compile()# 3) 跑:用户说"我先订机票,订完再订酒店"result=app.invoke({"messages":[("user","帮我订明天北京到上海的机票,然后订外滩附近的酒店")]})# → hotel_agent 接需求 → 识别是机票 → handoff 给 flight_agent → 处理完再 handoff 回 hotel_agent适用:用户主导的对话流,Agent 边界明确。优势:每个 Agent 自治,扩展简单。坑:循环 handoff(Agent A → B → A → B…)需要 cycle detection。
3.3 Swarm 模式(去中心化)
# Swarm:每个 Agent 都能主动转交fromlanggraph_swarmimportcreate_swarm# 比 Handoff 更激进:没有 default_active_agent,谁都能"喊"下一个sales_agent=create_react_agent("openai:gpt-4o-mini",[create_handoff_tool("support_agent")],system_prompt="你是销售,处理报价和合同。技术支持问题转 support_agent。",)support_agent=create_react_agent("openai:gpt-4o-mini",[create_handoff_tool("sales_agent")],system_prompt="你是技术支持。Bug 排查和故障处理。商务问题转 sales_agent。",)swarm=create_swarm([sales_agent,support_agent])app=swarm.compile()# 注意:Swarm 模式不指定 default_active_agent——首个接收用户输入的 Agent 就是激活态适用:Agent 角色高度自治、用户需求边界模糊。优势:无单点瓶颈。坑:状态可观测性差,调试难。
3.4 Subgraph 子图(专家封装)
# Subgraph:把专家 Agent 封装成可复用的子图fromlanggraph.graphimportStateGraph,MessagesState# 1) 子图:翻译专家(含中英日 3 个内部节点)deftranslator_subgraph(state:MessagesState)->MessagesState:sg=StateGraph(MessagesState)sg.add_node("router",lambdas:s)# 路由到中/英/日sg.add_node("to_en",lambdas:s)# 调用 LLM 翻译sg.add_node("to_zh",lambdas:s)sg.add_node("to_ja",lambdas:s)sg.set_entry_point("router")# ... 省略内部 LLM 调用细节returnsg.compile().invoke(state)# 2) 主图:把翻译专家当"黑盒"调用main=StateGraph(MessagesState)main.add_node("translate_expert",translator_subgraph)# 子图当节点main.add_node("writer",lambdas:s)main.add_edge(START,"translate_expert")main.add_edge("translate_expert","writer")app=main.compile()# 跑:主图只看到 translate_expert 的输入输出,不关心内部 3 个节点适用:专家 Agent 内部复杂、但对外接口简单。优势:可复用、易测试、主图清晰。坑:子图与主图的 state schema 必须兼容。
四、4 个常见坑:协作 / 切换的真实代价
坑 1:Supervisor 决策循环
现象:supervisor 节点把任务交给 research_agent,research_agent 完成后再回 supervisor,supervisor 又交给 research_agent
根因:没有"上一轮是哪个 Agent"的记忆,LLM 不知道已经做完了
解法:在 state 加last_agent字段,supervisor 决策时排除上一个 Agent
坑 2:Handoff 状态丢失
现象:flight_agent 接到酒店需求后状态空白,不知道用户上一轮说了什么忌口
根因:handoff 只切了"激活 Agent",没有传完整 MessagesState
解法:handoff tool 必须把messages一起传(create_handoff_tool内部已处理,但自己写要小心)
坑 3:Swarm 循环 handoff(agent A → B → A → B 死循环)
现象:sales_agent 转 support_agent,support_agent 又转 sales_agent
根因:两个 Agent 都把对方当成"非自己职责"的 fallback
解法:(1) 限制最大 handoff 次数max_handoffs=3;(2) LLM prompt 明确"连续 2 次转回原 Agent 应该直接处理"
坑 4:Subgraph 状态 schema 不兼容
现象:主图
state["messages"]是list[BaseMessage],子图期望list[dict],运行时KeyError
根因:StateGraph 的 state schema 是定义时检查,子图编译时没引入主图的 schema
解法:主图和子图用同一份MessagesState(继承而非重写),或者用TypedDict+Annotated显式对齐
五、生产考量:4 个维度
- 可观测性:Supervisor 模式有天然优势——一个节点就能看到所有决策。Swarm 模式必须给每个 Agent 加
LangSmithtrace tag,否则排查时根本不知道"为什么转过去了" - 状态隔离:每个 Agent 应该有独立
thread_id(用MemorySaver或PostgresSaver),避免 A 用户的 context 串到 B 用户 - 失败回退:Supervisor 节点必须 catch LLM 异常,回退到上一个成功的 Agent(而不是直接 END)。Swarm 模式需要给 handoff tool 加超时(默认无超时)
- 成本控制:Supervisor 模式的 LLM 调用数 = 节点数 × 2(Agent 一次 + Supervisor 一次),3 个 Agent 一轮就是 6 次。Swarm 模式更省(没 Supervisor)。预算是必要决策项
六、4 大协作模式 + 决策总表
| 模式 | 拓扑 | LLM 调用成本 | 可观测性 | 适用场景 | 不适用 |
|---|---|---|---|---|---|
| Supervisor | 中心化 | 高(每步 2 次) | ⭐⭐⭐⭐⭐ | 流程固定的任务流 | 高频切换场景 |
| Handoff | 半中心 | 中(按需 1 次) | ⭐⭐⭐ | 用户主导的多步对话 | 需要全局视角的任务 |
| Swarm | 去中心 | 中(按需 1 次) | ⭐⭐ | Agent 高度自治 | 强流程管控 |
| Subgraph | 嵌套 | 按子图内部 | ⭐⭐⭐⭐ | 专家 Agent 复用 | 子任务差异大 |
决策树简化版:
你的任务能拆成清晰的阶段吗? ├─ 能(调研→写稿→校对) → Supervisor ├─ 不能(用户主导) → Handoff └─ 不能 + Agent 高度自治 → Swarm 你有多组可复用的专家 Agent 吗? ├─ 有 → Subgraph 封装 └─ 没有 → 直接平铺主流框架选择(基于 2026-07 真实 star 数据):
- langchain-ai/langgraph [主流] — Python/TS 双版本,4 种模式全支持
- microsoft/autogen [主流] — GroupChat + Speaker Selection,动态切换更底层
- openai/swarm [主流] — Handoff 模式教学库,适合入门
- langchain-ai/langchain [主流] — Supervisor/Handoff 高级封装
七、面试官还会追问什么?
追问 1:Supervisor 和 Swarm 本质区别?
→ 决策权归属。Supervisor 决策权在中心节点(经理说了算),Swarm 决策权在每个 Agent(员工自治)。Supervior 可观测好但单点瓶颈,Swarm 反之。90% 生产项目选 Supervisor——因为你能 debug 经理节点。
追问 2:动态切换的 4 种触发条件?
→ (1) 任务阶段变化(Supervisor 决策完换 Agent);(2) Agent 主动 handoff(自认不行);(3) 工具调用失败(fallback 到别的 Agent);(4) 用户显式切换(“换个人工服务”)。前两个最常见。
追问 3:多 Agent 怎么共享 context 不爆?
→三层策略:(1) 每个 Agent 独立 thread(MemorySaver/PostgresSaver隔离);(2) Supervisor 维护"全局摘要" sub-state(每次切换前 LLM 总结);(3) 长期记忆走langgraph.store(跨 Agent 共享用户画像)。这正是前两篇 Context 工程的延伸。
追问 4:Subgraph 和普通节点的区别?
→ Subgraph 编译后是一个有内部状态机的节点,普通节点是单步函数。区别在于:Subgraph 可以独立 invoke、独立测试、独立持久化 thread_id。判断标准:如果一个"专家"需要 3+ 个内部步骤,就该抽成 Subgraph。
八、总结:多 Agent 设计 = 拓扑 + 切换 + 状态
多 Agent 协作的 3 个独立决策点:
- 拓扑选型(Supervisor / Handoff / Swarm / Subgraph)— 看责任怎么分配
- 切换触发(任务阶段 / Agent 主动 / 工具失败 / 用户切换)— 看时序怎么流转
- 状态管理(独立 thread / 共享摘要 / 长期记忆)— 看 context 怎么传
记住一句金句:“模式选错是设计问题,切换错是 bug,状态错是灾难”。优先把 Supervisor 跑通,Handoff 做扩展,Swarm 慎用,Subgraph 按需封装。
读完这篇你应该能:
- 说出 4 种协作模式的代码骨架(不只是背概念)
- 画出你项目当前的 Agent 拓扑(是 Supervisor 还是 Swarm?)
- 设计 3 类切换触发点(任务 / Agent / 工具)
- 用 4 维度决策框架给新项目选型
如果这篇让你对多 Agent 协作少一些纠结,欢迎点赞 + 在看。
最后留个开放问题:你的项目里如果 Supervisor 节点被替换成 LLM-as-judge 来决策"任务是否完成",会不会更稳?还是反而更慢?