摘要 :本文深入解析 LangChain 中的 SubAgents(子代理)多智能体模式。开篇借助架构图直观呈现主 Agent 与子 Agent 之间的协作机制,继而系统梳理该模式的四大核心特征------集中化、工具化、无状态设计及强制上下文隔离,并逐一阐述六种适合引入子代理的典型场景。随后,文章详细演示如何通过
create_agent创建子智能体,利用agent_as_tool将其封装为可复用的工具并挂载至主 Agent,最终以 Supervisor 统筹数学、英语、语文三位专家协同作业的完整 Python 示例收尾,帮助读者从原理到实践全面掌握这一架构。
内容参考于:图灵AI大模型全栈
官网地址:https://docs.langchain.com/oss/python/langchain/multi-agent/subagents
下方是SubAgents模式的架构图,User是我们向Agent提出的问题,MainAgent就是管理员Agent(主Agent),由它分析任务,调用 SubAgetn Agent(子Agent),子Agent它只返回结果,并不会记住之前做过什么,所有的记忆都是由主Agent提供,User response是主Agent整合子Agent的返回内容生成的最终答案

特征
集中化:子Agent之间没办法互相通信,只有主Agent才能跟子Agent进行通信,这样可以集中管理
工具化:子Agent就相当于被封装成了工具,主Agent可以调用这些启动这些工具
无状态设计:子Agent每次调用时都是全新的,它不会记得之前的交互,异步的子Agent它会有状态,可以在后台长时间运行
强制上下文隔离:子Agent它的上下文是独立的,子Agent只会返回结果,所以多次被主Agent调用不会污染主Agent的上下文,从而控制上下文膨胀
什么时候使用子代理
- 工具多到单个 Agent 管不过来时
当可调用的工具从几个增加到几十个,单个 Agent 既要记住每个工具能做什么、参数怎么填、什么时候该调用,又要在执行时从一堆选项里挑对工具,很容易选错、漏调、重复调,上下文也会被各种工具说明塞满。这时就该按专业能力拆分,例如搜索类工具交给搜索子 Agent,代码执行交给代码子 Agent,数据库和文件操作交给数据子 Agent,消息通知交给通知子 Agent。主 Agent 只判断"这一步该派谁去办",而不是自己硬管所有工具。- 提示词太长、任务太杂时
当一个 Agent 的 Prompt 里同时塞了角色设定、行为规则、输出格式、多个任务、大量示例和背景资料,它会越来越难记住重点,容易忘规则、跑题、格式出错,甚至把不同任务的要求混在一起。更合适的做法是把相对独立的任务交给不同子 Agent,例如问答、写作、摘要、审核分别由专人处理。每个子 Agent 只拿自己需要的指令和材料,上下文复杂度自然下降。- 需要多个专业领域协同时
有些任务不是单一能力能完成的,比如既要联网搜索资料,又要写代码验证,还要整理成文案,最后再做质量检查。不同领域需要的知识、工具和输出标准都不一样,一个 Agent 很难同时精通。这时可以让搜索子 Agent 负责找信息,代码子 Agent 负责实现和验证,写作子 Agent 负责表达,审核子 Agent 负责挑错。各自负责擅长的部分,整体再由主 Agent 汇总。- 任务需要分步骤执行时
复杂任务往往有先后依赖,比如"调研 → 方案设计 → 实现 → 测试 → 总结"。如果全压在一个 Agent 身上,它容易在长流程里丢失中间状态,或者一步做错后面全错。把复杂任务拆成多个独立执行单元,每个单元交给一个子 Agent,主 Agent 按顺序调度,并在关键节点检查结果,这样更方便失败重试、局部替换和过程追踪。- 需要统一控制执行流程时
如果多个子 Agent 各自为政,可能会出现重复调用同一个工具、互相覆盖结果、执行顺序混乱、资源争抢等问题。为了避免这种自由竞争,应由主 Agent 统一做规划、分配任务、控制先后顺序,并负责最后的结果合并。子 Agent 只在自己那一环执行,不负责全局决策。- 需要隔离上下文时
不同任务可能涉及不同用户、不同项目、不同权限,或者资料太多、彼此干扰。如果所有信息都放在同一个上下文里,既容易污染,也可能越权访问。让每个子 Agent 只维护自己的上下文和能力边界,只接触完成自己任务所需的信息,可以避免无关内容互相影响,也方便控制权限。
代码说明
如下图红框,它通过 create_agent 正常创建一个智能体,每个create_agent里的参数不一样
然后工具,工具的创建是需要写工具的作用描述和入参,这里通过写一个 agent_as_tool 函数返回一个LangChain工具函数,这样就不需要重复编写工具函数的逻辑,只需要对agent_as_tool 函数传递不同写工具的描述就可以了,然后工具的返回值是invoke的返回值,也就是Agent的返回结果,没有Agent的思考过程,如下图红框
如下图蓝框把工具添加到主Agent,下图红框是通过 agent_as_tool 函数返回的不同描述的工具函数
效果图:

