多代理工作流 — Claude Code + Codex CLI 协作
从一个 AI 代理扩展到两个时容易出现的问题 — 角色分工、交接文档、验证门禁、真实失败案例。
从单个代理起步、扩展到两个或多个时,最先崩溃的是**「它们共享上下文」的假设**。人类可以通过 Slack、会议或面对面沟通来弥补信息差,代理做不到。委托任务不能停留在「口头承诺」层面,而必须是用代码强制执行的门禁。
我认为多代理协作的本质不在于并行提速,而在于上下文隔离。以前我们期望单个代理承载一切;如今通过明确的角色分工,每个代理只处理自己范围内的信息,因为上下文边界正是质量的保障线。
本指南汇总了持续运行 Claude Code(主代理)+ Codex CLI(子代理) 超过一周的实战模式。同样的模式适用于其他组合(Cursor + Claude Code、Aider + Claude Code 等)。
TL;DR
- 角色分工 — 分析/规划/指令交给 Opus(主);执行交给 Sonnet / Codex(子)。同一任务两个都做会产生分歧。
- 编写交接文档 — 不是 Slack 消息。是另一个代理可以读取并从中完成工作的完整文档。
- 将验证门禁封装为代码 —
npm run verify:{phase}脚本 + CI 检查。没有门禁,差距会累积。 - 每个代理一个任务 — 不要盲目信任子代理结果。主代理在合并前重新运行。
为什么需要多代理
一个代理对许多任务来说已经足够:单文件编辑、短重构、代码审查。多代理在以下场景具有优势:
- 可并行的独立工作 — 前端 + 后端 + 迁移同步推进
- 与模型能力对齐的分工 — 推理(Opus)和执行(Sonnet/GPT)各司其职,降低成本并提高速度
- 上下文隔离 — 在大型代码库中保护主代理的 context window
- 独立验证 — 作者与审核者分离,带来客观性
以下场景得不偿失:
- 工作集中在单个文件 — 合并冲突会抵消协作收益
- context window 极小 — 交接文档比工作本身花费更多时间
- 规格模糊 — 两个代理会因解读不同而产生分歧
1. 角色分工 — 谁做什么
常见错误是「让两者做相同的工作」,结果产生分歧,没人负责。
推荐分工:
| 角色 | 模型 / 工具 | 负责 |
|---|---|---|
| 主(架构师) | Claude Opus(Claude Code) | 分析 · 计划 · 指令 · 交接审查 · 合并决策 · 文档 |
| 子(构建者) | Claude Sonnet 子代理或 Codex CLI | CLI 运行 · 构建 · 测试 · 重复任务 · Explore(文件搜索) |
| 审核者 | (可选)独立 Sonnet 实例或人工 | 重现结果 · diff 审查 · 门禁确认 |
即使只有一个人同时操作两者,也要分开会话。如果主代理用自己的上下文验证自己的结果,客观性就丧失了。
只有主代理做的事
- 计划 + 权衡评估 + 替代方案比较
- 记录决策背后的「为什么」
- 编写交接文档
- 合并前验证子代理结果(重新运行,检查门禁原始输出)
只有子代理做的事
- 明确定义的任务 — 输入/输出/验收在交接文档中明确
- 重复性 CLI 工作(构建、测试、迁移运行)
- 大型代码库的 grep/find — 保护主代理上下文
两者都不应该做的事
- 「弄清楚怎么做然后告诉我」— 两个不同的答案需要协调
- 「写代码并验证」— 自我审查会有盲点
2. 交接文档模式
交接文档是另一个代理可以单独读取、并据此完成工作的完整文档。不是 Slack 消息,也不是简短 prompt。
必需章节
# Phase X — {标题}
## 目标
{一句话:完成什么}
## 上下文
- 相关文件:`src/foo.ts:42`、`tests/foo.test.ts`
- 前期工作:PR #123 已合并,RFC-005 已采纳
- 外部依赖:API 规范 `docs/api.md` v2
## 范围
1. 修改 {文件 A} 中 {函数 B} 的签名
2. 在 {文件 C} 中添加新函数 D
3. 更新 {文件 E} 中的四个测试
## 非目标
- 不做 {诱人的扩展}(下一阶段的工作)
- 不做 {重构冲动}(单独 PR)
## 验收标准
- [ ] `npm run verify:phase-X` 通过
- [ ] `npm run typecheck` 干净
- [ ] PR diff 小于 300 行(更大则拆分)
## 验证命令
\`\`\`bash
npm run verify:phase-X # 阶段专属门禁
npm test src/foo # 单元测试
\`\`\`
## 卡住时
- 遇到同一错误 3 次,报告回来(不要无限自循环)
- 外部 API 返回与预期不同,报告(不要伪造响应)
## 作者 / 日期
csmarch · 2026-05-12核心原则
- 自包含 — 只靠交接文档就能完成工作。「我们在 Slack 聊过」无效
- 说明范围和非范围 — 有效阻止善意的范围蔓延
- 验收标准即代码 — 用具体的
npm run verify:phase-X门禁替代「如果能运行就 OK」 - 卡住报告规则 — 明确限制自我调试时间
交接文档的篇幅应随任务规模变化。一行改动写 100 行交接文档是浪费。5+ 文件或新模块 → 必须有交接文档;1–2 文件的 bug 修复 → 一行聊天即可。
3. 验证门禁 — 承诺即代码
最常见、代价最高的错误:「合并后再验证。」
子代理报告完成,主代理信任并直接进入下一阶段。一旦下一阶段出现问题就需要回溯,差距持续累积,最终爆发为一次大规模补救。
原则:将验证脚本与合并门禁和交接文档打包在同一个 PR 中。
三个门禁
- 本地验证脚本 —
npm run verify:phase-X或npm run verify:auth,每任务专属 - CI 门禁 — GitHub Actions / GitLab CI 自动运行
verify:phase-X。失败则阻止合并 - 主代理重新运行 — 主代理在自己的环境中重现子代理结果。结果相同 → 合并
示例 — verify:phase-X 脚本
// package.json
{
"scripts": {
"verify:phase-A": "tsc --noEmit && eslint src/phase-a && jest src/phase-a --coverage",
"verify:phase-B": "...",
"verify:assets": "node scripts/check-asset-sha256.mjs"
}
}GitHub Actions 门禁示例
# .github/workflows/ci.yml
name: CI
on: [pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm build
- run: pnpm verify:assets # 阶段验证遵循同样的模式子代理完成报告格式
子代理报告阶段完成时,附上:
[Phase X complete]
- 变更文件:5 个(src/foo.ts, ...)
- verify 原始输出:
$ npm run verify:phase-X
✓ tsc clean
✓ eslint clean
✓ jest 23 passed
- PR:#234
没有附原始输出的报告 → 追问一次。不要相信「可以运行」这类文字描述。
4. 每个代理一个任务 — 不要盲目信任结果
子代理报告完成后不要立即推进。主代理做三件事:
- 重新运行 — 不要相信子代理的 verify 原始输出,主代理在本地运行相同命令。如果不同,调查(环境差异?竞争?缓存?)
- Diff 审查 — 以人工审查深度审查 PR diff。注意范围外的改动、缺少注释、没有测试
- 尝试反例 — 除验收标准外,自己运行 1–2 个「这肯定不能破坏」的案例
这不是对子代理能力的质疑 — 代理从根本上看不到自身上下文的盲区。人类同样无法客观审查自己的代码。
5. 真实失败案例
案例 — 有交接文档但没有门禁
情况:UI 重新设计 Phase D 被委托。交接文档列出了 8 个验收项,子代理报告「全部完成」。主代理合并,Phase E 开始。
问题:Phase D 的验收项 #4 实际上并未通过(子代理将部分实现误判为 OK)。Phase E 依赖 Phase D 的功能并崩溃。调试 Phase E 需要回溯到 Phase D,同样的模式在 F 中重复。
恢复:用一个单独的阶段补救 D~F,事后补写 verify:phase-D 脚本。若门禁从一开始就存在,就会在合并前先行失败。
教训:没有验证脚本的验收标准会随时间漂移。将交接文档 + verify 脚本 + CI 门禁打包在同一个 PR 中。
案例 — 自我无限循环
情况:子代理被要求「修复失败的测试」。子代理自行尝试了 5 种不同方案,每次都产生新的错误。一小时后回报:「尝试了各种方法,没成功。」
问题:交接文档中没有「卡住报告」规则,子代理缺乏判断何时应该求助的标准。
恢复:在交接文档模板中添加「同一错误遇到 3 次后立即报告」条款。主代理凭借更广的上下文提出了不同的诊断假设。
教训:在交接文档中明确规定卡住规则。「继续尝试」→ 改为「3 次失败后,立即报告。」
6. 入门检查清单
迁移到多代理的第一周:
- 定义主代理的角色/规则 —
CLAUDE.md或等价物:角色、自主权、禁止事项、代码风格 - 从一个子代理开始 — Codex CLI 或一个 Sonnet 子代理。不要同时用 3–4 个
- 保持第一次交接简短 — 1–2 个文件的工作,2–3 个验收项,一个 verify 脚本
- 在 GitHub Actions 中注册一个 verify 门禁 — 随着阶段增加
- 应用卡住规则 — 3 次失败后报告 + 主代理审查
- 每个阶段后复盘 — 一行笔记记录缺什么。交接模板会随时间演进
故障排查
「交接文档太长,我失去动力了」
任务太大。把阶段切小。超过 100 行意味着这项工作需要超过一周时间。
「子代理一直做范围外的工作」
「非目标」部分缺失或模糊。不要用「不要重构」,而用「不要动 src/legacy/」— 要具体。
「没时间写 verify 脚本」
在编写交接文档的同时写 verify 脚本,而不是等代码完成后再补。每个验收项对应 verify:phase-X 中的一个断言。
「两个代理一直冲突」
上下文隔离失败。它们的范围重叠。交接文档的「范围 — 文件列表」必须可以干净地分离。两个人编辑同一文件也会冲突。
「主代理成了瓶颈」
解决方案不是给子代理更多权限。主代理始终保留验证 + 合并决策权。正确做法是投资于交接/门禁自动化,并缩减工作量(更小的范围、更简单的计划)。
参考资料
- Claude Code 配置 — 先配置主代理
- Anthropic — Claude Code subagents(子代理最佳实践)
- OpenAI Codex CLI — openai-codex GitHub
更新日志
- 2026-05-12:初稿。一周以上运营经验,整理为六个部分 + 五个故障排查案例。