DeepAgent 多 Agent 架构设计文档
文档范围 :基于
deepagents/graph.py+deepagents/middleware/subagents.py的源码分析,覆盖 DeepAgent 框架中多 Agent 协作的完整设计------从 API 定义、构建流程、运行时行为,到状态隔离与结果回传机制。目标读者:使用 DeepAgent 框架构建多 Agent 系统的工程师,或希望深入理解框架内部机制的技术人员。
目录
- 核心概念与术语
- 整体架构概览
- [子 Agent 类型:SubAgent vs CompiledSubAgent](#子 Agent 类型:SubAgent vs CompiledSubAgent)
- 构建流程:从声明到可运行对象
- [内置子 Agent:general-purpose](#内置子 Agent:general-purpose)
- 运行时流程:任务委托与结果回传
- [SubAgentMiddleware 深度解析](#SubAgentMiddleware 深度解析)
- [_build_task_tool 路由引擎解析](#_build_task_tool 路由引擎解析)
- 状态管理:隔离与传递
- [多子 Agent 并行协作](#多子 Agent 并行协作)
- 完整数据流总览
- 附录:关键常量与接口定义
1. 核心概念与术语
| 术语 | 定义 |
|---|---|
| 主 Agent (Main Agent) | 由 create_deep_agent() 构建的顶层 Agent,持有 task 工具,负责任务分发与结果汇总 |
| 子 Agent (SubAgent) | 由主 Agent 通过 task 工具委托的执行单元,独立运行完成具体任务后返回结果 |
| SubAgent (TypedDict) | 声明式配置描述字典,由框架自动编译为可运行对象 |
| CompiledSubAgent (TypedDict) | 用户自行编译好的可运行对象封装,框架直接使用 |
| spec | subagents 列表中的每个元素,类型为 `SubAgent |
| _SubagentSpec | 框架内部统一产物,包含 name、description、runnable 三个字段 |
| task tool | 注入到主 Agent 的 StructuredTool,是 LLM 调用子 Agent 的唯一入口 |
| SubAgentMiddleware | 核心中间件,负责构建子 Agent、注册路由表、生成 task tool 并注入系统提示 |
| _EXCLUDED_STATE_KEYS | 父子 Agent 间隔离的 state 字段集合,防止状态污染 |
| Command | LangGraph 原语,携带 update 字典直接修改图的 state,子 Agent 用此回传结果 |
| middleware 栈 | 按顺序组合的中间件链,在 LLM 调用前后注入额外能力(工具、提示、摘要等) |
| ephemeral 执行 | 子 Agent 每次调用都是独立无状态的,只返回最终结果,内部推理过程不暴露给父 Agent |
2. 整体架构概览
2.1 系统架构图
主 Agent (Main Agent)
注册 task tool
路由
invoke
invoke
invoke
invoke
invoke
👤 用户 (User)
- TodoListMiddleware
- MemoryMiddleware (可选)
- SkillsMiddleware (可选)
- FilesystemMiddleware
- SubAgentMiddleware ⭐
- SummarizationMiddleware
- AnthropicPromptCachingMiddleware
- PatchToolCallsMiddleware
- 用户自定义 middleware (可选)
🔧 task(subagent_type, description)
子 Agent 注册表
{ name → Runnable }
general-purpose
(内置,永远存在)
自定义 SubAgent 1
自定义 SubAgent 2
CompiledSubAgent N
ToolMessage
ToolMessage
ToolMessage
ToolMessage
2.2 设计原则
| 原则 | 说明 |
|---|---|
| 扁平化注册 | 所有子 Agent 在同一注册表中,无层级嵌套,路由逻辑统一 |
| 语义路由 | 主 Agent LLM 根据各子 Agent 的 description 自主决策路由,无硬编码规则 |
| 状态隔离 | 父子 Agent 之间通过 _EXCLUDED_STATE_KEYS 隔离敏感状态,防止上下文污染 |
| ephemeral 调用 | 子 Agent 执行完毕只返回最终结论,内部多步推理过程对父 Agent 不可见 |
| 向后兼容 | 同时支持旧 API(default_model)和新 API(backend),旧 API 发出弃用警告 |
3. 子 Agent 类型:SubAgent vs CompiledSubAgent
3.1 类型定义对比
| 维度 | SubAgent |
CompiledSubAgent |
|---|---|---|
| 本质 | 声明式配置描述字典 | 已编译好的可运行对象封装 |
| 关键字段 | name, description, system_prompt, tools, model, middleware, skills |
name, description, runnable |
| 构建方式 | 框架内部调用 create_agent() 自动构建 |
用户自行构建,框架直接使用 |
| middleware | 框架自动注入标准中间件栈(TodoList / Filesystem / Summarization / PromptCaching / PatchToolCalls) | 完全由用户控制,框架不注入任何中间件 |
| state 保证 | 框架自动保证 | 用户必须确保 state 含有 messages key |
| 灵活性 | 较低,遵守框架约定 | 极高,可使用任意 LangGraph StateGraph |
| 适用场景 | 快速定义功能专属子 Agent | 复用已有 Agent,或需要完全自定义内部结构 |
3.2 区分判断逻辑
框架在两处对 spec 进行遍历处理,均以 "runnable" in spec 作为唯一区分依据:
create_deep_agent()(graph.py第 224 行):预处理阶段,为SubAgent类型的 spec 填充默认 model / middleware;CompiledSubAgent直接透传。SubAgentMiddleware._get_subagents()(subagents.py第 629 行):构建阶段,根据 spec 类型决定是否调用create_agent()。
Yes → CompiledSubAgent
No → SubAgent
spec 可能包含的字段
SubAgent 字段
name, description, system_prompt
tools, model, middleware, skills
CompiledSubAgent 字段
name, description, runnable
subagents 列表中的每个元素
spec: SubAgent | CompiledSubAgent
'runnable' in spec ?
直接透传 runnable
不注入 middleware
不调用 create_agent()
框架调用 create_agent() 构建
自动注入标准 middleware 栈
TodoList + Filesystem + Summarization
- PromptCaching + PatchToolCalls
统一产物: _SubagentSpec
{name, description, runnable}
4. 构建流程:从声明到可运行对象
4.1 SubAgent 构建时序
主 Agent (LLM) task tool create_agent() SubAgentMiddleware create_deep_agent() 用户 主 Agent (LLM) task tool create_agent() SubAgentMiddleware create_deep_agent() 用户 预处理 SubAgent(graph.py) ① 继承主 Agent model(若未指定) ② 自动注入标准 middleware 栈: TodoList + Filesystem + Summarization + PromptCaching + PatchToolCalls ③ 追加用户自定义 middleware _get_subagents() 检测到无 'runnable' 字段 → SubAgent create_deep_agent(subagents=[SubAgent]) 传入 processed_spec(含完整 middleware) create_agent(model, system_prompt, tools, middleware) CompiledStateGraph (Runnable) _build_task_tool({name: runnable}) 注入 task tool(含子 Agent 描述)
4.2 CompiledSubAgent 构建时序
主 Agent (LLM) task tool SubAgentMiddleware create_deep_agent() 用户 主 Agent (LLM) task tool SubAgentMiddleware create_deep_agent() 用户 检测到 'runnable' in spec 直接透传,不做任何处理 _get_subagents() 检测到有 'runnable' 字段 → 直接使用 ⚠️ 不注入任何 middleware ⚠️ 不调用 create_agent() 自行构建 agent = StateGraph(...).compile() create_deep_agent(subagents=[CompiledSubAgent(runnable=agent)]) 透传 CompiledSubAgent(原样) _build_task_tool({name: compiled_runnable}) 注入 task tool(含子 Agent 描述)
4.3 两种类型构建流程对比
CompiledSubAgent 构建流程
SubAgent 构建流程
SubAgent
{name, description,
system_prompt, tools, model}
create_deep_agent 预处理
注入标准 middleware 栈
SubAgentMiddleware._get_subagents()
create_agent() → Runnable
CompiledSubAgent
{name, description, runnable}
直接透传
不做任何处理
SubAgentMiddleware._get_subagents()
直接使用 runnable
task tool 注册表
{name → Runnable}
5. 内置子 Agent:general-purpose
5.1 来源与构建
general-purpose 是框架在 create_deep_agent 中强制内置 的子 Agent,无论用户是否传入 subagents 参数,它始终存在且排在注册表首位:
追加到后面
永远排在首位
general-purpose 构建(强制内置)
GENERAL_PURPOSE_SUBAGENT
{name, description, system_prompt}
注入运行时属性
-
model = 主 Agent model
-
tools = 主 Agent tools
-
middleware = 标准栈
create_deep_agent()
子 Agent 注册表
用户自定义 subagents(可选)
5.2 与自定义子 Agent 的协作关系
无匹配专用 Agent 时 / 通用任务
任务匹配 description 时
结果
结果
用户自定义子 Agent
researcher
专注:文献搜索
code-reviewer
专注:代码审查
data-analyst
专注:数据分析
general-purpose(内置)
通用型
能力 = 主 Agent 全量能力
处理任何多步骤任务
主要用于上下文隔离
主 Agent LLM
(任务分发者)
5.3 核心价值
| 使用场景 | 说明 |
|---|---|
| 上下文隔离 | 把重型任务卸载给子 Agent,避免主 Agent 上下文被大量中间步骤撑爆 |
| 并行执行 | 多个独立任务同时派给不同子 Agent,主 Agent 汇总结果 |
| 兜底通用 | 没有匹配专用 Agent 时的默认选择,能力与主 Agent 完全相同 |
| Token 节省 | 子 Agent 深度执行后只返回摘要,主线程只看最终结论 |
6. 运行时流程:任务委托与结果回传
6.1 单次 task 调用完整时序
父 Agent State 子 Agent Runnable subagent_graphs 注册表 task() 闭包函数 主 Agent (LLM) 父 Agent State 子 Agent Runnable subagent_graphs 注册表 task() 闭包函数 主 Agent (LLM) alt [subagent_type 不存在] 从父 state 复制并过滤 重置 messages=[HumanMessage(description)] 子 Agent 独立运行 可能调用多个工具、多轮推理 (内部过程对父 Agent 不可见) 取 messages[-1].text.rstrip() 包装为 ToolMessage + Command state 被 Command 更新 主 Agent 收到 ToolMessage 继续推理 task(description="分析代码", subagent_type="code-reviewer") "code-reviewer" in subagent_graphs? 未找到 错误字符串:"只允许 general-purpose, researcher, ..." 校验 runtime.tool_call_id 存在 _validate_and_prepare_state() subagent.invoke(subagent_state) result dict(含 messages) _return_command_with_state_update() Command(update={messages: [ToolMessage], ...})
6.2 运行时判断逻辑
No
Yes
No
Yes
主 Agent LLM 生成 tool call
task(subagent_type='X', description='...')
subagent_type 在
注册表中?
返回错误字符串
告知合法类型列表
runtime.tool_call_id
存在?
raise ValueError
_validate_and_prepare_state()
① 从 runtime.state 复制父 Agent 状态
② 过滤掉 _EXCLUDED_STATE_KEYS
③ 重置 messages = [HumanMessage(description)]
subagent.invoke(subagent_state)
子 Agent 独立运行,完成任务
_return_command_with_state_update()
① 提取 result['messages'][-1].text
② 构建 ToolMessage(text, tool_call_id)
③ 合并非排除字段的 state 更新
④ 返回 LangGraph Command(update={...})
主 Agent state 被 Command 更新
主 Agent 收到 ToolMessage 继续推理
7. SubAgentMiddleware 深度解析
7.1 职责概述
SubAgentMiddleware 是整个多 Agent 协作机制的核心枢纽 ,继承自 AgentMiddleware。其唯一职责是:把若干子 Agent 包装成 task 工具,注入到主 Agent 的工具列表和系统提示中,使主 Agent LLM 能感知并调用子 Agent。
7.2 初始化阶段(__init__)
初始化时完成三件一次性工作:
③ 构建系统提示追加内容
TASK_SYSTEM_PROMPT
(何时用 / 如何用 task tool)
追加 Available subagent types 列表
self.system_prompt = 拼接结果
② 构建 task StructuredTool
_build_task_tool()
subagent_graphs = {name: runnable}
生成 tool description
含所有 Agent 的 name + description
闭包封装 task() / atask()
同步 + 异步双实现
StructuredTool.from_function(name='task')
① 构建子 Agent Runnable
_get_subagents()
Yes
No
遍历 subagents 列表
runnable in spec?
CompiledSubAgent:直接取 runnable
SubAgent:调用 create_agent()
构建 CompiledStateGraph
_SubagentSpec
{name, description, runnable}
SubAgentMiddleware.init()
self.tools = [task_tool]
7.3 运行时阶段:拦截每次 LLM 调用
SubAgentMiddleware 实现了 wrap_model_call / awrap_model_call,在每次主 Agent 调用 LLM 之前,将子 Agent 使用说明追加到 system message:
主 Agent LLM SubAgentMiddleware 主 Agent 执行引擎 主 Agent LLM SubAgentMiddleware 主 Agent 执行引擎 append_to_system_message() 将 TASK_SYSTEM_PROMPT + Available subagent types 追加到 request.system_message 末尾 wrap_model_call(request, handler) handler(request.override(system_message=新 system_msg)) ModelResponse(可能含 task tool call) 返回 ModelResponse
7.4 API 兼容性处理
Yes
No
Yes
No
SubAgentMiddleware.init()
backend 参数
存在?
default_model
参数存在?(已废弃)
新 API
backend + subagents
调用 self._get_subagents()
旧 API(已废弃)
调用 _get_subagents_legacy()
发出 DeprecationWarning
raise ValueError
必须提供 backend 或 default_model
7.5 职责汇总
| 职责 | 实现方式 | 时机 |
|---|---|---|
| 构建子 Agent | _get_subagents() → create_agent() 或直接取 runnable |
__init__ |
| 注册子 Agent | subagent_graphs = {name: runnable} 闭包 |
__init__ |
| 生成 task tool | _build_task_tool() → StructuredTool |
__init__ |
| 注入工具到主 Agent | self.tools = [task_tool] |
__init__ |
| 修改系统提示 | wrap_model_call() 追加 TASK_SYSTEM_PROMPT + Agent 列表 |
每次 LLM 调用前 |
| 状态隔离 | 过滤 _EXCLUDED_STATE_KEYS,重置 messages |
每次 task 调用时 |
| 结果回传 | Command(update={messages: [ToolMessage]}) |
子 Agent 执行完毕后 |
8. _build_task_tool 路由引擎解析
8.1 定位
_build_task_tool 是整个多 Agent 机制的路由引擎 。它接收所有已编译好的子 Agent,通过闭包 维护 { name → Runnable } 注册表,最终产出名为 task 的 StructuredTool,供主 Agent LLM 调用。
list[_SubagentSpec]
每项含 name / description / runnable
_build_task_tool()
StructuredTool(name='task')
挂载了闭包注册表
8.2 函数内部结构
内部函数(同在闭包中)
_validate_and_prepare_state()
准备子 Agent 入参状态
_return_command_with_state_update()
将子 Agent 结果包装为 Command
task() 同步路由函数
atask() 异步路由函数
tool description 组装
None
含占位
不含占位
task_description 参数?
None → 用 TASK_TOOL_DESCRIPTION 模板
填充 available_agents 占位符
含 available_agents 占位 → format 填充
不含占位符 → 原样使用
闭包作用域(函数级私有)
subagent_graphs: dict
{ name: Runnable }
subagent_description_str: str
所有子 Agent 的 name + description 拼接文本
_build_task_tool(subagents, task_description)
StructuredTool.from_function(
name='task',
func=task,
coroutine=atask,
description=description
)
8.3 tool description 的路由作用
task 工具的 description 是 LLM 路由决策的唯一依据 ,由 TASK_TOOL_DESCRIPTION 模板生成:
| description 包含的内容 | 作用 |
|---|---|
所有子 Agent 的 name + description 列表 |
LLM 据此判断把哪类任务派给哪个 Agent |
| 何时使用 task tool(复杂多步骤 / 可并行 / 上下文重 / 只关心输出) | 引导 LLM 决策是否使用 task |
| 何时不使用(简单任务 / 需要看中间步骤 / 拆分无益) | 防止 LLM 滥用 task |
| 并行调用示例 | 引导 LLM 在一轮中多次调用 task 实现并行 |
description 参数要求(需详细、含预期输出格式) |
确保子 Agent 收到足够上下文 |
.format
填入占位符
LLM 可见
TASK_TOOL_DESCRIPTION 模板
含 {available_agents} 占位符
subagent_description_str
-
general-purpose: ...
-
researcher: ...
-
code-reviewer: ...
最终 tool description
(注入到 StructuredTool)
主 Agent LLM
读取 tool description 决策:
① 是否用 task
② 用哪个 subagent_type
③ description 写什么
8.4 关键设计决策
| 设计点 | 实现方式 | 原因 |
|---|---|---|
| 闭包注册表 | subagent_graphs 在函数内定义,被 task/atask 捕获 |
注册表私有,外部无法篡改,线程安全 |
| tool description 驱动路由 | description 含完整 Agent 列表和使用指南 | LLM 是"软路由",靠语义理解而非硬编码规则决策 |
| 只传 description 而非完整 prompt | 子 Agent 入参只有 HumanMessage(description) |
强制 LLM 在调用前想清楚任务内容,避免模糊委托 |
返回 Command 而非字符串 |
_return_command_with_state_update 返回 LangGraph Command |
允许子 Agent state 变更透传回父 Agent |
| 同步 + 异步双实现 | task + atask 同时挂载到 StructuredTool |
支持 invoke 和 ainvoke 两种调用模式 |
| messages[-1] 作为结果 | 只取子 Agent 最后一条消息 | 子 Agent 内部推理过程对父 Agent 不可见,只暴露最终结论 |
9. 状态管理:隔离与传递
9.1 _EXCLUDED_STATE_KEYS:隔离字段集合
python
_EXCLUDED_STATE_KEYS = {
"messages", # 父消息历史不传给子 Agent,子 Agent 只收到单条 HumanMessage(description)
"todos", # 父 Agent 的 todo 列表不传递,子 Agent 有独立 todo
"structured_response", # 不传递,无 reducer 定义
"skills_metadata", # 子 Agent 通过自己的 SkillsMiddleware 加载技能
"memory_contents", # 子 Agent 通过自己的 MemoryMiddleware 加载记忆
}
9.2 状态流转:父 → 子
子 Agent State(注入)
父 Agent State(全量)
重置
过滤 _EXCLUDED_STATE_KEYS
剔除 messages / todos
skills_metadata / memory_contents
structured_response
messages: [全部历史消息]
todos: [父 Agent todo]
skills_metadata: [父技能]
memory_contents: [父记忆]
structured_response
其他自定义 state 字段...
messages: [HumanMessage(description)]
仅一条任务描述消息
其他 state 字段(继承自父 Agent)
设计意图:子 Agent 启动时上下文干净------没有父 Agent 历史消息的包袱,只有一条明确的任务指令。父 Agent 的非敏感自定义 state 字段可透传,实现轻量级上下文共享。
9.3 _validate_and_prepare_state 实现
python
def _validate_and_prepare_state(subagent_type, description, runtime):
subagent = subagent_graphs[subagent_type] # ① 从注册表取 Runnable
subagent_state = { # ② 复制父 Agent state(过滤)
k: v for k, v in runtime.state.items()
if k not in _EXCLUDED_STATE_KEYS # ③ 剔除隔离字段
}
subagent_state["messages"] = [HumanMessage( # ④ 重置 messages:只放单条任务描述
content=description
)]
return subagent, subagent_state
9.4 状态流转:子 → 父(结果回传)
子 Agent 执行结果通过 LangGraph Command 写回父 Agent state:
python
def _return_command_with_state_update(result: dict, tool_call_id: str) -> Command:
# 1. 校验子 Agent 返回的 state 必须含 messages
if "messages" not in result:
raise ValueError("CompiledSubAgent must return a state containing a 'messages' key.")
# 2. 提取非排除字段,准备回写父 state
state_update = {k: v for k, v in result.items() if k not in _EXCLUDED_STATE_KEYS}
# 3. 只取最后一条消息的文本,rstrip() 防止 Anthropic API 尾部空白报错
message_text = result["messages"][-1].text.rstrip() if result["messages"][-1].text else ""
# 4. 包装为 LangGraph Command,触发父 Agent state 更新
return Command(update={
**state_update,
"messages": [ToolMessage(message_text, tool_call_id=tool_call_id)]
})
No
Yes
Yes
子 Agent 执行结果
result: dict
含 messages + 其他 state 字段
result 含
'messages' key?
raise ValueError
CompiledSubAgent 必须返回 messages
state_update = result
过滤掉 _EXCLUDED_STATE_KEYS
(子 Agent 的 todos/skills 等不回传)
取 messages[-1].text.rstrip()
子 Agent 的最终输出文本
Command(update={
...state_update, ← 非隔离字段回写父 state
'messages': [
ToolMessage(text, ← 以 ToolMessage 形式插入父消息链
tool_call_id) ← 与原 tool call 绑定
]
})
父 Agent 收到 ToolMessage
继续 LLM 推理,处理子 Agent 结果
为什么返回
Command而非字符串?LangGraph 的
Command携带update字典,可以直接修改图的 state,不只是作为消息内容返回。这允许子 Agent 把自己产生的非消息类 state 变更(如自定义字段)也回写到父 Agent,实现跨 Agent 的 state 共享。
10. 多子 Agent 并行协作
10.1 注册表构建
用户自定义 subagents 处理
内置:general-purpose 构建
create_agent
create_agent
直接透传
create_agent
all_subagents = [GP, ...user_agents]
注册表 subagent_graphs
{
'general-purpose': Runnable_0,
'researcher': Runnable_1,
'code-reviewer': Runnable_2,
'custom-rag': Runnable_3
}
用户调用
create_deep_agent(subagents=[A, B, C])
GENERAL_PURPOSE_SUBAGENT
-
主 Agent model
-
主 Agent tools
-
标准 middleware 栈
researcher
(SubAgent)
code-reviewer
(SubAgent)
custom-rag
(CompiledSubAgent)
Runnable_1
Runnable_2
Runnable_3
Runnable_0 (general-purpose)
task StructuredTool
(含所有 Agent 的描述)
10.2 并行调用示例
并行调用
并行调用
并行调用
TaskTool
主 Agent LLM
根据 description 智能路由
task('researcher', '搜索论文')
task('code-reviewer', '审查代码')
task('custom-rag', 'RAG 检索')
ToolMessage_1
ToolMessage_2
ToolMessage_3
主 Agent 综合结果
回复用户
10.3 并行协作设计要点
| 要点 | 说明 |
|---|---|
| 扁平化注册 | 所有子 Agent 在同一注册表,无层级,路由统一 |
| general-purpose 永远首位 | 是无匹配专用 Agent 时的兜底通用选项 |
| LLM 自主路由 | 主 Agent LLM 根据每个子 Agent 的 description 自主决策路由目标 |
| 单轮并行 | 一轮消息中可发出多个 task tool call,实现真正的并行执行 |
| ephemeral 无状态 | 每个子 Agent 是独立调用,只返回最终结果,无持久状态 |
11. 完整数据流总览
create_deep_agent(
model, tools,
subagents=[...])
返回 CompiledStateGraph
运行阶段(每次调用)
否
是
用户输入 → 主 Agent LLM 推理
需要委托子 Agent?
直接回复用户
task(subagent_type, description)
subagent.invoke(state)
子 Agent 独立执行多步骤
ToolMessage(最终结果)
主 Agent 综合所有结果
回复用户
构建阶段(一次性)
① 构建 general-purpose subagent
model + tools + 标准 middleware
② 遍历用户 subagents
SubAgent → create_agent()
CompiledSubAgent → 直接透传
③ 合并:[GP, ...user_agents]
④ _build_task_tool()
注册表 + task StructuredTool
⑤ 主 Agent middleware 栈组装
注入 SubAgentMiddleware
⑥ create_agent() → 主 Agent
👤 用户
主 Agent
(已含 task tool)
12. 附录:关键常量与接口定义
12.1 _SubagentSpec(内部统一数据结构)
| 字段 | 类型 | 说明 |
|---|---|---|
name |
str |
子 Agent 唯一标识,用于 task tool 路由 |
description |
str |
子 Agent 能力描述,LLM 据此路由决策 |
runnable |
Runnable |
已编译好的可调用图对象 |
12.2 SubAgent(TypedDict)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
str |
✅ | 子 Agent 唯一标识 |
description |
str |
✅ | 能力描述(LLM 路由决策依据) |
system_prompt |
str |
❌ | 子 Agent 系统提示 |
tools |
list |
❌ | 子 Agent 可用工具列表 |
model |
str |
❌ | 指定模型(默认继承主 Agent model) |
middleware |
list |
❌ | 用户自定义中间件(追加在标准栈后) |
skills |
list |
❌ | 子 Agent 技能列表 |
12.3 CompiledSubAgent(TypedDict)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
str |
✅ | 子 Agent 唯一标识 |
description |
str |
✅ | 能力描述(LLM 路由决策依据) |
runnable |
Runnable |
✅ | 用户自行编译的可运行对象,state 必须含 messages key |
12.4 标准 middleware 栈(SubAgent 自动注入)
| 顺序 | 中间件 | 作用 |
|---|---|---|
| 1 | TodoListMiddleware |
管理 todo 列表 |
| 2 | FilesystemMiddleware |
文件系统访问 |
| 3 | SummarizationMiddleware |
历史消息摘要,防止上下文过长 |
| 4 | AnthropicPromptCachingMiddleware |
Anthropic 提示缓存优化 |
| 5 | PatchToolCallsMiddleware |
tool call 格式修复 |
| 6+ | 用户自定义 middleware | 追加在标准栈末尾 |
12.5 状态隔离字段说明
| 字段 | 隔离原因 |
|---|---|
messages |
父消息历史不传给子 Agent,子 Agent 只收到单条 HumanMessage(description) |
todos |
父 Agent 的 todo 列表不传递,子 Agent 有独立 todo 管理 |
structured_response |
无 reducer 定义,传递会导致合并冲突 |
skills_metadata |
子 Agent 通过自己的 SkillsMiddleware 独立加载技能 |
memory_contents |
子 Agent 通过自己的 MemoryMiddleware 独立加载记忆 |