Subagent 与上下文隔离
用子 Agent 处理探索性子任务,保护主上下文。
一句话理解:Subagent 是主 Agent 临时派出去的“专员”:在一个干净的上下文里完成探索性子任务,只把精简的结论带回来,让主 Agent 的上下文始终保持清爽。
想象一个 Coding Agent 在排查“结账接口偶发超时”。为了找到根因,它读了 40 个文件、跑了十几次搜索、翻了几千行日志。等它终于定位到问题、准备动手修改时,上下文里塞满了与修改无关的代码片段和日志,最初的需求描述和关键约束已经被淹没在中间。这正是 上下文腐化 一课讲过的问题:上下文越长越杂,模型越容易遗漏重点。
Subagent 的思路很直接:探索的过程不需要留在主线程里,主线程只需要探索的结论。 这是多 Agent 架构里最实用、也最容易用对的一种形态,Claude Code 等 Coding Agent 已经把它作为日常能力。
上下文隔离如何工作
图 1 以排查结账超时为例,画出两份上下文如何隔离:
Anthropic 在关于上下文工程的文章中描述了这种架构:子 Agent 在干净的上下文窗口中处理聚焦的任务,自身可能消耗大量 Token 做探索,但只返回精简的摘要(文中给出的量级通常是 1,000–2,000 Token),从而把详细的搜索上下文隔离在子 Agent 内部,让主 Agent 专注于综合与分析。
以 Claude Agent SDK 为例,文档对子 Agent 的行为有明确说明:
- 子 Agent 在自己的会话中运行,默认从全新的上下文开始(除非显式使用 fork 继承父会话)。
- 父 Agent 传给子 Agent 的内容只有调用 Agent 工具时的那段提示词,所以文件路径、错误信息和已做出的决定都必须写进这段提示词。
- 子 Agent 的中间工具调用和结果留在它自己的上下文里,只有最终消息作为工具结果返回给父 Agent。
- 子 Agent 可以限制可用工具,例如只给读取和搜索权限,保证它“只能看、不能改”。
- 多个子 Agent 可以并发运行,相互独立的子任务总耗时取决于最慢的那个,而不是所有任务之和。
写好委派:子 Agent 只知道你告诉它的
子 Agent 效果不好,最常见的原因不是模型能力,而是委派写得太随意。Anthropic 在多 Agent 研究系统的文章中总结:每个子 Agent 需要 目标、输出格式、使用哪些工具和信息源的指引,以及清晰的任务边界。他们早期让主 Agent 只下达“研究半导体短缺”这种简短指令,结果子 Agent 误解任务,或者几个子 Agent 做了重复的调研。
对比一个 Coding 场景的委派:
差的委派:
看看结账超时是怎么回事。
好的委派:
目标:找出 POST /checkout 偶发超时(P95 超过 8 秒)的根因。
已知:超时集中在每天 20:00–22:00;本周没有部署支付相关代码。
范围:只看 services/checkout 与 services/inventory 两个目录和
logs/checkout-*.log;不要修改任何文件。
方法:优先检查连接池、重试与外部调用的超时配置。
输出:
1. 最可能的根因(一句话)
2. 证据:文件路径 + 行号,或日志时间戳
3. 置信度:已确认 / 高度怀疑 / 猜测
4. 排除过的可能性
如果 20 次搜索内找不到线索,停止并报告已检查过的范围。
好的委派有四个特征:说清楚“为什么”(背景和已知信息)、划定边界(范围和禁止事项)、规定返回格式(主 Agent 才能直接使用)、给出停止条件(防止子 Agent 无限探索)。
什么适合交给 Subagent
| 适合 | 原因 | 例子 |
|---|---|---|
| 探索与搜索 | 过程冗长、结论简短 | 在代码库中找出某函数的所有调用点;检索 20 份合同中的违约条款 |
| 相互独立的批量子任务 | 可并行,互不依赖 | 分别诊断 50 个页面的 SEO 问题 |
| 需要不同视角的检查 | 独立上下文避免被主线程的思路带偏 | 代码写完后由审查子 Agent 独立检查安全问题 |
| 读取不可信内容 | 可以只给只读权限,隔离注入风险 | 浏览外部网页收集竞品信息 |
| 不适合 | 原因 | 更好的做法 |
|---|---|---|
| 需要连续决策的修改 | 子 Agent 看不到主线程的全部决策,容易改出冲突 | 主 Agent 自己改,子 Agent 只负责查 |
| 与用户多轮沟通 | 子 Agent 结果只回到主 Agent,不直接面对用户 | 使用 Handoff,见 Agent as Tool 与 Handoff |
| 很小的任务 | 启动子 Agent 需要重新加载指令与工具,开销大于收益 | 直接调用工具 |
| 依赖大量共享上下文 | 把上下文完整写进委派几乎等于复制一份主上下文 | 保持单线程,必要时做 上下文压缩 |
再回到客服场景:订单售后诊断 Agent 本身保持单线程,但当某个用户的历史工单有上百条时,把“检索历史工单并找出同类问题”交给一个只读的子 Agent,是合理的局部用法。
控制成本与失控风险
子 Agent 很好用,也很容易被滥用:
- 过度委派。 Anthropic 的文章提到,早期版本曾为简单查询派出 50 个子 Agent。他们的解法是在提示中写入按复杂度分配投入的规则:简单的事实查找只需 1 个 Agent 调用 3–10 次工具;直接比较类任务用 2–4 个子 Agent,每个 10–15 次调用;复杂研究才使用 10 个以上的子 Agent,并明确分工。
- 嵌套失控。 子 Agent 也可能再派子 Agent,一个请求会长成一棵树。Claude Agent SDK 提供了限制嵌套深度、同时运行的子 Agent 数量和整个查询花费上限的配置;无论使用哪个框架,都应该设置这三类上限。
- 结果传递失真。 子 Agent 的结论经过主 Agent 转述,可能被再次压缩而丢失细节。对于报告、代码这类大块产物,Anthropic 的做法是让子 Agent 把结果写到外部存储(例如文件系统),只把轻量的引用传回主 Agent。
- 可观测性。 子 Agent 的运行也要进入 Trace,并与父 Agent 的调用关联起来。以 Claude Agent SDK 为例,来自子 Agent 内部的消息带有
parent_tool_use_id字段,可以据此还原调用关系。
图 2 把这些控制点画在一棵调用树上:
常见误区
- “子 Agent 能看到主对话。” 除非显式 fork,子 Agent 默认看不到父 Agent 的历史。所有必要信息都要写进委派。
- “结论返回得越详细越好。” 返回内容会进入主上下文,太长就失去了隔离的意义。规定格式和长度上限。
- “让子 Agent 顺手把问题修了。” 修改应由掌握全局决策的主 Agent 完成,否则多个子 Agent 的修改可能相互冲突。
- “有了子 Agent 就不用管上下文了。” 主 Agent 的上下文仍会随着任务增长,子 Agent 只是减缓了这个过程,长任务仍需要压缩与外置笔记。
产品经理检查清单
- 委派给子 Agent 的任务,是否满足“过程长、结论短”或“可独立并行”?
- 委派模板是否包含目标、已知信息、范围边界、方法指引、输出格式和停止条件?
- 子 Agent 的工具权限是否按最小权限配置?探索型子 Agent 是否只读?
- 是否设置了子 Agent 的数量、嵌套深度和总花费上限?
- 大块产物是通过文件或存储引用传递,还是塞进返回消息?
- 子 Agent 的运行能否在 Trace 中与父 Agent 关联查看?
练习
在 Claude Code 或任何支持子 Agent 的工具里完成一次对比实验(45–60 分钟):
- 选一个中等规模的代码仓库,提问:“这个项目里用户认证是怎么实现的?列出关键文件。”
- 第一次让主 Agent 直接完成;第二次明确要求用子 Agent 探索并返回结构化结论。
- 对比两次的回答质量、总耗时、主会话上下文占用(或 Token 用量)。
- 按本课的模板重写一次委派提示词,再跑一次,记录变化。
延伸阅读
- Claude Agent SDK:Subagents
- Anthropic:Effective context engineering for AI agents
- Anthropic:How we built our multi-agent research system
下一步
子 Agent 带来隔离与并行,也带来额外的 Token、信息压缩和调试成本。下一课「多 Agent 的代价」系统地清点这些代价,以及如何控制它们。