简介: 针对单体 Agent 在复杂任务中易迷失、易死循环的痛点,本文深入探讨了基于 LangGraph 的多 Agent 协作架构。通过 Supervisor 模式的实战演练,详细解析了状态管理、路由决策及避坑经验,助你构建真正可落地的工业级 AI 应用。
如果你曾尝试让一个单体 Agent(如标准的 ChatOpenAI 配合 AgentExecutor)同时完成"调研新技术、编写 Demo 代码、进行单元测试并输出文档"这一系列任务,你大概率会遇到以下惨状:Agent 在执行到第三步时忘记了第一步的约束,或者在代码报错时陷入了无意义的自我修正死循环,最终烧光了你的 Token,却只吐出一堆逻辑混乱的废话。
在生产环境中,单体 Agent 的上下文窗口(Context Window)和推理链条是有极限的。当任务复杂度超过某个阈值,模型就会开始"胡言乱语"。解决办法不是换一个更强的模型,而是改变架构------从单兵作战转向多 Agent 协作(Multi-Agent Systems)。
本文将基于 LangGraph(LangChain 官方推出的有状态多 Agent 编排库)分享如何构建一个可落地的多 Agent 应用。
1. 为什么是 LangGraph 而不是传统的 AgentExecutor?
传统的 LangChain Agent 是一个黑盒,你很难控制它的内部循环逻辑。而在多 Agent 场景下,我们需要的是一个状态机。
- State(状态):所有 Agent 共享的"账本",记录当前任务进度。
- Nodes(节点):每个 Agent 或工具就是一个节点,负责处理状态并返回更新。
- Edges(边):定义了从一个节点到另一个节点的流转逻辑(条件路由)。
这种架构允许我们像设计工业流水线一样,精确控制每个 Agent 的职责边界。
2. 核心架构:Supervisor(导师)模式
在多 Agent 协作中,最稳定的模式是 Supervisor 模式。它由一个主控 Agent 负责分发任务,多个专家 Agent 负责执行,最后由主控汇总。
3. 实战演练:构建一个技术文档生成系统
我们将构建一个包含"搜索专家"和"代码专家"的协作系统。
环境要求:
langchain >= 0.2.0langgraph >= 0.1.0langchain-openai
第一步:定义共享状态
python
from typing import Annotated, List, TypedDict
import operator
# 定义 Agent 之间共享的状态
class AgentState(TypedDict):
# 所有的消息都会被追加到这个列表里
messages: Annotated[List, operator.add]
# 下一个要执行的节点
next: str
第二步:创建专家 Agent
不要直接给 Agent 塞入所有工具。职责分离是降低幻觉的关键。
python
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 1. 调研专家:仅赋予搜索工具
research_agent = create_react_agent(
llm, tools=[tavily_tool], state_modifier="你是一名资深技术调研员,负责搜集最新的技术文档和 API 用法。"
)
# 2. 代码专家:仅负责编写和运行 Python 代码
code_agent = create_react_agent(
llm, tools=[python_repl_tool], state_modifier="你是一名高级工程师,负责根据调研结果编写高质量的 Python 代码示例。"
)
第三步:构建主控路由(Supervisor)
这是系统的"大脑",它不干活,只负责看进度并决定谁是下一个执行者。
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers.openai_functions import JsonOutputFunctionsParser
members = ["Researcher", "Coder"]
system_prompt = (
"你是一名团队负责人,负责管理以下人员:{members}。"
"根据用户的问题,决定谁应该执行下一步。每个人员执行完后都会向你汇报。"
"当任务完全结束时,回复 FINISH。"
)
options = ["FINISH"] + members
function_def = {
"name": "route",
"description": "选择下一个执行者",
"parameters": {
"type": "object",
"properties": {
"next": {"anyOf": [{"enum": options}]}
},
"required": ["next"],
},
}
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("placeholder", "{messages}"),
("system", "根据以上对话,谁应该是下一个执行者?或者是结束任务?")
]).partial(members=", ".join(members))
# 使用 OpenAI 的 Function Calling 来保证输出的稳定性
supervisor_chain = (
prompt
| llm.bind_functions(functions=[function_def], function_call="route")
| JsonOutputFunctionsParser()
)
第四步:编排工作流
python
from langgraph.graph import StateGraph, END
workflow = StateGraph(AgentState)
# 添加节点
workflow.add_node("Researcher", lambda state: research_agent.invoke(state))
workflow.add_node("Coder", lambda state: code_agent.invoke(state))
workflow.add_node("supervisor", lambda state: supervisor_chain.invoke(state))
# 所有的专家节点执行完后,都要回到 supervisor
for member in members:
workflow.add_edge(member, "supervisor")
# 根据 supervisor 的判断进行条件路由
conditional_map = {k: k for k in members}
conditional_map["FINISH"] = END
workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map)
workflow.set_entry_point("supervisor")
graph = workflow.compile()
4. 避坑指南:老司机的私房建议
1. 警惕"幻觉传递"
Agent A 可能会生成一个错误的 API 调用方法,Agent B 拿到后会基于这个错误继续编写代码。
- 对策 :在
Researcher和Coder之间增加一个Validator(校验节点)。不要让 Agent 自己检查自己,让另一个 Prompt 专门负责"找茬"。
2. 解决死循环与 Token 爆炸
当 Agent 无法完成任务时,它可能会在两个节点之间反复横跳。
-
对策 :在
compile()时设置recursion_limit。python# 限制最大步数为 20 步,超过则强制停止 graph.invoke({"messages": [HumanMessage(content="...") ]}, {"recursion_limit": 20})
3. 状态清理
随着对话增加,messages 列表会越来越长,导致 Context Window 溢出。
- 对策:在 Supervisor 节点中加入"摘要逻辑"。每当消息超过 10 条,就触发一次总结,将历史信息压缩,只保留关键结论。
4. 人类干预(Human-in-the-loop)
有些关键决策(比如删除数据库、发送邮件)不能全自动化。
- 对策 :利用 LangGraph 的
interrupt_before功能。在执行Coder节点前暂停,等待人工在控制台输入Approve后再继续。
5. 深度总结:单体 vs 多 Agent
| 特性 | 单体 Agent (Single Agent) | 多 Agent 协作 (Multi-Agent) |
|---|---|---|
| 复杂度上限 | 低,容易在长链条任务中迷失 | 高,通过模块化拆解复杂逻辑 |
| 调试难度 | 极难,Prompt 牵一发而动全身 | 较易,可针对特定节点优化 Prompt |
| Token 效率 | 早期省,后期因重复尝试而浪费 | 初始开销大,但任务成功率更高 |
| 适用场景 | 简单的问答、单一工具调用 | 软件开发、深度市场调研、复杂流转业务 |
最后的一点经验: 不要为了用多 Agent 而用多 Agent。如果一个任务通过优化 System Prompt 就能让单体 Agent 搞定,那就不要引入 LangGraph。多 Agent 系统的本质是用架构的确定性来弥补模型推理的不确定性。当你发现你的 Prompt 已经长到连你自己都读不下去时,就是该拆分 Agent 的时候了。