subagents 参数中指定自定义子代理。子代理对于上下文隔离(保持主代理的上下文清晰)和提供专业指令非常有用。
为什么要使用子代理?
子代理解决了上下文膨胀问题。当代理使用具有大输出的工具(网络搜索、文件读取、数据库查询)时,上下文窗口会很快被中间结果填满。子代理隔离了这项详细工作——主代理只接收最终结果,而不是产生该结果的数十个工具调用。 何时使用子代理:- ✅ 会使主代理上下文混乱的多步骤任务
- ✅ 需要自定义指令或工具的专业领域
- ✅ 需要不同模型能力的任务
- ✅ 当您想让主代理专注于高层协调时
- ❌ 简单、单步任务
- ❌ 当您需要维护中间上下文时
- ❌ 当开销超过收益时
配置
subagents 应该是一个字典列表或 CompiledSubAgent 对象。有两种类型:
子代理 (基于字典)
对于大多数用例,将子代理定义为字典: 必填字段:- name (
str):子代理的唯一标识符。主代理在调用task()工具时使用此名称。 - description (
str):此子代理的功能。要具体且面向行动。主代理使用此项来决定何时委派。 - system_prompt (
str):子代理的指令。包括工具使用指南和输出格式要求。 - tools (
List[Callable]):子代理可以使用的工具。尽量保持最小化,只包含所需工具。
- model (
str | BaseChatModel):覆盖主代理的模型。使用格式"provider:model-name"(例如,"openai:gpt-4o")。 - middleware (
List[Middleware]):用于自定义行为、日志记录或速率限制的附加中间件。 - interrupt_on (
Dict[str, bool]):为特定工具配置人工干预。需要检查点。
CompiledSubAgent
对于复杂的工作流,请使用预构建的 LangGraph 图: 字段:- name (
str):唯一标识符 - description (
str):此子代理的功能 - runnable (
Runnable):已编译的 LangGraph 图(必须先调用.compile())
使用子代理
使用 CompiledSubAgent
对于更复杂的用例,您可以提供自己预构建的 LangGraph 图作为子代理通用子代理
除了任何用户定义的子代理之外,deep agents 始终可以访问一个general-purpose 子代理。此子代理
- 与主代理具有相同的系统提示
- 可以访问所有相同的工具
- 使用相同的模型(除非被覆盖)
何时使用
通用子代理非常适合上下文隔离而无需专门行为。主代理可以将复杂的、多步骤的任务委派给此子代理,并获得简洁的结果,而不会因中间工具调用而膨胀。示例
主代理不是进行 10 次网络搜索并用结果填充其上下文,而是委派给通用子代理:
task(name="general-purpose", task="研究量子计算趋势")。子代理在内部执行所有搜索,只返回一个摘要。最佳实践
编写清晰的描述
主代理使用描述来决定调用哪个子代理。要具体: ✅ 好:"分析财务数据并生成带有置信度评分的投资见解" ❌ 差: "做金融方面的事情"保持系统提示详细
包含有关如何使用工具和格式化输出的具体指导最小化工具集
只给子代理他们需要的工具。这提高了专注度和安全性按任务选择模型
不同的模型擅长不同的任务返回简洁的结果
指示子代理返回摘要,而不是原始数据常见模式
多个专业子代理
为不同的领域创建专业子代理- 主代理创建高级计划
- 将数据收集委派给数据收集器
- 将结果传递给数据分析器
- 将见解发送给报告撰写者
- 编译最终输出
故障排除
子代理未被调用
问题:主代理尝试自己完成工作而不是委派。 解决方案:-
使描述更具体
-
指示主代理进行委派
上下文仍然膨胀
问题:尽管使用了子代理,上下文仍然膨胀。 解决方案:-
指示子代理返回简洁的结果
-
使用文件系统处理大数据
选择了错误的子代理
问题:主代理为任务调用了不合适的子代理。 解决方案:在描述中清楚地区分各子代理:以编程方式连接这些文档到 Claude、VSCode 等,通过 MCP 获取实时答案。