135.Agent-多Agent框架-LangChain多智能体(SubAgents子代理)

摘要 :本文深入解析 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的上下文,从而控制上下文膨胀

什么时候使用子代理

  1. 工具多到单个 Agent 管不过来时
    当可调用的工具从几个增加到几十个,单个 Agent 既要记住每个工具能做什么、参数怎么填、什么时候该调用,又要在执行时从一堆选项里挑对工具,很容易选错、漏调、重复调,上下文也会被各种工具说明塞满。这时就该按专业能力拆分,例如搜索类工具交给搜索子 Agent,代码执行交给代码子 Agent,数据库和文件操作交给数据子 Agent,消息通知交给通知子 Agent。主 Agent 只判断"这一步该派谁去办",而不是自己硬管所有工具。
  2. 提示词太长、任务太杂时
    当一个 Agent 的 Prompt 里同时塞了角色设定、行为规则、输出格式、多个任务、大量示例和背景资料,它会越来越难记住重点,容易忘规则、跑题、格式出错,甚至把不同任务的要求混在一起。更合适的做法是把相对独立的任务交给不同子 Agent,例如问答、写作、摘要、审核分别由专人处理。每个子 Agent 只拿自己需要的指令和材料,上下文复杂度自然下降。
  3. 需要多个专业领域协同时
    有些任务不是单一能力能完成的,比如既要联网搜索资料,又要写代码验证,还要整理成文案,最后再做质量检查。不同领域需要的知识、工具和输出标准都不一样,一个 Agent 很难同时精通。这时可以让搜索子 Agent 负责找信息,代码子 Agent 负责实现和验证,写作子 Agent 负责表达,审核子 Agent 负责挑错。各自负责擅长的部分,整体再由主 Agent 汇总。
  4. 任务需要分步骤执行时
    复杂任务往往有先后依赖,比如"调研 → 方案设计 → 实现 → 测试 → 总结"。如果全压在一个 Agent 身上,它容易在长流程里丢失中间状态,或者一步做错后面全错。把复杂任务拆成多个独立执行单元,每个单元交给一个子 Agent,主 Agent 按顺序调度,并在关键节点检查结果,这样更方便失败重试、局部替换和过程追踪。
  5. 需要统一控制执行流程时
    如果多个子 Agent 各自为政,可能会出现重复调用同一个工具、互相覆盖结果、执行顺序混乱、资源争抢等问题。为了避免这种自由竞争,应由主 Agent 统一做规划、分配任务、控制先后顺序,并负责最后的结果合并。子 Agent 只在自己那一环执行,不负责全局决策。
  6. 需要隔离上下文时
    不同任务可能涉及不同用户、不同项目、不同权限,或者资料太多、彼此干扰。如果所有信息都放在同一个上下文里,既容易污染,也可能越权访问。让每个子 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)

相关推荐
为你学会写情书1 小时前
Agent 能力评测——2026 年基准测试全景与模型真实能力画像
agent
lucas_AI1 小时前
别等上下文爆了才压缩:AutoCompact 教编码智能体主动「断舍离」
llm·agent
ACME20441 小时前
房产商业拍卖适用范围调查:五类物业能否上拍?
人工智能
用户3134672143541 小时前
Agent相关 - agent_scratchpad 到底该放哪?一个隐蔽的顺序坑
langchain·llm·agent
数商思语行1 小时前
从BA、产品、实施或开发转做FDE,先补哪种能力
人工智能·ai·供应链·商业分析·ontology·本体·fde
Elastic 中国社区官方博客1 小时前
错误最多的服务运行正常:使用 ES|QL 从日志进行根因分析
大数据·运维·数据库·sql·elasticsearch·搜索引擎·全文检索
代码简单说1 小时前
GPT Image 2.5 API 调用教程:Node.js 实现图片生成与编辑
人工智能
零基础1231 小时前
VoiceStudio 开源项目深度解析:特性、对比与实战测试
人工智能·经验分享·python·开源
故七月1 小时前
本地生活 GEO 内容质量风控体系构建 —— 基于陕西金贝儿母婴家政项目,万域智瞰 GEO 实践
人工智能·生活