【LangChain进阶01:Multi-agent】—— LangChain 多 Agent 实战:从子 Agent 到架构选型,让 Agent 团队协作
LangChain 多 Agent 实战:从子 Agent 到架构选型,让 Agent 团队协作
一个 Agent 看似万能,但当你给它塞了 50 个工具、写了一页纸的 system_prompt,它就开始「分心」了——该用哪个工具犹豫不决,长提示词里真正关键的指令反而被淹没。这不是模型不行,是单 Agent 的上下文被撑爆了。
多 Agent 的方案就是把复杂任务拆给一群各司其职的 Agent,让它们像团队一样协作。这篇文章讲清楚:为什么要多 Agent、有哪些实现方式、以及你该选哪种架构模式。
一、先厘清:为什么需要多 Agent
1.1 单 Agent 的三个瓶颈
| 问题 | 具体表现 |
|---|---|
| system_prompt 太长 | 模型注意力分散,关键指令被淹没 |
| 工具太多 | 模型选择工具的出错概率上升 |
| 任务类型混杂 | 不同类型任务需要不同专业知识和行为风格 |
1.2 多 Agent 的解法
每个 Agent 专注一个领域,通过协作完成复杂任务。核心价值是上下文管理——给每个 Agent 只喂它需要的信息,而不是把全部知识都塞进一个提示词。
✅ 一句话总结:单 Agent 靠「大而全」硬扛,多 Agent 靠「专而精」分工。
⚠️ 注意:多 Agent 会增加复杂度和 Token 消耗。不要为了「多 Agent」而多 Agent——先用单个 Agent + 好的 system_prompt + Middleware 解决问题,只有当确实需要领域隔离或独立上下文时才引入。
二、实现方式一:把子 Agent 当作工具
这是最直观、最好上手的方式。你把子 Agent 编译后用 @tool 包装,注册给父 Agent。父 Agent 作为「协调者」,按需调用这些「专家工具」。
from dotenv import load_dotenv
load_dotenv()
from langchain.tools import tool
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
# 子 Agent 1:天气专家
@tool
def get_weather(city: str) -> str:
"""查询天气"""
data = {"杭州": "晴,25°C", "北京": "多云,18°C"}
return data.get(city, f"{city}: 数据暂缺")
weather_agent = create_agent(
model=model,
tools=[get_weather],
name="weather_expert", # 名字用于标识和日志
system_prompt="你是天气专家,专门回答天气相关问题。回答要简洁。",
)
# 子 Agent 2:计算专家
@tool
def calculate(expression: str) -> str:
"""计算数学表达式"""
result = eval(expression, {"__builtins__": {}}, {})
return f"{expression} = {result}"
math_agent = create_agent(
model=model,
tools=[calculate],
name="math_expert",
system_prompt="你是数学专家,专门进行数学计算。回答要简洁。",
)
# 父 Agent:协调者
@tool
def ask_weather_expert(question: str) -> str:
"""向天气专家咨询天气相关问题。
Args:
question: 关于天气的问题
"""
result = weather_agent.invoke(
{"messages": [HumanMessage(content=question)]}
)
return result["messages"][-1].content
@tool
def ask_math_expert(question: str) -> str:
"""向数学专家咨询数学计算问题。
Args:
question: 数学计算问题
"""
result = math_agent.invoke(
{"messages": [HumanMessage(content=question)]}
)
return result["messages"][-1].content
coordinator = create_agent(
model=model,
tools=[ask_weather_expert, ask_math_expert],
system_prompt="""你是协调助手。根据用户问题选择合适的专家:
- 天气相关问题 → 使用 ask_weather_expert
- 数学计算问题 → 使用 ask_math_expert
- 如果同时涉及多个领域,依次咨询各个专家""",
)
# 测试复合问题
result = coordinator.invoke({
"messages": [HumanMessage(
content="杭州今天天气怎么样?如果温度是 25 度,换算成华氏度是多少?(公式:华氏度 = 摄氏度 × 9/5 + 32)"
)]
})
print(result["messages"][-1].content)
运行结果:
根据天气专家的查询,杭州今天晴天,气温25°C。
换算成华氏度:25 × 9/5 + 32 = 77°F。
所以杭州今天25°C,相当于77°F,天气晴好。
父 Agent 成功把复合问题拆成了「问天气专家 + 问计算专家」两步,然后自己汇总。这就是最朴素的子 Agent 协作。
三、实现方式二:用 name 参数区分 Agent
当你把子 Agent 作为工具嵌入时,设置 name 参数很有用——它作用在三处:
agent = create_agent(
model=model,
tools=[...],
name="customer_service", # 给 Agent 命名
)
name 参数的作用:
- 编译后的图里使用该名称
- 作为子图节点嵌入父图时使用该名称
- 所有 AI 消息被标记为该名称
好处是便于追踪消息来源——在多 Agent 的日志里,你能一眼看出某条回复是哪个 Agent 生成的。
四、实现方式三:Middleware 实现 Agent 路由
更复杂的多 Agent 场景可以用 Middleware 做动态路由——根据运行时的上下文(比如用户角色、会话状态)动态切换可用工具或 Agent。
from langchain.agents.middleware import before_model
# 定义不同专家使用的工具集
general_tools = [tool_a, tool_b]
admin_tools = [tool_c, tool_d]
@before_model
def route_by_user_role(state, runtime):
"""根据用户角色动态切换可用工具"""
context = runtime.context
if context is None:
return None
user_role = context.get("user_role", "user")
# 不同角色看到不同的工具
if user_role == "admin":
available_tools = general_tools + admin_tools
else:
available_tools = general_tools
return None
⚠️ 注意:
before_model不能直接修改 tools。要真正改变工具集,需要配合wrap_model_call或request.override来实现(见中间件进阶那篇)。
五、多 Agent 架构模式对比
5.1 三种经典模式
| 模式 | 结构 | 适用场景 |
|---|---|---|
| 协调者模式 | 一个父 Agent → 多个子 Agent 工具 | 任务类型明确可分类 |
| 接力模式 | Agent A 的输出 → Agent B 的输入 | 流水线式处理(生成→审核→润色) |
| 辩论模式 | 多个 Agent 并行输出 → 汇总决策 | 需要多角度分析的问题 |
5.2 官方四模式扩展
LangChain 官方文档把多 Agent 归纳为四种更细的模式,各有侧重:
| 模式 | 怎么运作 | 适合 |
|---|---|---|
| Subagents(子 Agent) | 主 Agent 把子 Agent 当工具调用,所有路由经过主 Agent | 领域隔离、并行执行 |
| Handoffs(交接) | 工具调用更新状态变量,触发路由/配置切换,Agent 之间转移控制权 | 多跳、直接与用户交互 |
| Skills(技能) | 一个 Agent 主导,按需加载专业提示词和知识 | 简单专注、重复请求、并行 |
| Router(路由) | 一个路由步骤分类输入,派发给专业 Agent,合成结果 | 并行执行、大上下文领域 |
5.3 按场景选模式(关键决策表)
| 优化目标 | Subagents | Handoffs | Skills | Router |
|---|---|---|---|---|
| 单次请求高效 | - | ✅ | ✅ | ✅ |
| 重复请求省调用 | - | ✅ | ✅ | - |
| 并行执行 | ✅ | - | - | ✅ |
| 大上下文领域 | ✅ | - | - | ✅ |
| 简单专注任务 | - | - | ✅ | - |
5.4 性能权衡(Model calls 对比)
| Pattern | 单次请求 | 重复请求(两轮) | 多领域 |
|---|---|---|---|
| Subagents | 4 次 | 8 次 | 5 次 / ~9K tokens |
| Handoffs | 3 次 | 5 次 | 7+ 次 / ~14K tokens |
| Skills | 3 次 | 5 次 | 3 次 / ~15K tokens |
| Router | 3 次 | 6 次 | 5 次 / ~9K tokens |
关键洞察:
- Subagents 多一次调用(结果要回流主 Agent),换来的是强上下文隔离和集中控制。
- Handoffs / Skills 在重复请求最省(状态/技能复用,省 40-50% 调用)。
- 多领域任务选并行执行(Subagents / Router)最划算,Skills 虽调用少但 token 累积高。
✅ 一句话总结:要集中控制选 Subagents,要省调用选 Handoffs/Skills,要多领域并行选 Router。
六、总结:你真正需要记住的这几件事
- 单 Agent 的瓶颈是上下文过载——prompt 太长、工具太多、任务混杂都会让它「分心」。
- 最易上手的实现是把子 Agent 用
@tool包装成「专家工具」,交给父 Agent 协调。 name参数帮你追踪来源,多 Agent 日志排查必备。- 复杂路由用 Middleware,但改工具集要靠
wrap_model_call。 - 四种官方模式各有长板:Subagents 集中控制、Handoffs 交接、Skills 按需加载、Router 分类派发。
- 别盲目上多 Agent——单 Agent + 好 prompt 能解决,就别增加复杂度。
验证清单
- 能用「子 Agent 当工具」方式实现一个天气 + 数学的复合问答
- 不同子 Agent 间上下文隔离,互不干扰
-
name参数生成的 AI 消息带正确来源标记 - 能说出四种模式下各自适合的选型场景
- 能根据「单次/重复/多领域」判断最省调用的模式
参考资源
- LangChain 官方 · Multi-agent: https://docs.langchain.com/oss/python/langchain/multi-agent
- LangChain 官方 · Subagents 模式: https://docs.langchain.com/oss/python/langchain/multi-agent/subagents
- 菜鸟教程 · LangChain 多 Agent: https://www.runoob.com/langchain/langchain-multi-agent.html
说明:文中
deepseek:deepseek-v4-flash等模型名及代码示例以官方文档和菜鸟教程为准,具体 API 细节请以你安装的 LangChain 版本为准。
更多推荐





所有评论(0)