在Claude Code中fan out subagent,再检查返回的结果
在Claude Code中,fan out指的是把一项工作拆成互相独立的分片,每个分片交给自己的subagent运行:可以直接开口要求,可以用/batch,也可以用claude -p循环。已在Claude Code 2.1.301上验证。还会介绍我们如何检查每晚翻译本博客的六个subagent合并后的结果。
很多人在Google里输入“claude fan out subagents”,还有不少人在后面加上“command”,好像有个开关可以一拨就开。其实有一种做法,也有一个命令。我们在2026年10月16日用Claude Code 2.1.301和Anthropic的文档核对了这两者。
还有一部分是文档很少提到的,也是我们写这篇文章的原因:拿到结果之后该怎么办。我们每晚都运行一次fan out。六个subagent把这个博客的每篇新文章翻译成十七种语言,主会话再合并它们的工作。每一个subagent都报告说自己遵守了规则。可我们在启动前写好的检查,仍然会发现问题。
简短的回答
fan out指的是一个会话把一项工作拆成互不依赖的分片,把每个分片交给一个subagent,让它们同时运行,再合并返回的内容。在Claude Code中有三种做法。
| 做法 | 输入什么 | 每个分片在哪里运行 | 适合 |
|---|---|---|---|
| 在提示词里要求 | “用不同的subagent并行研究auth、数据库和API模块” | 你会话中的一个subagent,独立上下文,返回摘要 | 调研和阅读 |
/batch | /batch migrate src/ from JavaScript to TypeScript | 5到30个后台subagent,每个一个git worktree | 横跨整个代码库的大改动 |
| 脚本循环 | 每个文件调用一次claude -p | 每次调用一个独立的非交互会话 | 数百个文件、CI |
本文接下来逐一介绍每种做法,然后介绍我们在自己的fan out上运行的检查。
subagent能看到什么,看不到什么
文档中的三个事实决定了你该怎么拆分工作。
每个subagent都从零开始。 它在自己的上下文窗口中运行,有自己的系统提示词、工具和权限。它看不到你的对话,看不到你已经用过的技能,也看不到Claude已经读过的文件。它需要知道的一切,都必须写在它的任务简报里。
结果会回到主对话。 subagent工作中冗长的部分留在它自己的上下文里,只有结果会返回。但如果很多subagent都返回很长的报告,仍然可能塞满你的主上下文,而且每个subagent在运行时都消耗自己的令牌。
有上限。 默认情况下,一个会话中同时最多运行20个subagent。第21个会以Concurrent subagent limit reached失败,而且这个错误会告诉Claude不要重试。你可以用CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS调高或调低这个上限。subagent可以启动自己的subagent,最多到主对话下方三层,一个会话中的总数没有限制。
做法一:直接用自然语言要求
最简单的fan out就是一句话。Anthropic文档中的例子:
Research the authentication, database, and API modules in parallel using separate subagents
每个subagent探索自己的部分,然后Claude写出一份综合结论。文档补充了关键的条件:调研路线互不依赖时效果最好。如果关于数据库的问题需要先知道关于auth的答案,那你手里的不是三个分片,而是一个先后顺序。
用自然语言要求时,由Claude来决定。如果你在.claude/agents/中定义了自定义subagent,用@提到它,就能保证它在这个任务中运行。这些文件如何工作,见我们关于Claude Code subagents的页面。
做法二:/batch,最接近fan out命令的东西
/batch是Claude Code内置的一个技能。你给它一条指令:
/batch migrate src/ from JavaScript to TypeScript
它会研究代码库,把工作拆成5到30个独立单元,并给你看一份计划。你批准后,它为每个单元启动一个后台subagent,每个都在隔离的git worktree中。每个subagent实现自己的单元,运行测试,并发布自己的改动。它需要一个git仓库,或者一个为其他版本控制系统创建worktree的WorktreeCreate钩子。
计划这一步要放慢。拆分就是在这里决定的,而拆分就是全部:两个改动同一个文件的单元,或者一个需要另一个单元输出的单元,不管每个subagent多出色,都无法干净地合并。读这份单元清单时,要像读一位同事写的迁移计划那样。
做法三:用claude -p循环
当工作是一份文件清单、而你想掌控每一次调用时,Anthropic的最佳实践介绍了一种循环。先让Claude写出清单(list all 2,000 Python files that need migrating and save the list to files.txt)。然后:
for file in $(cat files.txt); do
claude -p "Migrate $file from Python 2 to Python 3. Return OK or FAIL." \
--allowedTools "Edit,Bash(git commit *)" \
--permission-mode dontAsk
done
这个例子里有三个细节值得照搬。
- 回答让机器来读。 “Return OK or FAIL”意味着你的脚本不用读文字就能统计失败数。
- 权限提前定好。
--allowedTools只批准迁移所需的操作,--permission-mode dontAsk拒绝其余一切,而不是等一个不在场的人。 - 先从两三个文件开始。 文档说得很直白:根据前几个文件出的问题改进提示词,再跑完整清单。
按原样写,这个循环是一个文件接一个文件处理的。同时运行多个调用只是普通的shell操作,但每次调用都是一个完整的会话,占用你的机器和你的配额。我们在这篇文章里测量过多个代理在同一分钟启动同一条重型命令时会发生什么,这里也是同样的道理:并行调用先从少量开始。
对于CI,文档建议加上--bare,它会跳过钩子、技能、MCP服务器和CLAUDE.md,让每台机器都得到相同的运行结果。bare模式不使用你订阅的登录:它需要ANTHROPIC_API_KEY。
我们每晚如何fan out
下面是我们真正在运行的fan out。我们的夜间SEO团队手工用英文和法文撰写每篇新文章。接着第二个代理用Claude Code的subagent把它翻译成另外十七种语言,并用脚本从简体中文生成繁体中文,而不是重新翻译。自2026年9月13日以来,已有十一篇文章走过这个流程,每篇最终是二十个文件。
分片
六个subagent,每个负责三种语言(最后一个负责两种):西班牙语、葡萄牙语和意大利语;德语、荷兰语和波兰语;俄语、乌克兰语和土耳其语;日语、韩语和中文;泰语、越南语和印尼语;阿拉伯语和印地语。没有任何一种语言依赖另一种,这正是它成为一次干净fan out的原因。
每份任务简报都包含同样的五样东西,因为subagent看不到别的:
- 英文原文,以及作为语气和产品术语参考的法文版;
- 每种语言在网站上已经发布的句子,让subagent沿用网站已有的用词,而不是自己发明新词;
- 硬性规则:品牌名和产品名保持原样,代码逐字节不变,不用长破折号;
- 检查脚本,并要求一直运行到它返回OK为止;
- 要求它报告看到的任何可疑之处,无论在自己的分片之内还是之外。
检查在启动前写好
检查是一个脚本,而不是某个subagent的意见。它把每种语言的文件与英文原文对比:
- slug和日期相同,标题与H1一致;
- 章节、小节、图片、链接和表格行数相同,正文中的FAQ回答数与元数据中的问题数相同;
- 链接逐字节相同,代码片段逐字节相同;
- 统计品牌名出现次数,绝不能少于英文;
- 长度在为每种语言校准的范围内,因为中文说同样的内容大约只需要英文36%的字符,日文大约一半;
- 有重音符号的语言要带上重音符号(波兰语、土耳其语、越南语)。
每个subagent最后都会说一句类似“完成,所有检查通过”的话。我们唯一据以行动的判定,是由主会话对所有文件一次性重新运行的同一个脚本。
中央检查发现了、而自我报告没有提到的问题
表格里的代码被翻译了。 9月13日,大约一半的subagent把表格中与命令放在同一对反引号里的后续文字翻译了。每个都按自己理解的方式遵循了任务简报。修正落在任务简报上,而不是subagent上:代码片段里只放命令,后面的文字放到反引号外面。
我们自己的检查错了。 9月6日,一个按我们要替换的旧句子校准的长度检查,在17个subagent中标记了11个。这11个都是对的:新文本本来就应该更长。改为按已修正的法文校准后,一个都没有被标记。中央检查也可能出错,发现它的办法是先在一份你已知没问题的交付物上运行它。
分片之间的一致性。 10月15日,在一个用同样方式翻译的新功能页面上,合并检查确认90个文件中只有预期的句子发生了变化。但日语、韩语和中文的subagent,各自为“You may also like”选了一个标题,与它们的语言在相邻页面上已经使用的不同。每个选择都是正确的翻译。没有一个与网站一致。没有哪个subagent能从自己的分片里看到这一点:只有对合并结果做一遍检查才能看到。
一个错词能通过所有结构检查。 网站的某种语言曾经把AI代理称作汽车经销商,而且在线上挂了好几个月。长度相同,标点相同,品牌名也在:所有计数都是绿色。唯一能抓住它的,是一份列出已知错词的清单,它会拦下每一次部署,每发现一个新错词就增加一行。
分片之外的报告。 10月15日,负责土耳其语的subagent报告说,网站在97个现有句子里把“agent”写成了“ajans”,也就是代理机构。它没有去改,因为任务简报不允许。我们开了一个工单,修复在第二天上线。问subagent看到了什么,而不只是做了什么,代价很小,回报不错。
合并在一个地方完成
subagent不直接写入仓库。每个都交回自己的文件,由脚本合并,然后逐句把结果与上一个版本比较:只有我们要求修改的句子才允许变化。之后,仓库的检查和网站的构建只在合并后的结果上运行一次。每个subagent各跑一次构建会更慢,而且测试的是永远不会上线的半合并状态。
什么时候不要fan out
- 分片之间互相依赖。 如果分片B需要分片A的输出,就按顺序运行。
- 工作量很小。 每个subagent都从零开始,重新读取它需要的内容。对一个十分钟的任务来说,重新开始的成本比省下的还多。
- 你写不出检查。 如果不亲自全部读一遍就无法区分好分片和坏分片,你的时间就会花在合并上。
- 配额很紧。 每个subagent都消耗自己的令牌。fan out换来的是时间和干净的主上下文,而不是更少的账单。
AgentsRoom的位置
subagent活在一个Claude Code会话的内部。你看到的是它们的结果,而不是它们的工作过程,也无法在中途引导其中某一个。如果你希望每个分片都是一个可以单独观察、回复和审查的代理,那就改为运行独立的会话:每个工单在自己的git worktree里,分片之间需要交接工作时用Agent Teams。团队中的一个步骤可以带上一条检查命令,决定这次运行能否继续的,是它的退出码,而不是代理自己的说法。这和上面是同一条规则,由运行器来执行。它适用于Claude Code、Codex以及AgentsRoom支持的其他代理CLI。
如果你还在subagent和Agent Teams之间犹豫,这篇对比解释了它们各自适合做什么。
下载 AgentsRoom
在一个窗口中运行你所有项目的所有 AI 代理。
配套应用:随时随地监控你的 Agent
使用 Claude、Codex、Antigravity CLI 或其他 AI 提供商。
把 Bug 和需求直接发送到您的公开待办清单。
继续阅读
Codex、OpenCode、Antigravity 和 Claude Code 的语音模式:哪个 CLI 有?
我们在 2026 年 10 月 13 日检查了五个编程代理 CLI 和两个应用。Codex CLI 和 oh-my-pi 能进行语音对话,Claude Code 和 Antigravity CLI 只能把语音听写进提示词,OpenCode 没有任何内置功能。每个怎么启动、音频发往哪里,以及语音要花多少令牌。
阅读全文Claude 的令牌是什么,又是怎么运作的?我们数了 38 亿个
令牌是词的一个片段,Claude 会统计四种令牌:输入、缓存写入、缓存读取和输出。我们统计了自己 30 天的 Claude Code 会话,共 38 亿令牌:98% 是从缓存里重新读取的对话,Claude 写出的只占 0.3%。每种令牌的成本、为什么会话每多一轮就更重,以及 5 小时窗口到底在计量什么。
阅读全文SSH 断开后让 Claude Code 继续运行:tmux 配方
用 tmux 让 Claude Code 在 SSH 断开后继续运行。重新连回同一个进程,检查持久性,并使用 AgentsRoom 需手动开启的设置。
阅读全文