【Claude Code-上下文实测】把上下文边界变成工程边界:子代理隔离是否真的能提升 Coding Agent 表现
非线智能API经验 [Claude Code-上下文实测] 第21篇
摘要
复杂 coding 任务不一定适合塞进单一长会话。长会话会积累调研材料、失败日志、重复工具输出、过期假设和中间决策;即使上下文窗口足够大,这些低价值内容也会污染主会话。子代理隔离的核心价值不是“多开几个模型”,而是把任务边界、记忆边界和责任边界显式化。
调研代理可以读大量资料但只返回结论和引用;实现代理只接收目标、约束和相关文件;测试代理保留完整失败日志但只向主会话返回根因和复现步骤;审查代理只接收 diff、约束和测试结果。主会话从“全量记忆”转为“决策账本”,上下文压力和污染风险都会下降。
数据来源:非线智能Nonlinear 官网
证据层级
Anthropic Engineering 关于 context engineering 的文章可支撑“上下文需要被工程化管理”的主框架。LangChain 的 context engineering 文章可作为 write、select、compress、isolate 等策略分类参考。arXiv “Dive into Claude Code” 可作为 Claude Code 架构分析和 subagent delegation 观察。Matsuoka Hyperdev、Start Debugging 等文章适合作为 Claude Code 生态实践观察,不应写成官方架构承诺。
本文讨论的是可验证的任务拆分模式,不假设子代理一定更省 token 或一定提升质量。隔离收益取决于任务边界、返回格式和协调成本。
为什么单一长会话会腐烂
单一长会话的优点是连续:所有历史都在一个地方,模型能看到完整过程。但复杂任务跑久后,会出现上下文腐烂:
| 腐烂来源 | 表现 |
|---|---|
| 过期假设 | 早期猜测已经被推翻,但仍在上下文里 |
| 已解决错误 | 旧失败日志继续影响后续推理 |
| 重复工具输出 | 多次搜索和测试结果稀释关键信息 |
| 调研噪声 | 大量背景材料和最终实现关系很弱 |
| 计划漂移 | 旧计划、新计划、局部计划混在一起 |
| 约束稀释 | 用户硬约束被长历史埋没 |
长上下文窗口能延后爆炸,但不能自动区分“当前仍有效状态”和“历史噪声”。子代理隔离就是用任务边界帮助系统做这种区分。
子代理不是简单并行
把一个任务拆给多个 agent,不一定更好。如果只是把同一个上下文复制给多个模型,最后合并一堆自由文本,可能会增加 token 和协调成本。
有效的子代理隔离有三个特征:
| 特征 | 含义 |
|---|---|
| 输入最小化 | 子代理只拿完成自己任务所需的上下文 |
| 输出结构化 | 子代理只返回主会话需要吸收的结论 |
| 责任清晰 | 每个子代理有明确阶段、文件、验证或审查职责 |
核心不是“并行”,而是“隔离”。并行只是隔离带来的额外收益。
推荐角色拆分
复杂 coding 任务可以拆成五类角色:
| 角色 | 输入 | 输出 | 不应返回 |
|---|---|---|---|
| Research Agent | 问题、来源、检索范围 | 结论、证据等级、引用链接 | 全量网页、长摘录 |
| Implementation Agent | 目标、约束、相关文件 | patch、设计理由、风险点 | 全量调研过程 |
| Test Agent | 变更、验证命令、环境 | 通过 / 失败、根因、复现步骤 | 完整日志原文 |
| Review Agent | diff、用户约束、测试结果 | findings、严重级别、文件行号 | 宽泛建议 |
| Coordinator | 用户目标、决策账本、子结果 | 下一步决策、最终交付 | 全量子代理上下文 |
这种拆分让每个 agent 的上下文只为一个目标服务。主会话不需要吞下调研代理读过的所有材料,也不需要保留测试代理的完整失败日志。
主会话应当是决策账本
如果主会话仍然保存所有子代理输出原文,隔离价值就会消失。主会话应保留:
| 内容 | 示例 |
|---|---|
| 用户目标 | 要修复什么、交付什么 |
| 不可违反约束 | 不改哪些文件、不执行哪些命令 |
| 已接受决策 | 选用方案 A,放弃方案 B |
| 子代理结果摘要 | 调研结论、测试根因、审查 findings |
| 当前代码状态 | 修改文件、关键 diff、验证状态 |
| 下一步 | 谁负责什么,是否需要继续 |
完整日志、完整网页、完整测试输出、子代理探索过程应外置为 artifact 或只保留引用。
返回格式决定污染程度
子代理输出格式会直接影响主会话上下文质量。
| 格式 | 适用场景 | 风险 |
|---|---|---|
| 自由文本 | 早期探索、开放性判断 | 易冗长,难自动提取 |
| JSON 摘要 | 主会话吸收、状态机更新 | 需要 schema 设计 |
| patch + rationale | 实现任务 | 需要冲突处理 |
| findings list | 审查任务 | 要求文件 / 行号具体 |
| test report | 验证任务 | 要区分关键日志和完整日志 |
推荐对子代理使用结构化返回模板:
{
"task": "测试当前 diff",
"status": "failed",
"key_findings": [
{
"severity": "high",
"summary": "npm test 在 mapper test 失败",
"evidence": "tests/tool_mapper.test.ts",
"next_action": "检查 tool_call_id 映射"
}
],
"artifacts": [
{
"type": "log",
"path": "artifacts/test-runs/npm-test.log",
"sha256": "..."
}
],
"context_for_coordinator": "当前唯一阻塞是 tool_call_id 映射错误。"
}
主会话只吸收 context_for_coordinator、关键 findings 和 artifact 引用。
上下文隔离与 prompt cache
子代理隔离也会影响 prompt cache。单一长会话里,工具结果、调研材料和测试日志不断进入同一历史,cacheable prefix 容易被动态内容拖累。多子代理模式下,每个代理可以有更稳定的前缀:
| 代理 | 稳定前缀 |
|---|---|
| Research | 来源分级规则、引用格式 |
| Implementation | 编码规范、相关文件摘要、工具子集 |
| Test | 验证命令、日志摘要 schema |
| Review | review rubric、严重级别定义 |
主会话只保留协调状态,动态日志不进入主 cacheable prefix。这样不保证总 token 一定更少,但能让 token 花在更相关的上下文上。
上下文隔离与工具治理
不同子代理应暴露不同工具:
| 代理 | 工具集 |
|---|---|
| Research | web/search/read-only docs |
| Implementation | read/search/edit/test |
| Test | test/build/browser/log tools |
| Review | diff/read/test output |
| Coordinator | planning、summary、有限工具 |
工具隔离有两个好处:减少工具定义 token,降低误调用概率。调研代理不需要部署工具,审查代理不需要写文件工具,测试代理不需要读完整外部资料。
评价指标
要验证子代理隔离是否有用,不能只看总 token。建议同时看:
| 指标 | 含义 |
|---|---|
| 总 token | 所有代理加起来的输入 / 输出 |
| 主会话增长率 | coordinator 上下文是否保持小而稳 |
| 任务成功率 | 最终是否完成 |
| 约束遗漏率 | 是否违反用户硬约束 |
| 错误恢复轮数 | 遇到失败后需要几轮恢复 |
| 重复工作率 | 是否重复调研、重复修复、重复跑错命令 |
| 并行耗时 | wall-clock 是否下降 |
| 审查发现数 | 是否更早发现风险 |
| cache hit rate | 稳定前缀是否更可复用 |
子代理可能增加总 token,但降低主会话污染、提高成功率、减少人工恢复成本。评估时要看完整权衡。
实验设计
推荐用同一组真实任务做 A/B:
| 组 | 方式 |
|---|---|
| A | 单一长会话完成全部调研、实现、测试、审查 |
| B | Research / Implementation / Test / Review 子代理隔离,Coordinator 汇总 |
固定变量:
• 同一模型或同一模型组合。
• 同一代码库版本。
• 同一任务说明。
• 同一工具权限。
• 同一完成标准。
记录:
• 每阶段 token。
• wall-clock 时间。
• 最终 diff 质量。
• 测试通过情况。
• 用户约束是否遗漏。
• review findings。
• 主会话最终上下文大小。
最好让独立 reviewer 盲评两组结果,避免只看 agent 自评。
失败模式
| 失败模式 | 触发原因 | 修复策略 |
|---|---|---|
| 子代理丢关键约束 | 输入上下文裁得太狠 | Coordinator 提供 constraints block |
| 总 token 上升 | 子代理重复读取相同资料 | 共享 artifact 和摘要索引 |
| 合并冲突 | 多个实现代理改同一文件 | disjoint ownership 和主线程集成 |
| 主会话仍被污染 | 子代理返回完整日志 | 强制结构化摘要和 artifact ref |
| 审查无效 | Review Agent 没有 diff / 约束 | 输入包含 patch、测试结果、rubric |
| 责任不清 | 所有代理都做所有事 | 明确角色和工具边界 |
验证清单
• 选 bugfix、重构、功能开发、测试补齐、文档更新五类任务做对比。
• 主会话只接收结构化子结果,不接收完整工具日志。
• 对每个子代理限制工具集,记录工具定义 token。
• 对比单会话和多子代理的主会话 token 增长率。
• 统计约束遗漏、重复工作、错误恢复轮数。
• 让独立 reviewer 盲评 diff 质量和风险。
工程结论
子代理隔离的价值不是简单并行,而是把上下文边界变成工程边界。调研、实现、测试、审查的临时噪声不应全部进入主会话;主会话应该维护决策账本,而不是全量记忆。子代理不保证一定省 token,但在复杂任务中,它能把 token 花在更局部、更相关、更可控的上下文里。
参考链接
• Anthropic Engineering: Effective context engineering for AI agents
• LangChain Blog: Context Engineering
• arXiv: Dive into Claude Code
• Matsuoka Hyperdev: 2025 The Year of the Hyperdev
• Start Debugging: Monorepo context stays small
• Start Debugging: Dynamic Workflows fan out to subagents
本文由非线智能API Claude Code 行业专家整理编写