子 Agent 的本质:上下文隔离与专门化
"子 Agent"这个词在多 Agent 系统的讨论中频繁出现,却鲜有人把它说清楚。它是一个能力弱化的 Agent,类似一个 Agent 化的工具?还是一个拥有更小上下文的原始 Agent,像从主 Agent fork 出来的进程?还是一个在指挥体系里听从领导 Agent、但拥有更强资源和能力的 Agent?
这三种直觉都不完全准确。本文从 Anthropic、LangChain、Claude Code 等权威来源出发,厘清子 Agent 的真实本质,并探讨一个更深层的问题:"子 Agent"究竟是能力描述,还是关系描述?
三种直觉,三种误解
在深入定义之前,先把三种常见直觉逐一检验。
误解一:子 Agent 是能力弱化的 Agent
这种直觉来自于"子"字的字面含义——子集、子系统、子进程,往往意味着更小、更弱。但 LangChain 官方文档明确指出:
“An interesting aspect of this approach is that sub-agents may have the exact same capabilities as the main agent.”
子 Agent 可以拥有与主 Agent 完全相同的能力。它不是弱化版,不是受限版,更不是"工具的高级包装"。
误解二:子 Agent 是拥有更小上下文的 fork
这种直觉来自操作系统的进程模型——子进程从父进程 fork,继承部分状态,但资源受限。这个类比有一定道理,但关键词不是"更小",而是"独立且干净"。
Anthropic 官方工程博客描述其多 Agent 研究系统时写道:
“Subagents facilitate compression by operating in parallel with their own context windows, exploring different aspects of the question simultaneously before condensing the most important tokens for the lead research agent.”
子 Agent 拥有独立的上下文窗口(own context windows),而不是主 Agent 上下文的子集。这个上下文窗口是全新的、干净的,不是"更小的"。
误解三:子 Agent 是听从指挥但能力更强的下属
这种直觉来自军事或企业的层级模型——将领指挥士兵,但士兵在具体战术上可能比将领更专业。这个类比在某些场景下成立,但它把"子 Agent"理解成了一种永久的身份,而非一种临时的关系。
真正的问题在于:一个 Agent 是否是"子 Agent",取决于它在当前任务中的角色,而非它的固有属性。
子 Agent 的真实本质
综合 Anthropic、Claude Code、LangChain 的权威定义,子 Agent 的本质可以用一句话概括:
子 Agent 是一个完整的、专门化的 Agent 实例,运行在独立的上下文窗口中,由主 Agent 通过工具调用方式协调,其核心价值在于上下文隔离,而非能力弱化。
四个核心特征
1. 上下文隔离
这是子 Agent 最核心的价值。LangChain 的表述最为精辟:
“This provides context isolation: each subagent invocation works in a clean context window, preventing context bloat in the main conversation.”
每次调用子 Agent,都是在一个干净的上下文窗口里开始工作。主 Agent 的历史对话、工具调用记录、中间推理过程,都不会污染子 Agent 的上下文。这防止了主 Agent 的上下文膨胀(context bloat)。
2. 完整的 Agent 能力
子 Agent 不是工具(Tool)。工具是单一功能的函数,被动执行,没有决策能力,没有 Agent Loop。子 Agent 是完整的 Agent 实例,拥有:
- 独立的推理-行动循环(Agent Loop)
- 自主规划和决策能力
- 多步骤任务执行能力
- 执行期间的短期记忆
3. 无状态执行
子 Agent 是无状态的(stateless)——它不保留跨调用的记忆。每次被主 Agent 调用,都是一次全新的执行。所有跨步骤的状态,由主 Agent 维护。
4. 专门化任务处理
子 Agent 通过自定义 system prompt 定义专门职责,可以针对特定领域优化。这种专门化不是能力的限制,而是能力的聚焦。
把上面四点放到一张图里,子 Agent 的工作机制就是:
flowchart LR
subgraph Main["主 Agent 上下文窗口"]
M["主 Agent<br/>(编排者)"]
Mem["对话历史<br/>工具调用记录<br/>中间推理过程"]
end
subgraph Sub["子 Agent 上下文窗口 (clean)"]
S["子 Agent<br/>(专门化执行)"]
end
M ==>|"① 最小化任务 prompt<br/>目标 · 约束 · 输出格式"| S
S ==>|"② 压缩后的结果摘要"| M
style Mem fill:#fff3cd,stroke:#856404,color:#333
style Main fill:#fef9e7,stroke:#856404
style Sub fill:#d1ecf1,stroke:#0c5460
主 Agent 把"对话历史、工具记录、中间推理"这些消耗上下文的内容留在自己的窗口里,只把任务必需的最小信息发出去;子 Agent 在干净窗口里完成任务后,回传的也只是结果摘要而非全过程。这就是"上下文隔离"的物理含义。
递归约束:Claude Code 的设计选择
Claude Code 对子 Agent 施加了一个刻意的约束:
“Subagents cannot spawn other subagents, so Agent(agent_type) has no effect in subagent definitions.”
子 Agent 不能再派发子 Agent。这防止了无限递归和控制流混乱,保证行为的可预测性。但需要注意:这是 Claude Code 的平台特定设计,不是子 Agent 的通用本质特征。 LangGraph 的 subgraph 可以任意嵌套,AutoGen 和 CrewAI 的 Agent 也没有这个限制。不同平台在"是否允许递归派发"上做了不同的权衡。
与此形成对比的是 Skill 机制。Skill(如 Claude Code 中的 SKILL.md)本质上是系统提示的动态扩展,而非 Agent 实例的创建。当一个 Skill 被触发时,它的内容被加载到当前 Agent 的上下文中,Agent 按照 Skill 的指令行动。整个过程发生在同一个上下文窗口内。因此,Skill A 可以触发 Skill B,Skill B 可以触发 Skill C,形成多层调用链——这是上下文内的行为扩展,不涉及新 Agent 实例的创建,受上下文窗口容量约束。
| 概念 | 本质 | 调用链能力 |
|---|---|---|
| 子 Agent | 完整的 Agent 实例,独立上下文窗口 | 取决于平台(Claude Code 禁止,LangGraph 允许) |
| Skill | 系统提示的动态扩展 | 可以形成多层调用链(受窗口容量约束) |
两种调用链的机制差异可以直观对照:
flowchart TB
subgraph A["子 Agent 派发:每层一个独立上下文窗口"]
direction TB
A1["主 Agent · 上下文 #1"]
A2["子 Agent · 上下文 #2"]
A3["孙 Agent · 上下文 #3"]
A1 ==>|"创建新实例"| A2
A2 -.->|"Claude Code 禁止 · LangGraph 允许"| A3
end
subgraph B["Skill 调用链:始终在单一上下文窗口内"]
direction TB
B0["Agent 上下文窗口 (唯一)"]
SkA["Skill A"] -.->|"加载到"| B0
SkB["Skill B"] -.->|"加载到"| B0
SkC["Skill C"] -.->|"加载到"| B0
end
style A fill:#fdecea,stroke:#c0392b
style B fill:#e8f5e9,stroke:#27ae60
这个区别揭示了一个设计原则:Agent 实例的创建是重量级操作(需要独立上下文窗口),各平台倾向于约束它;而上下文内的行为扩展是轻量级操作,可以自由组合。
"子 Agent"是关系描述,不是能力描述
当我们说某个 Agent 是"子 Agent"时,我们描述的是它在当前任务中与其他 Agent 的关系,而不是它的固有属性或能力等级。
以 Oh My OpenCode 的 Agent 团队为例:
1 | |
在这个架构图里,Prometheus、Oracle、Librarian 看起来是 Sisyphus 的"子 Agent"。但这个判断是错误的,或者说是不完整的。
Prometheus、Oracle、Librarian 都可以独立运行。
- 用户可以直接对话 Prometheus,让它制定战略规划,完全不经过 Sisyphus
- 用户可以直接调用 Oracle 进行架构咨询
- Librarian 可以作为独立的文档研究 Agent 被任何工作流调用
它们之所以在某些场景下表现为 Sisyphus 的"子 Agent",仅仅是因为 Sisyphus 在那个特定的任务中扮演了编排者的角色,通过工具调用的方式协调了它们。一旦任务结束,这种"主-子"关系就消失了。
这与传统软件工程中的"子系统"概念截然不同。子系统是静态的架构关系,一旦被设计为子系统,就永远是子系统。而 Agent 的"主-子"关系是动态的、任务级别的。
类比:项目中的角色 vs 职位
一个更直观的类比:
在一个软件项目中,张三是"项目经理",李四是"开发工程师"。但在另一个项目中,李四可能是项目经理,张三是开发工程师。他们的职位(固有属性)没有变,但他们在不同项目中的角色(关系描述)是不同的。
Agent 的"主-子"关系正是如此。Prometheus 的固有属性是"战略规划专家",但它在不同的任务中可以是:
- 独立运行的规划 Agent(直接与用户对话)
- Sisyphus 的子 Agent(被 Sisyphus 通过工具调用协调)
- 某个更高层编排器的子 Agent(在更复杂的多层架构中)
子 Agent vs Tool:本质区别
既然子 Agent 不是弱化的 Agent,那它和 Tool 的区别是什么?
| 维度 | Tool | 子 Agent |
|---|---|---|
| 本质 | 单一功能的函数/方法 | 完整的 Agent 实例 |
| 上下文 | 无独立上下文 | 拥有独立上下文窗口 |
| 决策能力 | 无,被动执行 | 有,可自主规划 |
| 循环能力 | 无 | 拥有 Agent Loop(推理-行动循环) |
| 记忆 | 无 | 执行期间有短期记忆 |
| 复杂度 | 单步操作 | 多步骤复杂任务 |
| 状态 | 无状态 | 执行期间有状态,调用间无状态 |
何时用 Tool,何时用子 Agent?
- Tool:任务是单步的、确定性的、不需要推理的(读文件、执行命令、调用 API)
- 子 Agent:任务需要多步骤推理、需要上下文隔离、需要专门化处理
上下文隔离的代价
上下文隔离不是免费的。每次创建子 Agent 都意味着:
- 信息损失:协调者必须在 prompt 中显式传递所有相关上下文,压缩过程不可避免地丢失细节。子 Agent 不知道"之前发生了什么",它只知道 prompt 告诉它的内容。
- 延迟与成本:每个子 Agent 调用是一次完整的 API 请求,有网络延迟和额外的 token 消耗。
- 协调开销:任务拆分、结果汇总、异常处理都需要协调者的额外上下文空间。
因此,上下文隔离是一种权衡:用信息传递的精确性换取上下文空间的清洁。任务越复杂、上下文污染风险越高,这个交换越值得;任务越简单,直接在主 Agent 内处理的效率越高。
实践含义
理解子 Agent 的本质,对实际的多 Agent 系统设计有直接影响:
1. 不要把"子 Agent"设计成永久的层级关系
如果你的系统里有一个 Agent 永远只能被另一个 Agent 调用,永远不能独立运行,这往往是过度设计的信号。好的 Agent 应该是可以独立运行的,"主-子"关系是任务级别的协调,而非架构级别的约束。
2. 上下文隔离是选择子 Agent 的核心理由
当你考虑是否要用子 Agent 时,最重要的问题不是"这个任务需要多强的能力",而是"这个任务需要独立的上下文吗?"如果任务足够简单,一个 Tool 就够了;如果任务需要多步骤推理但上下文不需要隔离,在主 Agent 内处理就够了;只有当任务需要多步骤推理且需要上下文隔离时,才需要子 Agent。
3. Skill 是上下文内的行为扩展,子 Agent 是上下文外的任务委托
这两种机制解决的是不同层面的问题。Skill 扩展的是当前 Agent 的行为能力,子 Agent 委托的是独立的任务执行。前者是"让我学会新技能",后者是"把这个任务交给专家去做"。
4. 协调者 Agent 应该专注调度
在多 Agent 团队中,协调者 Agent 应当专注于任务分解、进度追踪和质量把控,而不直接参与执行细节。
原因有二。第一,执行细节(代码 diff、编译错误、测试输出)会迅速填满上下文窗口,挤压协调者对全局目标和约束条件的掌控——就像一个项目经理如果整天埋头写代码,就会忘记关注项目风险和交付时间线。第二,子 Agent 从干净上下文开始工作,只接收最小化的任务描述,不会被协调者的历史对话和无关信息污染。
这是分治思想在 Agent 系统中的体现:调度层保持轻量,随时准备调整策略;执行层可以"重",涉及大量工具调用和错误重试。两层职责分离,系统的可预测性和可维护性都会更好。"协调者不写代码"不是能力的限制,而是架构的自觉。
委派子 Agent 时还有一个容易被忽略的杠杆:不是所有任务都需要用最强的模型。 一个"重命名变量"的任务和一个"重构认证模块"的任务,对模型能力的要求完全不同。协调者在委派时可以根据任务性质指定不同等级的模型——轻量快速模型处理简单操作,重量级推理模型处理架构级变更——在保证质量的同时显著降低运行成本。
总结
子 Agent 的本质是上下文隔离的专门化 Agent 实例,而非能力弱化的 Agent 或资源受限的进程。
几个关键结论:
- 子 Agent 是完整的 Agent,可以拥有与主 Agent 相同甚至更强的能力
- 上下文隔离是核心价值,不是能力限制
- 递归派发是平台特定约束(Claude Code 禁止,LangGraph 允许),Skill 可以形成多层调用链
- "子 Agent"是关系描述,不是能力描述——Prometheus、Oracle、Librarian 这样的 Agent 可以独立运行,也可以在特定任务中作为子 Agent 被协调
- 主-子关系是动态的、任务级别的,不是静态的架构约束
理解了这些,你就能更清晰地设计多 Agent 系统:让每个 Agent 都能独立运行,让"主-子"关系服务于任务,而不是被架构固化。


