LangChain LangGraph
Module 1 Module 2 Module 3
Module 2 · 工具、状态与多 Agent
1 2.1 MCP
2 2.1 Travel Agent
3 2.2 Runtime Context
4 2.2 State
5 2.3 Multi Agent
6 2.4 Wedding Planners
7 Bonus: RAG
8 Bonus: SQL
SUM Module Summary
HomeLangChainModule 2 · 工具、状态与多 Agent2.3 Multi Agent
📓 Notebook 📖 Explained
LANGCHAIN MODULE 2 · LESSON 2.3

Multi-Agent:把子 Agent 包装成工具
Delegation · Routing · Message Trace

本节用两个数学子 Agent 演示多 Agent 编排:主 Agent 不直接做所有事,而是通过工具调用专门的子 Agent。

1 为什么要做 Multi-Agent

当一个 Agent 同时承担太多职责时,prompt 会变长,工具选择也更混乱。Multi-Agent 的做法是把能力拆给多个专门 Agent,再由主 Agent 负责选择和协调。

Subagent

专注一个小任务,例如只会开方或只会平方。

Wrapper Tool

把调用子 Agent 的逻辑封装成普通 tool。

Main Agent

根据用户问题选择调用哪个 wrapper tool。

核心模式

“Agent as Tool”:子 Agent 本身不是直接暴露给用户,而是被一个 tool 函数调用。主 Agent 只需要学会何时调用这个 tool。

2 先定义底层工具

Notebook 先定义两个普通工具:一个计算平方根,一个计算平方。它们是子 Agent 的专属工具。

Python
@tool
def square_root(x: float) -> float:
    """Calculate the square root of a number"""
    return x ** 0.5

@tool
def square(x: float) -> float:
    """Calculate the square of a number"""
    return x ** 2
简单示例的意义

数学工具很小,但结构和真实业务一致:每个子 Agent 拥有自己的工具集和职责边界。

3 创建两个子 Agent

每个子 Agent 只拿到自己需要的工具。这样它的动作空间更小,行为也更容易预测。

Python
subagent_1 = create_agent(
    model=deepseek_model(),
    tools=[square_root],
)

subagent_2 = create_agent(
    model=deepseek_model(),
    tools=[square],
)
Agent工具职责
subagent_1square_root回答开方问题
subagent_2square回答平方问题

4 把子 Agent 包装成主 Agent 的工具

主 Agent 不能直接“看见”子 Agent。Notebook 用两个 wrapper tool 调用子 Agent,并把子 Agent 的最终消息返回给主 Agent。

Python
@tool
def call_subagent_1(x: float) -> float:
    """Call subagent 1 in order to calculate the square root of a number"""
    response = subagent_1.invoke(
        {"messages": [HumanMessage(content=f"Calculate the square root of {x}")]}
    )
    return response["messages"][-1].content

@tool
def call_subagent_2(x: float) -> float:
    """Call subagent 2 in order to calculate the square of a number"""
    response = subagent_2.invoke(
        {"messages": [HumanMessage(content=f"Calculate the square of {x}")]}
    )
    return response["messages"][-1].content
返回值要简单

Wrapper tool 最好返回主 Agent 需要的最终结果或简短解释。不要把完整子 Agent trace 原样塞回去,否则主 Agent 上下文会膨胀。

5 主 Agent 负责路由

主 Agent 拿到两个 wrapper tool 后,会根据用户问题选择调用哪个子 Agent。例如“square root”应路由到 call_subagent_1

Python
main_agent = create_agent(
    model=deepseek_model(),
    tools=[call_subagent_1, call_subagent_2],
)

question = "What is the square root of 456?"
response = main_agent.invoke({"messages": [HumanMessage(content=question)]})

print(response["messages"][-1].content)
User

提出数学问题。

Main Agent

判断需要开方。

Wrapper Tool

调用开方子 Agent。

Subagent

调用底层工具并返回结果。

6 查看消息 trace

Notebook 最后用 pprint(response)model_dump() 查看消息细节。这一步能看到主 Agent 何时发起 tool call、tool 返回了什么、最终回答如何形成。

Python
pprint(response)
pprint(response["messages"][1])
pprint(response["messages"][0].model_dump(), sort_dicts=False)
pprint(response["messages"][1].model_dump(), sort_dicts=False)
调试重点

Multi-Agent 问题通常不是“模型不会回答”,而是“路由错了”或“子 Agent 返回值不适合主 Agent”。检查 trace 是最快定位方式。