Skip to main content
深度智能体可以创建子智能体来委派工作。你可以在 subagents 参数中指定自定义子智能体。子智能体适用于上下文隔离(保持主智能体的上下文清洁)以及提供专门的指令。 本页面涵盖同步子智能体,即主管智能体会阻塞直到子智能体完成。对于长时间运行的任务、并行工作流,或需要中途调整和取消的场景,请参阅异步子智能体

为什么使用子智能体?

子智能体解决了上下文膨胀问题。当智能体使用产生大量输出的工具(网络搜索、文件读取、数据库查询)时,上下文窗口很快会被中间结果填满。子智能体隔离这些详细工作——主智能体只接收最终结果,而非产生结果的大量工具调用。 何时使用子智能体:
  • 多步骤任务会使主智能体的上下文变得混乱
  • 需要自定义指令或工具的专门领域
  • 需要不同模型能力的任务
  • 当你希望主智能体专注于高层协调时
何时不使用子智能体:
  • 简单的单步骤任务
  • 当你需要维护中间上下文时
  • 当开销大于收益时

配置

subagents 应该是一个字典列表或 CompiledSubAgent 对象。有两种类型:

默认子智能体

深度智能体会自动添加一个同步的 general-purpose 子智能体,除非你已经提供了一个同名的同步子智能体。
  • 要替换它,请传入你自己的名为 general-purpose 的子智能体。
  • 要重命名或重新设置自动添加版本的提示词,请在活跃的 Harness 配置上设置 general_purpose_subagent=GeneralPurposeSubagentProfile(...)
  • 要禁用它,请参阅下面的不使用子智能体运行

不使用子智能体运行

要运行不带 task 工具的智能体,需要执行两个操作:
  1. 在活跃的 Harness 配置上设置 general_purpose_subagent=GeneralPurposeSubagentProfile(enabled=False)
  2. create_deep_agent 上不通过 subagents= 传入同步子智能体。
深度智能体仅在存在至少一个同步子智能体时才会附加 SubAgentMiddleware(和 task 工具)。当既没有默认的也没有调用者提供的子智能体时,智能体将在不委派的情况下运行。 异步子智能体不受影响——它们通过自己的中间件和工具流转,详见异步子智能体
不要尝试使用 excluded_middleware——SubAgentMiddleware 是必需的基础设施,将其列入会引发 ValueErrorgeneral_purpose_subagent.enabled = False 是受支持的方式。

SubAgent(基于字典)

对于大多数用例,将子智能体定义为符合 SubAgent 规范的字典,包含以下字段:
CLI 用户: 你也可以将子智能体定义为磁盘上的 AGENTS.md 文件,而非代码。namedescriptionmodel 字段映射到 YAML frontmatter,markdown 正文成为 system_prompt。参阅在 CLI 中使用子智能体了解文件格式。部署用户:subagents/ 下将子智能体定义为目录,包含自己的 deepagents.tomlAGENTS.md。打包工具会自动发现它们。参阅部署子智能体了解完整的配置参考。

CompiledSubAgent

对于复杂的工作流,使用预构建的 LangGraph 图作为 CompiledSubAgent

使用 SubAgent

使用 CompiledSubAgent

对于更复杂的用例,你可以使用 CompiledSubAgent 提供自定义子智能体。 你可以使用 LangChain 的 create_agent 创建自定义子智能体,或使用图 API 创建自定义 LangGraph 图。 如果你创建自定义 LangGraph 图,请确保图有一个名为 "messages" 的状态键

流式输出

在流式追踪信息中,智能体名称可作为元数据中的 lc_agent_name 获取。 在查看追踪信息时,你可以使用此元数据来区分数据来自哪个智能体。 以下示例创建了一个名为 main-agent 的深度智能体和一个名为 research-agent 的子智能体:
当你向深度智能体发出提示时,子智能体或深度智能体执行的所有智能体运行都会在其元数据中包含智能体名称。 在此例中,名为 "research-agent" 的子智能体在任何关联的智能体运行元数据中都会有 {'lc_agent_name': 'research-agent'} LangSmith 示例追踪,显示元数据

结构化输出

