Skip to main content
子智能体架构中,一个中央主智能体(通常称为监督者)通过将子智能体作为工具调用来协调它们。主智能体决定调用哪个子智能体、提供什么输入以及如何组合结果。子智能体是无状态的——它们不记住过去的交互,所有对话记忆由主智能体维护。这提供了上下文隔离:每次子智能体调用在干净的上下文窗口中工作,防止主对话中的上下文膨胀。 有关内置子智能体支持,请参阅 Deep Agents

关键特征

  • 集中控制:所有路由通过主智能体
  • 无直接用户交互:子智能体将结果返回给主智能体而非用户(不过你可以在子智能体中使用中断来允许用户交互)
  • 通过工具调用子智能体:子智能体通过工具被调用
  • 并行执行:主智能体可以在单轮中调用多个子智能体
监督者 vs. 路由器:监督者智能体(此模式)与路由器不同。监督者是一个完整的智能体,它维护对话上下文并跨多轮动态决定调用哪些子智能体。路由器通常是一个单一的分类步骤,将请求分发给智能体而不维护持续的对话状态。

何时使用

当你有多个不同的领域(例如日历、邮件、CRM、数据库)、子智能体不需要直接与用户对话,或者你想要集中的工作流控制时,使用子智能体模式。对于只有少量工具的简单情况,使用单个智能体
需要在子智能体中与用户交互? 虽然子智能体通常将结果返回给主智能体而不是直接与用户对话,但你可以在子智能体中使用中断来暂停执行并收集用户输入。当子智能体在继续之前需要澄清或批准时,这很有用。主智能体仍然是编排者,但子智能体可以在任务中途收集用户信息。

基本实现

核心机制是将子智能体包装为主智能体可以调用的工具:

教程:使用子智能体构建个人助手

学习如何使用子智能体模式构建个人助手,其中中央主智能体(监督者)协调专业的工作智能体。

设计决策

实现子智能体模式时,你需要做出几个关键设计选择。下表总结了各选项——每个都在下面的章节中详细介绍。

同步 vs. 异步

子智能体执行可以是同步的(阻塞)或异步的(后台)。你的选择取决于主智能体是否需要结果才能继续。
不要与 Python 的 async/await 混淆。这里的”异步”意味着主智能体启动后台任务(通常在单独的进程或服务中)并继续而不阻塞。

同步(默认)

默认情况下,子智能体调用是同步的:主智能体等待每个子智能体完成后再继续。当主智能体的下一步操作依赖于子智能体的结果时,使用同步。 何时使用同步:
  • 主智能体需要子智能体的结果来制定响应
  • 任务有顺序依赖(例如获取数据 → 分析 → 响应)
  • 子智能体失败应阻止主智能体的响应
权衡:
  • 实现简单——只需调用并等待
  • 用户在所有子智能体完成之前看不到响应
  • 长时间运行的任务会冻结对话

异步

当子智能体的工作是独立的时,使用异步执行——主智能体不需要结果就能继续与用户对话。主智能体启动后台任务并保持响应性。 何时使用异步:
  • 子智能体的工作独立于主对话流
  • 用户应该能在工作进行时继续聊天
  • 你想并行运行多个独立任务
三工具模式:
  1. 启动任务:启动后台任务,返回任务 ID
  2. 检查状态:返回当前状态(pending、running、completed、failed)
  3. 获取结果:检索完成的结果
处理任务完成: 当任务完成时,你的应用需要通知用户。一种方法:显示一个通知,点击后发送类似”检查 job_123 并总结结果”的 HumanMessage

工具模式

有两种主要方式将子智能体暴露为工具:

每个智能体一个工具

核心思想是将子智能体包装为主智能体可以调用的工具:
主智能体在决定任务匹配子智能体的描述时调用子智能体工具,接收结果,然后继续编排。有关精细控制,请参阅上下文工程

单一调度工具

