导读:Anthropic 10 月 22 日发了一篇《Building agents: When to fold subagents into your main agent loop》,意思是很多团队的子代理拆多了,应该并回主循环。掘金上相关解读的标题已经是"别学 subagent 了,很可能要凉了"。说法归说法,我想看到数字,就在 Claude Code 2.1.299 上拿同一个 Java 项目跑了 11 次
claude -p,对比"主对话自己干"和"派子代理去干"的花费、耗时和结果质量,再整理出什么时候子代理确实值得用、怎么配置和禁用。
一、先说清楚:subagent 是什么
subagent(子代理) 就是主对话里的 Claude 再派出去的一个"临时工":它有自己独立的上下文窗口,拿着主对话写给它的任务说明去读文件、搜代码,干完只把一段总结交回来,过程中读过的文件内容不会进主对话。打个比方,主对话是你,子代理是你派去档案室翻资料的同事,他翻了一下午,回来只给你一页纸。
Claude Code 内置了几个子代理,最常见的是 Explore(只读,专门搜代码),你也可以在 .claude/agents/ 下自己定义。主对话会根据任务自己决定要不要派,你也可以在提示词里点名让它派。
不管它会怎样:你可能根本没意识到 Claude 派过子代理。它的好处是主对话的上下文干净;代价是每派一次,子代理都要重新读一遍系统提示词和文件,多一轮模型调用,多一段等待,交回来的总结还可能漏掉细节。
什么时候值得动它:如果你在用订阅时经常撞用量上限、用 API Key 按 token 付费、或者在 CI 里批量跑 claude -p,值得看看子代理在你的场景里是省了还是费了。下面的数字可以当参照。
二、Anthropic 那篇文章说了什么
原文作者是 Diane Sarkis,内容来自 Anthropic 应用 AI 团队(Applied AI)在企业部署里看到的情况。核心观点两句话:
- 很多团队按"一个业务一个子代理、上面再放一个调度器"来搭 Agent,结构像公司组织架构图。这样做信息每转一手就丢一些,延迟和 token 成本也跟着涨。有一个客户把多代理方案和单个主循环对比,单循环的运行时间大约快了一倍
- 现在有了"渐进式披露"(Skills 和工具先只给模型看简短描述,用到时才加载完整内容),以前因为上下文装不下才拆子代理的理由,大部分已经不成立了。原文提到 Claude Code 针对更强模型的系统提示词缩减了 80% 以上,其中就包括这部分
原文没有说子代理没用,它列了三种仍然适合用子代理的情况:
| 原文给的情况 | 我的理解 |
|---|---|
| 单个循环因为上下文膨胀,出现了可测量的效果下降 | 主对话已经被大量原始材料撑满,开始答非所问 |
| 多个任务需要用全新的上下文窗口并行处理 | 几件互不相关的事可以同时干,干完就扔 |
| 单个 Agent 选不对工具,或系统提示词里有互相冲突的指令 | 某个角色需要一套完全不同的工具和规则 |
迁移建议是先建一个小的端到端评估集(原文说 10 个标准样例就够起步),然后一次只并一个子代理,比较并之前和并之后的结果,每个任务多跑几次。
这篇文章讲的是企业用 Claude API 自己搭 Agent 的架构,Claude Code 里的子代理是同一套思路的具体实现。所以我想在 Claude Code 里验证的是:一个普通的后端开发任务,派子代理到底贵多少、慢多少、结果有没有变差。
三、实测:同一个 Java 项目跑 11 次
3.1 环境和做法
| 项 | 设置 |
|---|---|
| Claude Code | 2.1.299,claude.ai 订阅登录 |
| 模型 | 主对话 --model sonnet --effort medium(Sonnet 5.5) |
| 项目 | 生成的 Java 项目,30 个 *Service 类,共 6254 行;其中 7 个类把 SimpleDateFormat 声明成 static 字段(线程不安全),4 个类用局部变量,19 个类用 DateTimeFormatter |
| 隔离 | --setting-sources project --strict-mcp-config,不加载我本机的用户级设置、插件和 MCP,项目目录里没有 CLAUDE.md |
| 主对话组 | --disallowedTools Agent,提示词末尾加"直接用 Read、Grep、Glob 自己完成" |
| 子代理组 | 提示词末尾加"必须先用 Agent 工具派一个 Explore 子代理完成文件搜索和阅读,你自己不要直接调用 Read、Grep、Glob" |
| 数据来源 | --output-format json 里的 total_cost_usd、modelUsage、subagent_stats;耗时用 /usr/bin/time -p 量墙钟时间 |
⚠️
total_cost_usd是 Claude Code 按标价在本地算的。我是订阅登录,这个数字和实际账单无关,只能拿来比较"哪种做法用的 token 多"。每组只跑了一到两次,数字有波动,看倍数关系,别看绝对值。
主对话组的运行命令如下,子代理组只是换了提示词末尾那句、去掉 --disallowedTools Agent:
# 在项目目录下执行;p1.txt 是任务描述
claude -p "$(cat p1.txt)
直接用 Read、Grep、Glob 自己完成。" \
--model sonnet --effort medium \
--setting-sources project --strict-mcp-config \
--permission-mode acceptEdits --allowedTools Read Glob Grep Edit Agent \
--disallowedTools Agent --output-format json > t1_main.json
三个任务:
- 任务 1(窄):找出所有把
SimpleDateFormat声明为 static 字段的类,说明问题和改法 - 任务 2(宽):逐个检查 30 个类,统计 public 方法数,标出每个类格式化时间用的哪种方式,出一张表
- 任务 3(两步):先做任务 2,然后在同一个会话里(
--resume)接着把 7 个类改成DateTimeFormatter
3.2 结果
第一轮四组是成对并行跑的,缓存是冷的;之后我按顺序把任务 1 重跑了一轮,缓存是热的,同时加测了 Haiku 子代理和禁用子代理两种配置。
| 任务 | 做法 | 花费(美元) | 墙钟耗时 | 结果 |
|---|---|---|---|---|
| 任务 1,第一轮 | 主对话自己搜 | 0.137 | 14.7 秒 | 7 个类全对 |
| 任务 1,第一轮 | 派 Explore 子代理 | 0.275 | 36.9 秒 | 7 个类全对 |
| 任务 1,热缓存重跑 | 主对话自己搜 | 0.033 | 11.7 秒 | 全对 |
| 任务 1,热缓存重跑 | 派 Explore 子代理 | 0.097 | 27.1 秒 | 全对 |
| 任务 1 | 派自定义 Haiku 子代理 | 0.056 | 31.9 秒 | 全对 |
| 任务 1 | 项目设置里禁用 Agent | 0.040 | 14.5 秒 | 全对 |
| 任务 2 | 主对话自己查 | 0.073 | 20.1 秒 | 表格全对,431 个方法 |
| 任务 2 | 派 Explore 子代理 | 0.159 | 53.5 秒 | 表格全对,但自己说"没有逐个读完" |
| 任务 3 第一步 | 主对话 | 0.070 | 19.2 秒 | 同任务 2 |
| 任务 3 第一步 | 派 Explore 子代理 | 0.365 | 71.9 秒 | 同任务 2 |
| 任务 3 第二步(改文件) | 主对话会话接着改 | 0.192 | — | 7 个文件改对 |
| 任务 3 第二步(改文件) | 子代理会话接着改 | 0.165 | — | 7 个文件改对,两边 diff 完全一致 |
任务 3 第二步是 --resume 接着上一步的会话跑的,JSON 里的 total_cost_usd 和 modelUsage 是整个会话累计的(我核对过:主对话组第二步的缓存写入 25109 = 第一步 9252 + 本次 15857),表里填的是减掉第一步之后的增量。这一步我没量墙钟时间。
3.3 从数字里看出的四件事
1. 窄任务派子代理,花费翻 2~3 倍,耗时翻一倍多。 任务 1 本质上是一次 Grep,主对话 4 轮就答完了。派子代理时,子代理要重新加载一遍自己的系统提示词、再搜一遍,主对话还要写任务说明、读回总结。两轮测试里子代理组的花费分别是主对话的 2.0 倍和 2.9 倍,耗时是 2.5 倍和 2.3 倍。
2. 子代理交回来的是"有损总结"。 任务 2 两组的表格数字都对,但子代理组的最终回答里写着:"子代理没有逐行读完全部 30 个文件,只精读了 OrderService 和 AuditService,其余是用 Grep 列出……",后面还说那 19 个用 DateTimeFormatter 的类,它没有逐个打开确认是否真的用到了格式化器,问我要不要再派一次子代理去查。主对话组自己 Grep,统计方式和局限说得很清楚。这就是 Anthropic 原文说的信息每转一手丢一些:主对话只能看到子代理愿意写进总结的东西。
3. 子代理的好处确实存在,但这次没赚回来。 任务 3 第二步,子代理会话的主上下文里只有一段总结,没有 30 个文件的搜索结果,接着改文件时花费比主对话会话少了约 14%(0.165 对 0.192)。可第一步多花的 0.29 美元远远没补回来。上下文隔离要在"读了大量材料、后面还要在同一个会话里干很多轮"时才划算。
4. 子代理换成 Haiku 能省钱,省不了时间。 自定义的 date-scanner 子代理设了 model: haiku,子代理本身只花了 0.002 美元,但主对话那边的 Sonnet 花了 0.054,加起来还是比主对话自己搜(0.033)贵,耗时 31.9 秒也最长。派活、等待、读总结这些固定开销,换便宜模型省不掉。
💡 一个实测细节:
claude -p里子代理组的duration_ms只有 7~12 秒、num_turns都是 1,远小于墙钟的 27~72 秒,subagent_stats里显示子代理是started_in_background: 1。在脚本里统计耗时,别只看duration_ms,用time量墙钟时间才准。
四、什么时候子代理值得用
结合原文的三种情况和上面的数字,我的建议是:
| 场景 | 用不用子代理 | 原因 |
|---|---|---|
| 查一个类、搜一个关键字、改一两个文件 | 不用 | 一次 Grep 能解决的事,派出去只多花钱、多等待 |
| 读几十个日志文件、扫一个很大的陌生仓库,只要结论 | 用 | 原始内容很大,后面又用不上,放进主对话会把上下文撑满 |
| 同一个会话后面还要干很多轮 | 倾向用 | 主上下文越干净,后面每轮越便宜(任务 3 第二步省了 14%) |
| 几件互不相关的事要同时做 | 用 | 原文的第二种情况,各自全新上下文 |
| 需要一个只读的审查角色、不想让它有写权限 | 用自定义子代理 | 用 tools 字段限死工具,比在主对话里靠提示词约束可靠 |
| 想靠子代理"分工"提高质量 | 先别 | 这次实测里质量没提高,总结反而带来了"没读完"的不确定性 |
一句话:子代理是用来隔离上下文的,不是用来分工的。按业务拆一堆子代理,正是 Anthropic 那篇文章劝大家别做的事。
五、怎么配置:自定义子代理、换模型、禁用
5.1 自定义一个只读、用 Haiku 的子代理
在项目的 .claude/agents/ 下建一个 Markdown 文件,frontmatter 写名字、描述、工具和模型,正文是给子代理的指令。下面就是我实测用的那个:
---
name: date-scanner
description: 在 Java 项目里搜索日期格式化相关写法(SimpleDateFormat、DateTimeFormatter),只读,返回类名和行号清单。
tools: Read, Grep, Glob
model: haiku
---
你是只读的代码搜索助手。用 Grep 和 Glob 定位,必要时用 Read 看上下文。
只返回结论清单:类名、文件路径、行号、写法(static 字段 / 局部变量),不要贴大段代码。
实测在提示词里点名"用 date-scanner 子代理",subagent_stats.by_type 里出现 date-scanner: 1,modelUsage 里多了一项 claude-haiku-5-5,说明定义生效、模型也切过去了。
几点注意(据官方文档):
description决定主对话什么时候会主动派它,写清楚"什么任务找它"tools不写就继承全部工具,只读角色一定要写model可以写sonnet、opus、haiku、fable、完整模型 ID 或inherit- 放
~/.claude/agents/是个人全局可用,放项目.claude/agents/可以提交到 git 给团队共用
5.2 让内置的 Explore 也跑 Haiku
内置 Explore 默认用主对话的模型。我这次主对话是 Sonnet,modelUsage 里也只有 Sonnet 一项。官方文档的做法是在用户级或项目级定义一个同样叫 Explore 的子代理,它会覆盖内置的那个,用你写的 model:
---
name: Explore
description: 只读的代码搜索与探索,用于定位文件、搜索代码、理解代码结构。
tools: Read, Grep, Glob
model: haiku
---
只读探索代码库,返回结论和文件路径、行号,不贴大段代码。
这一条我没单独实测,按上面 3.3 第 4 点的数字,换 Haiku 能降子代理本身的花费,但派活的固定开销还在。
5.3 团队里禁用子代理
不想让 Claude 派子代理,在项目 .claude/settings.json 里把 Agent 工具禁掉:
{
"permissions": {
"deny": ["Agent"]
}
}
实测加了这条后,我在提示词里明确要求"必须派 Explore 子代理",Claude 回答"我没法派 Explore 子代理,因为这里没有 Agent 工具,所以是直接用 Grep 搜的",subagent_stats.spawned 为 0,花费 0.040 美元。
只想在某次 claude -p 里禁用,用命令行参数:
# 只对这一次运行禁用子代理
claude -p "找出所有 static SimpleDateFormat 字段" --disallowedTools Agent
⚠️ 全局禁掉要想清楚:大仓库里的探索类任务、plan 模式里的调研(用的是内置
Plan子代理)都会受影响。我更倾向于不全局禁,而是在 CLAUDE.md 里写一句"简单搜索直接用 Grep,不要派子代理",这一条的效果我没做对照测试。
六、速查表
| 想做的事 | 做法 |
|---|---|
| 看一次运行有没有派子代理 | claude -p ... --output-format json,看 subagent_stats.spawned 和 by_type |
| 看子代理花了多少 | 子代理用了不同模型时看 modelUsage 里各模型的 costUSD;同模型时 usage 只算主对话,modelUsage 是合计 |
| 统计真实耗时 | 用 time 量墙钟,别只看 duration_ms |
| 自定义子代理 | .claude/agents/<name>.md,frontmatter 写 name、description、tools、model |
| 子代理换便宜模型 | frontmatter 写 model: haiku |
| 覆盖内置 Explore | 定义一个 name: Explore 的子代理 |
| 项目里禁用子代理 | .claude/settings.json 里 permissions.deny: ["Agent"] |
| 单次运行禁用 | --disallowedTools Agent |
七、常见问题
Q:Anthropic 说要并回主循环,Claude Code 的子代理是不是要被砍了?
原文讲的是企业用 API 搭 Agent 时别按业务拆子代理,没有说要去掉 Claude Code 的子代理功能,还专门列了三种适合用子代理的情况。"别学了"这个说法过头了,该学的是什么时候不用。
Q:我没让它派,它自己派了,怎么办?
主对话会根据任务自己判断要不要派 Explore。先用 --output-format json 看看你常用的任务里它派了多少次;派得太频繁,再考虑在 CLAUDE.md 里写规则或者禁用 Agent。
Q:交互模式里的 /agents 命令怎么不是向导了?
据官方文档,2.1.197 及更早版本的 /agents 会打开一个交互向导,之后的版本改成提示你直接让 Claude 写,或者手动编辑 .claude/agents/ 下的文件。我在 2.1.299 交互界面里没截图验证。
Q:子代理是串行还是并行跑的?
这次每次只派了一个子代理,subagent_stats 显示它是在后台启动的。一次派多个时是否真并行,我没测,不下结论。
参考链接
- Building agents: When to fold subagents into your main agent loop(Claude 官方博客,2026-10-22)
- Claude Code 文档:Subagents
- Claude Code 文档:Permissions
- Claude Code 文档:Manage costs effectively
你用
--output-format json跑一下自己最常做的任务,看看subagent_stats.spawned是几?你们团队是放开让它派子代理,还是在设置里禁掉了?评论区说说,我挑典型的补进 FAQ。觉得有用的话点个赞、收个藏,下次调 Claude Code 花费时翻得到。