子智能体支持结构化输出,使父智能体接收可预测、可解析的 JSON 而非自由文本。
子智能体的结构化输出需要 deepagents>=0.5.3
在子智能体配置上传入 response_format。当子智能体完成时,其结构化响应会被 JSON 序列化并作为 ToolMessage 内容返回给父智能体。该模式接受 create_agent 支持的任何内容:Pydantic 模型、ToolStrategy(...)ProviderStrategy(...) 或原始模式类型。
如果没有 response_format,父级接收子智能体的最后消息文本原样。有了它,父级始终获得匹配模式的有效 JSON,这在父级需要以编程方式处理结果或将其传递给下游工具时非常有用。 有关模式类型和策略(工具调用 vs. 提供商原生)的完整详情,请参阅结构化输出

通用子智能体

除了用户定义的子智能体外,每个深度智能体始终可以访问一个 general-purpose 子智能体。该子智能体:
  • 与主智能体具有相同的系统提示词
  • 可以访问所有相同的工具
  • 使用相同的模型(除非被覆盖)
  • 当配置了技能时,继承主智能体的技能

覆盖通用子智能体

subagents 列表中包含一个 name="general-purpose" 的子智能体来替换默认的。用它来为通用子智能体配置不同的模型、工具或系统提示词:
当你提供一个同名的子智能体时,默认的通用子智能体不会被添加。你的规范完全替换它。 要完全移除内置的通用子智能体而非替换它,请将活跃 Harness 配置的通用子智能体 enabled 标志设置为 False

何时使用

通用子智能体非常适合不需要专门行为的上下文隔离。主智能体可以将复杂的多步骤任务委派给该子智能体,并获得简洁的结果,避免中间工具调用的膨胀。

示例

主智能体不必自己进行 10 次网络搜索并用结果填满上下文,而是委派给通用子智能体:task(name="general-purpose", task="Research quantum computing trends")。子智能体在内部执行所有搜索并只返回摘要。

技能继承

使用 create_deep_agent 配置技能时:
  • 通用子智能体:自动继承主智能体的技能
  • 自定义子智能体:默认继承技能——使用 skills 参数为它们提供自己的技能
只有配置了技能的子智能体才会获得 SkillsMiddleware 实例——没有 skills 参数的自定义子智能体不会获得。当存在时,技能状态在两个方向上完全隔离:父级的技能对子级不可见,子级的技能不会传播回父级。

最佳实践

编写清晰的描述

主智能体使用描述来决定调用哪个子智能体。要具体: 好的示例: "Analyzes financial data and generates investment insights with confidence scores" 差的示例: "Does finance stuff"

保持系统提示词详细

包含关于如何使用工具和格式化输出的具体指导:

最小化工具集

只给子智能体它们需要的工具。这可以提高专注度和安全性:

根据任务选择模型

不同的模型擅长不同的任务:

返回简洁的结果

指示子智能体返回摘要,而非原始数据:

常见模式

多个专门子智能体

为不同领域创建专门的子智能体:
工作流:
  1. 主智能体创建高层计划
  2. 将数据收集委派给 data-collector
  3. 将结果传递给 data-analyzer
  4. 将洞见发送给 report-writer
  5. 汇编最终输出
每个子智能体都以仅专注于其任务的清洁上下文工作。

上下文管理

当你使用运行时上下文调用父智能体时,该上下文会自动传播到所有子智能体。每个子智能体运行都会接收你在父级 invoke / ainvoke 调用中提供的相同运行时上下文。 这意味着在任何子智能体内运行的工具都可以访问你提供给父级的相同上下文值:

每个子智能体的上下文

所有子智能体接收相同的父级上下文。要传递特定于某个子智能体的配置,请在扁平 context 映射中使用命名空间键(用子智能体名称作为键前缀,例如 researcher:max_depth),在上下文类型上将这些设置建模为单独的字段:

识别哪个子智能体调用了工具

当同一个工具在父级和多个子智能体之间共享时,你可以使用 lc_agent_name 元数据(与流式输出中使用的值相同)来确定是哪个智能体发起了调用:
你可以结合两种模式——从 runtime.context 读取智能体特定的设置,从 runtime.config 元数据读取 lc_agent_name 来分支工具行为。

故障排除

子智能体未被调用

问题:主智能体试图自己完成工作而不是委派。 解决方案
  1. 使描述更具体:
  2. 指示主智能体进行委派:

上下文仍然膨胀

问题:尽管使用了子智能体,上下文仍然填满。 解决方案
  1. 指示子智能体返回简洁的结果:
  2. 使用文件系统处理大数据:

选择了错误的子智能体

问题:主智能体为任务调用了不恰当的子智能体。 解决方案:在描述中清楚地区分子智能体:
:::