子智能体进阶异步

1. 先判断,该用智能体还是工具

主智能体先通过 task 派活,子智能体拿到独立任务后自己完成推理和工具调用,最后只把结果交回主智能体。这样主智能体不用背着所有细节继续往下推理。

写子智能体之前,先问一个很实际的问题:这件事是否值得单独拆出一个助手?

如果答案是“是”,才继续配置它的 namedescriptionsystem_prompt 和 tools

2. 适合拆成子智能体的任务

场景 说明 示例
多步骤任务上下文很乱 中间过程多,主智能体容易被大量信息干扰 深度研究、多轮搜索、多源资料整合
存在不同专业领域 不同任务需要不同知识和工具 金融分析、法律检索、数据库查询
需要不同模型能力 某些任务可能需要多模态或更强模型 图片理解、长文档分析、代码生成
主智能体只做统筹 主智能体像项目经理,只负责分派和汇总 「深度研搜」的 Main Agent

3. 普通工具和子智能体的选择边界

任务类型 更适合的形式 原因
一次函数调用就能完成 普通工具 成本低、链路短、结果更稳定
查询天气、简单计算、格式转换 普通工具 逻辑边界清楚,不需要独立上下文
多步搜索、阅读、分析、归纳 子智能体 需要独立提示词、独立上下文和多步执行
带专属工具和复杂策略的任务 子智能体 方便限制工具权限,也方便单独调试

所以写代码前,更准确的判断标准不是“步骤多不多”,而是下面三个问题:

  • 这些步骤是否需要不同专业能力?
  • 这些步骤之间是否可以隔离上下文?
  • 拆开以后收益是否大于额外成本?

一句话总结:工具适合做确定的小动作,子智能体适合做需要思考的一段小任务

配置子智能体方式

  • 字典子智能体:配置一个简单助手。
  • CompiledSubAgent:把一个完整 Agent / Graph 封装成子智能体。

字典子智能体基本字段:

字段 作用 是否必填
name 子智能体名称,主智能体调用时会使用 必填
description 子智能体职责描述,主智能体靠它判断是否调用 必填
system_prompt 子智能体自己的系统提示词 常用
tools 子智能体可使用的工具列表 常用
model 子智能体使用的模型,不填则通常继承主智能体模型 可选

name 是子智能体的唯一标识。后面流式输出里看到 task 调用时,subagent_type 就会对应这个名称。

description 是主智能体判断任务归属的依据。如果描述写得模糊,主智能体就容易分派错。

本案例中定义了三个简单助手:天气助手、数学助手、翻译助手:

# 字典式子智能体的核心字段:
# name 是子智能体唯一标识,流式输出里的 subagent_type 会对应它;
# description 主要给主智能体看,用来判断什么时候应该调用该助手;
# system_prompt 是子智能体自己的角色和行为约束;
# tools 是该子智能体可用的工具列表,不填 model 时通常继承主智能体模型。
weather_agent = {"name": "weather_helper","description": "用于查询天气信息。当用户询问天气时,请调用此助手。","system_prompt": """你是一个天气查询助手。无论用户查询哪个城市,请统一回复:今天天气晴朗,温度25度。""","tools": [],
}math_agent = {"name": "math_helper","description": "用于处理数学计算问题。当用户询问加减乘除、数字计算、算数题时,请调用此助手。","system_prompt": """你是一个严谨的数学助手。请帮助用户完成数学计算,并给出清晰、准确的答案。""","tools": [],
}translate_agent = {"name": "translate_helper","description": "用于处理中英互译任务。当用户需要中文和英文之间的翻译时,请调用此助手。","system_prompt": """你是一个中英翻译助手。如果输入是中文,请翻译成英文;如果输入是英文,请翻译成中文。""","tools": [],
}

注册到主智能体:

 创建主智能体时,把这些字典放进 subagents 即可。

# 主智能体自己不挂普通工具,重点负责根据用户问题分派给合适的子智能体
main_agent = create_deep_agent(model=llm,tools=[],subagents=[weather_agent, math_agent, translate_agent],system_prompt="""你是一个负责统筹任务的主智能体。请根据用户需求选择合适的子智能体完成任务。你不直接执行天气查询、数学计算或翻译任务,而是通过子智能体完成。""",
)

系统提示词要说清楚主智能体的边界:它不是天气助手、数学助手或翻译助手本身,而是负责把任务交给合适的子智能体 

以天气查询这组输出为例,三行日志分别对应三件事:

输出片段 代表的含义
【model】决定调用子智能体weather_helper 主智能体判断这个问题应该交给天气助手处理
【agent】调用了具体的工具task DeepAgents 执行 task,也就是实际去调用子智能体
【model】返回最终结果 主智能体拿到子智能体结果后,再整理成最终回复给用户

后面分析 task 工具调用时,心里先记住这条线就可以:   用户问题 -> 主智能体选择子智能体 -> task 执行 -> 子智能体返回结果 -> 主智能体整理最终回复

子智能体本质上是task工具调用

主智能体并不是直接跳到某个子智能体里执行,而是先由模型做一次决策,在 DeepAgents 中,主智能体调用子智能体时,通常会表现为一次特殊工具调用: tool_call["name"] == "task"

它的参数里会说明两件事:

  • subagent_type:要调用哪个子智能体,对应前面配置里的 name
  • description:交给这个子智能体的具体任务。

也就是说,从主智能体视角看,子智能体是一种可调度能力。它不是普通 Python 函数工具,而是一个拥有独立提示词、独立工具集和独立上下文的 Agent。

image

子智能体并不是“凭空被调用”的。主智能体先请求模型判断下一步,模型返回 task 工具调用,DeepAgents 再根据 subagent_type 找到对应子智能体执行

还要补一个容易混淆的细节:子智能体不是普通工具,但它在主智能体眼里会像工具一样返回结果

原因是主智能体调用子智能体时,走的是 task 这个特殊工具。子智能体执行完以后,它的结果会回到主智能体这边,并且通常表现为一条 ToolMessage

一个“主智能体调用子智能体再回答”的简单流程,常见链路是:

主智能体模型:判断调用哪个子智能体 -> 子智能体模型:完成被分派的局部任务 -> 主智能体模型:整合子智能体结果并输出最终答案

这也是为什么子智能体比普通工具成本更高:普通工具通常只是一次函数或 API 调用,而子智能体本身还会走一段 Agent 执行过程

如何在流式输出里识别Task:

重点看 model 节点里最后一条消息的 tool_calls。普通工具调用和子智能体调用都会出现在这里,区别主要看工具名.

观察位置 普通工具调用 子智能体调用
tool_call["name"] 工具自己的名字,例如 internet_search 固定是 task
tool_call["args"] 普通工具的入参 包含 subagent_type 和 description
返回结果所在节点 tools 也是 tools,因为 task 本身表现为一个工具结果

所以在流式解析代码里,只要判断工具名是不是 task,就能区分“调用普通工具”和“分派子智能体”:

if tool_call["name"] == "task":print(f"调用子智能体:{tool_call['args']['subagent_type']}")
else:print(f"调用普通工具:{tool_call['name']}")