另一种方法使用单个参数化工具来调用临时子智能体执行独立任务。与每个智能体一个工具方法(每个子智能体都包装为单独的工具)不同,这使用基于约定的方法和单个 task 工具:任务描述作为人类消息传递给子智能体,子智能体的最终消息作为工具结果返回。 当你想跨多个团队分配智能体开发、需要将复杂任务隔离到单独的上下文窗口中、需要一种可扩展的方式添加新智能体而无需修改协调器,或者偏好约定优于自定义时,使用此方法。此方法用上下文工程的灵活性换取了智能体组合的简单性和强大的上下文隔离。 关键特征:
  • 单一 task 工具:一个可按名称调用任何注册子智能体的参数化工具
  • 基于约定的调用:按名称选择智能体,任务作为人类消息传递,最终消息作为工具结果返回
  • 团队分发:不同团队可以独立开发和部署智能体
  • 智能体发现:子智能体可以通过系统提示词(列出可用智能体)或通过渐进式披露(通过工具按需加载智能体信息)来发现
此方法的一个有趣方面是子智能体可能与主智能体具有完全相同的能力。在这种情况下,调用子智能体实际上主要是为了上下文隔离——允许复杂的多步骤任务在隔离的上下文窗口中运行,而不会膨胀主智能体的对话历史。子智能体自主完成工作并仅返回简洁的摘要,保持主线程的专注和高效。

上下文工程

控制上下文如何在主智能体和其子智能体之间流动: 另请参阅我们关于智能体上下文工程的全面指南。

子智能体规格

与子智能体关联的名称描述是主智能体了解要调用哪些子智能体的主要方式。这些是提示词杠杆——请仔细选择。
  • 名称:主智能体如何引用子智能体。保持清晰和面向操作(例如 research_agentcode_reviewer)。
  • 描述:主智能体了解子智能体能力的信息。具体说明它处理什么任务以及何时使用它。
对于单一调度工具设计,你还需要为主智能体提供关于它可以调用的子智能体的信息。 你可以根据智能体数量以及注册表是静态还是动态的,以不同方式提供此信息:

系统提示词枚举

直接在主智能体的系统提示词中列出可用智能体。主智能体在其指令中看到智能体列表及其描述。 何时使用:
  • 你有少量固定的智能体(< 10 个)
  • 智能体注册表很少变化
  • 你想要最简单的实现
示例:

调度工具上的枚举约束

在调度工具的 agent_name 参数上添加枚举约束。这提供了类型安全性并使可用智能体在工具模式中明确。 何时使用:
  • 你有少量固定的智能体(< 10 个)
  • 你想要类型安全和明确的智能体名称
  • 你偏好基于模式的验证而非基于提示词的指导
示例:

基于工具的发现

提供一个单独的工具(例如 list_agentssearch_agents),主智能体可以调用它来按需发现可用智能体。这启用了渐进式披露并支持动态注册表。 何时使用:
  • 你有许多智能体(> 10 个)或不断增长的注册表
  • 智能体注册表频繁变化或是动态的
  • 你想减少提示词大小和 Token 用量
  • 不同团队独立管理不同智能体
示例:

子智能体输入

自定义子智能体接收什么上下文来执行其任务。添加无法在静态提示词中捕获的输入——完整消息历史、先前结果或任务元数据——通过从智能体状态中提取。
Subagent inputs example

子智能体输出

自定义主智能体接收回什么,以便它能做出好的决策。两种策略:
  1. 提示子智能体:指定应该返回什么。一个常见的失败模式是子智能体执行工具调用或推理但不在最终消息中包含结果——提醒它监督者只能看到最终输出。
  2. 在代码中格式化:在返回之前调整或丰富响应。例如,使用 Command 除了最终文本外还传回特定状态键。
Subagent outputs example

检查点和状态检查

默认情况下,子智能体使用继承的检查点器模式——每次调用从新状态开始,支持中断,并安全地并行运行。如果你需要子智能体跨调用维护自己的持久化对话历史,请使用 checkpointer=True(延续模式)编译它。有关模式的完整比较,请参阅子图持久化 因为子智能体在工具函数内部被调用,LangGraph 无法静态发现它们。这意味着带 subgraphsget_state 不会返回子智能体状态。如果你需要读取嵌套图状态(例如在中断期间),请在自定义图中从节点函数调用子智能体。有关每种模式如何影响状态可见性的详情,请参阅子图持久化