在 LangChain 开发智能应用的过程中,我们常常会遇到这样的困境:当单体智能体集成的工具越来越多,它的决策效率反而急剧下降;当对话上下文超过千条消息,单智能体的跟踪能力就会出现明显断层。一个具备 12 种工具调用能力的智能体,在处理复杂任务时频繁出现 "工具滥用" 问题 —— 明明只需要调用计算器,却反复触发搜索引擎。这种情况下,多智能体系统架构就成了破局的关键。本文将系统拆解 LangGraph 中五种经典多智能体架构的设计逻辑与代码实现,助你打造从 "笨拙巨人" 到 "敏捷团队" 的 AI 协作体系。
一、多智能体系统:破解单体智能体困局的核心方案
当你的智能应用出现以下症状时,正是引入多智能体系统的最佳时机:
- 工具调用混乱:智能体在超过 3 种功能类似的工具间频繁误判
- 上下文溢出:单轮对话 token 数超过 3000 后出现 "记忆断层"
- 专业能力不足:需要同时处理规划、检索、计算等跨领域任务
多智能体系统的核心价值在于将复杂问题拆解为可管理的子任务,其带来的三大工程优势值得我们重点关注:
- 模块化开发:每个智能体作为独立组件,支持团队并行开发(效率提升约 30%)
- 专业分工:让规划智能体专注任务拆解,检索智能体专注信息获取
- 精准控制:告别函数调用的黑盒模式,实现通信流程的可视化编排
类比理解:多智能体系统就像交响乐团,不同智能体如同乐团中的小提琴手、大提琴手,而监管智能体则是指挥家,共同协作完成复杂的演奏任务。
二、五种经典多智能体架构
在多智能体系统中,有几种连接智能体的方法:
- 网络:每个智能体都可以与其他所有智能体进行通信。任何智能体都可以决定接下来呼叫哪个其他智能体。
- 监督智能体:每个智能体与单个监督智能体进行通信。监督智能体决定接下来应该调用哪个智能体。
- 监督智能体(工具调用):这是监督架构的一种特殊情况。单个智能体可以表示为工具。在这种情况下,监督智能体使用工具调用大语言模型来决定调用哪个智能体工具,以及传递给这些智能体的参数。
- 分层式:你可以定义一个具有主管的主管的多智能体系统。这是主管架构的一种泛化,允许更复杂的控制流。
- 自定义多智能体工作流程:每个智能体仅与一部分智能体进行通信。流程的某些部分是确定性的,只有部分智能体可以决定接下来调用哪些其他智能体。
2.1 网络架构:自由交互的智能体生态
架构特点:每个智能体可与其他所有智能体直接通信,适合无明确层级的协作场景
python
# 核心实现逻辑
def agent_1(state: MessagesState) -> Command[Literal["agent_2", "agent_3", END]]:
# 通过LLM分析当前状态决定路由方向
response = model.invoke(
f"根据对话历史{state['messages']},判断下一步调用agent_2/agent_3或结束"
)
next_agent = response.json()["next_agent"]
return Command(
goto=next_agent,
update={"messages": [{"role": "agent_1", "content": response.content}]}
)
适用场景:创意生成、头脑风暴等需要自由联想的场景
注意事项:智能体数量建议不超过 5 个,避免通信过载
2.2 监管架构:中心化的智能体调度
架构特点:引入监管者智能体,所有子智能体仅与监管者通信
python
# 监管者核心逻辑
def supervisor(state: MessagesState) -> Command[Literal["agent_1", "agent_2", END]]:
# 分析全局状态决定调用哪个子智能体
response = model.invoke(
f"分析工单{state['messages']},判断转交agent_1(售后)或agent_2(技术)"
)
return Command(goto=response.json()["next_agent"])
适用场景:客服工单处理、任务审批等流程化场景
性能优化:为监管者配置专用 LLM 模型,提升决策效率约 25%
2.3 工具调用监管架构:智能体即工具的封装模式
架构特点:将子智能体封装为工具,通过 ReAct 机制调用
python
# 子智能体作为工具实现
def agent_1(state: dict) -> str:
# 专注数据分析任务
return model.invoke(f"分析数据:{state['query']}").content
# 快速构建工具调用监管者
supervisor = create_react_agent(model, [agent_1, agent_2])
集成优势:无需手动处理 Command 对象,自动解析工具返回结果
接口规范:建议统一工具输入输出格式,降低集成成本
2.4 分层架构:应对超复杂系统的层级方案
架构特点:通过多层监管者实现分级调度,解决单一监管者瓶颈
python
# 顶层监管者逻辑
def top_level_supervisor(state: MessagesState) -> Command[Literal["team_1", "team_2", END]]:
# 决定调用哪个子团队
response = model.invoke(
f"分析全局任务{state['messages']},判断转交team_1(技术)或team_2(产品)"
)
return Command(goto=response.json()["next_team"])
应用场景:包含 10 + 智能体的大型系统,如多领域客服平台
层级建议:建议不超过 3 层,避免调度延迟
2.5 自定义工作流架构:精准控制的流程设计
-
显式控制流(普通边):LangGraph 允许通过 普通图边显式定义应用程序的控制流(即智能体之间通信的顺序)。这是上述架构中最具确定性的变体 —— 我们始终提前知道接下来将调用哪个智能体。
-
动态控制流(指令):在LangGraph中,可以让大语言模型(LLMs)决定应用程序控制流的部分内容。这可以通过使用Command来实现。其中一种特殊情况是监督者工具调用架构。在这种情况下,为监督者智能体提供支持的工具调用大语言模型将决定调用工具(智能体)的顺序。
python
# 显式定义调用流程
builder = StateGraph(MessagesState)
builder.add_node(agent_1)
builder.add_node(agent_2)
builder.add_edge(START, "agent_1")
builder.add_edge("agent_1", "agent_2")
适用场景:标准化审批流程、固定步骤的生产流水线
扩展建议:可结合 Command 实现动态分支,提升灵活性
三、智能体通信核心:交接(Handoffs)机制详解
在多智能体架构中,智能体可以表示为图节点。每个智能体节点执行其步骤,并决定是完成执行还是路由到另一个智能体,这可能包括路由到自身(例如,循环运行)。多智能体交互中的一种常见模式是交接,即一个智能体将控制权交接给另一个智能体。交接能够指定:
- destination:要导航到的目标智能体(例如,要前往的节点名称)
- paylod:有效载荷,传递给该智能体的信息(例如,状态更新)
为了在LangGraph中实现交接,智能体节点可以返回Command对象,该对象允许同时组合控制流和状态更新:
def agent(state) -> Command[Literal["agent", "another_agent"]]:
# 路由/终止条件可以是任意逻辑,例如大语言模型工具调用、结构化输出等
goto = get_next_agent(...) # 'agent' / 'another_agent'
return Command(
# 指定下一步要调用的智能体
goto=goto,
# 更新图状态
update={"my_state_key": "my_state_value"}
)
在更复杂的场景中,每个智能体节点本身就是一个图(即一个子图),其中一个智能体子图中的节点可能想要导航到另一个智能体。例如,如果有两个智能体,alice
和bob
(父图中的子图节点),并且alice
需要导航到bob
,可以在Command
对象中设置graph=Command.PARENT
:
def some_node_inside_alice(state):
return Command(
goto="bob",
update={"my_state_key": "my_state_value"},
# 指定要导航到的图(默认值为当前图)
graph=Command.PARENT,
)
如果需要支持使用 Command(graph=Command.PARENT)
进行通信的子图的可视化,需要使用 Command
注解将它们包装在一个节点函数中
def call_alice(state) -> Command[Literal["bob"]]:
return alice.invoke(state)
builder.add_node("alice", call_alice)
通过Command
注解包装子图节点,本质是向 LangGraph 的可视化系统显式声明控制流元数据,确保跨层次的代理通信能被正确捕获和展示。这对于复杂多代理系统的开发、调试和维护至关重要,尤其在需要层次化设计的场景中
将工具作为交接手段
最常见的智能体类型之一是**工具调用智能体**。对于这类智能体,一种常见模式是将交接操作封装在工具调用中,例如:
@tool
def transfer_to_bob():
"""Transfer to bob."""
return Command(
# 要导航到的智能体(节点)名称
goto="bob",
# 要发送给智能体的数据
update={"my_state_key": "my_state_value"},
# 向LangGraph表明我们需要导航到父图中的智能体节点
graph=Command.PARENT,
)
结语
多智能体架构代表着 AI 应用开发的新范式,它让复杂智能系统的构建从 "单打独斗" 转向 "团队协作"。本文系统解析了 LangGraph 中多智能体架构的核心设计与实战技巧,后续将围绕状态管理、性能优化等主题展开深度分享。
如果本文对你有帮助,别忘了点赞收藏,关注我,一起探索更高效的开发方式~