代码
python
# -*- coding: utf-8 -*-
"""
Supervisor + 子专家多智能体示例。
整体结构:
用户
↓
Supervisor 主管智能体
├── math_expert 数学专家
├── english_expert 英语专家
└── chinese_expert 语文专家
核心思路:
1. 先创建多个"子 Agent",每个子 Agent 只负责一个领域;
2. 使用 agent_as_tool 把子 Agent 包装成普通 Tool;
3. Supervisor 只看到这些 Tool,根据用户需求决定调用哪个专家;
4. Tool 内部再调用对应的子 Agent,从而形成多智能体协作。
依赖示例:
pip install python-dotenv langchain langchain-qwq langchain-tavily numexpr
"""
import os
from dotenv import load_dotenv
from langchain.tools import tool
from langchain.agents import create_agent
from langchain_qwq import ChatQwen
from langchain_tavily import TavilySearch
# =====================================================
# 初始化模型
# =====================================================
# 从 .env 文件加载环境变量,例如:
# DASHSCOPE_API_KEY、DASHSCOPE_BASE_URL、TAVILY_API_KEY
load_dotenv()
model = ChatQwen(
model="qwen3.7-flash", # 使用的通义千问模型名称
api_key=os.getenv("DASHSCOPE_API_KEY"), # 从环境变量读取 DashScope API Key
base_url=os.getenv("DASHSCOPE_BASE_URL"), # 从环境变量读取服务地址
thinking_budget=16, # 推理/思考预算参数,具体含义由 langchain_qwq 决定
)
# =====================================================
# 数学工具
# =====================================================
@tool
def calculator(expression: str) -> str:
"""
执行数学计算。
参数:
expression: 数学表达式字符串,例如 "(52+18)*2"
返回:
计算结果字符串;如果失败,返回错误信息。
"""
import numexpr # 延迟导入:只有真正调用计算器时才加载 numexpr
try:
# numexpr.evaluate 返回 numpy 标量或数组;
# .item() 将单元素结果转成 Python 原生数值。
return str(numexpr.evaluate(expression).item())
except Exception as e:
# 捕获表达式错误、除零等异常,避免整个 Agent 崩溃
return f"计算失败:{e}"
# =====================================================
# 语文工具 - 搜索
# =====================================================
# Tavily 搜索工具:语文专家在需要素材、背景知识时调用。
# 通常需要配置环境变量 TAVILY_API_KEY。
search_tool = TavilySearch()
# =====================================================
# 数学专家
# =====================================================
math_agent = create_agent(
model=model, # 所有子 Agent 共用同一个底层大模型
tools=[calculator], # 数学专家可以使用计算器工具
system_prompt="""
你是数学专家。
职责:
- 数学计算
- 数值推导
- 公式计算
要求:
遇到计算优先调用 calculator。
禁止:
翻译。
写作文。
"""
)
# =====================================================
# 英语专家
# =====================================================
english_agent = create_agent(
model=model,
tools=[], # 英语专家不需要外部工具,直接依靠模型翻译和润色
system_prompt="""
你是英语专家。
职责:
- 中译英
- 英译中
- 英文润色
要求:
保持准确。
禁止:
做数学计算。
写文章。
"""
)
# =====================================================
# 语文专家
# =====================================================
chinese_agent = create_agent(
model=model,
tools=[search_tool], # 语文专家可以搜索素材
system_prompt="""
你是语文专家。
职责:
- 写作
- 扩写
- 总结
- 搜集素材
要求:
如果需要背景知识:
优先搜索。
禁止:
修改数学结果。
"""
)
# =====================================================
# Agent 包装成 Tool
# =====================================================
def agent_as_tool(
name: str,
title: str,
description: str,
agent,
):
"""
将子 Agent 包装成 Supervisor 可调用的 Tool。
为什么需要包装?
Supervisor 本身也是一个 Agent,它只能调用 Tool;
而子专家也是 Agent。
因此这里做一个适配层:
Tool -> 调用子 Agent -> 返回子 Agent 的结果。
参数:
name: 工具名称,Supervisor 通过它调用,例如 "math_expert"
title: 工具中文标题,用于返回结果展示,例如 "数学专家"
description: 工具描述,帮助 Supervisor 判断何时调用
agent: 被包装的子 Agent 实例
返回:
一个 LangChain Tool 函数
"""
@tool(name, description=description)
def execute(request: str) -> str:
"""
调用子智能体。
参数:
request: 交给子 Agent 的具体任务描述
返回:
带有专家标题和子 Agent 执行结果的文本
"""
print(f"\n开始执行:{name}") # 调试日志:记录哪个专家开始执行
# 把 Supervisor 传来的 request 包装成标准 messages 格式,
# 然后交给子 Agent 处理。
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": request
}
]
}
)
# 取子 Agent 最后一条消息作为最终结果。
# 注意:这里使用单引号访问字典,避免 f-string 内外引号冲突。
final_content = result["messages"][-1].content
print(f"完成执行:{name}, 结果:{final_content}") # 调试日志
# 返回给 Supervisor 的文本。Supervisor 会把它当作工具调用结果。
return f"""
【{title}】已完成任务:
执行结果:{final_content}
"""
return execute
# 将三个子 Agent 分别包装成 Tool,供 Supervisor 调用
math_tool = agent_as_tool(
name="math_expert",
title="数学专家",
description="数学专家智能体,负责数学计算",
agent=math_agent,
)
english_tool = agent_as_tool(
name="english_expert",
title="英语专家",
description="英语专家智能体,负责翻译",
agent=english_agent,
)
chinese_tool = agent_as_tool(
name="chinese_expert",
title="语文专家",
description="语文专家智能体,负责写作",
agent=chinese_agent,
)
# =====================================================
# Supervisor
# =====================================================
# Supervisor 是"主管 Agent":
# 它不直接解决问题,而是根据用户需求选择并调用上面的专家工具。
supervisor = create_agent(
model=model,
tools=[
math_tool,
english_tool,
chinese_tool,
],
system_prompt="""
你是教育领域 Supervisor。
职责:
分析用户需求。
决定调用哪个专家。
可调用:
1.数学专家 math_tool
2.英语专家 english_tool
3.语文专家 chinese_tool
禁止:
自己直接回答问题。
最终汇总结果。
"""
)
# =====================================================
# 运行
# =====================================================
if __name__ == "__main__":
# 示例任务同时涉及"写故事"和"翻译":
# 预期 Supervisor 会调用语文专家写中文故事,再调用英语专家翻译。
user_input = """
帮我写一个猫咪的故事,字数控制在100字,并把故事翻译成英文
"""
# 启动 Supervisor,传入用户消息。
result = supervisor.invoke(
{
"messages": [
{
"role": "user",
"content": user_input,
}
]
}
)
# 打印最终结果:通常取最后一条消息作为输出。
print("\n")
print("=" * 80)
print(result["messages"][-1].content)



