1. 为什么你的 coding agent 总在自审自批
Vibecoding 走到进阶阶段,很多人会撞上同一堵墙:你让 coding agent 修一个 Bug,它改完代码,顺手在回复里写一句"已验证通过,测试全部通过"。你信了,合入,第二天 CI 红了。回头翻它的输出,发现它根本没跑测试,那句"通过"是它自己脑补的。
这不是模型笨,而是角色设计错了。让同一个 agent 既写实现又做验收,等于让运动员自己当裁判。它对自己刚写下的代码有天然的"确认偏误"——它倾向于相信自己写的是对的,于是审查环节被架空,变成走过场。
我在多智能体协作里踩过最典型的坑就是这个:一个 agent 负责改auth.py,改完自己 review,结论是"逻辑清晰、边界完整"。结果我手动跑pytest tests/test_auth.py,三个用例直接挂掉,其中一个还是它自己新引入的空指针。它审查时压根没看测试文件。
问题的根子在于:写代码和审代码需要的是两种相反的思维模式。写代码要收敛,要快速做决策、落地实现;审代码要发散,要怀疑、要找反例、要构造边界。把这两种模式塞进同一个上下文里,模型会不自觉地偏向"我已经做完了"的完成态,审查就失去了独立性。
所以这一篇要解决的核心就一件事:用AGENTS.md把角色拆开,让 Scout 只找线索、Builder 只做实现、Verifier 只做审查,三者信息隔离、职责不重叠。配合 Codex 的多 Agent 并行能力,把"自审自批"拉回"分权协作"。
适合谁看:已经在用 Codex、Claude Code 或类似 coding agent 做真实项目,发现单 agent 在复杂任务上开始发散、自评失真、越改越乱的人。如果你还在环境搭建阶段,建议先看基础篇把闭环跑通再回来。
下面我会先讲清楚角色分离的设计思路,再给一份可以直接复制进AGENTS.md的约束配置,然后用 Codex 跑一遍多智能体分工的验证流程,最后把常见的报错和排查路径列出来。全程可跟做,配置片段路径和原文一致。
2. TaoToken 前置:给多智能体准备统一的模型入口
在拆角色之前,得先解决一个工程问题:Scout、Builder、Verifier 三个角色如果各自接不同的模型服务,Key 管理、额度、Base URL 会乱成一团。尤其是 Codex 并行跑多个 Agent 时,每个 Agent 都要发请求,你需要一个统一的入口来收口。
我现在的做法是用 TaoToken 作为统一的模型接入层。它兼容 OpenAI 风格的接口,Codex、Claude Code 这类工具只要把 Base URL 指过去、填上 Key、指定 Model ID 就能跑。这样三个角色共用一套凭证,切换模型只改一个 Model ID,不用在每个工具里重复配置。
具体来说,你需要准备三样东西,这也是后面所有配置的基础:
第一是 API Key。到控制台生成一个,注意别把 Key 硬编码进仓库,用环境变量注入。生成入口在 API Keys 页面,建议按项目建不同的 Key,方便后面按角色或按项目统计用量。
第二是 Base URL。Codex 和大多数 OpenAI 兼容工具都认这个地址,填https://taotoken.net/api即可,注意不要带多余的路径后缀。
第三是 Model ID。这个取决于你当前想用哪个模型,在模型列表里选一个,比如做代码实现和审查时选推理能力强的,做 Scout 检索时可以选响应快的。Model ID 要一字不差地填进配置,写错了会直接报模型不存在。
如果你用的是 Claude Code 这类走 Anthropic 协议的工具,接入方式略有不同,需要参考对应的接入文档,把 Base URL 和 Key 按 Anthropic 的格式配置。文档里有分工具的步骤,照着填就行。
这里有个我实测下来的经验:多智能体场景下,不要给所有角色配同一个模型。Scout 做的是检索和范围圈定,用快模型省钱;Builder 和 Verifier 做的是实现和审查,用推理强的模型保质量。统一入口的好处就是你可以按角色灵活切 Model ID,而不用改一堆配置文件。
另外提醒一句,Codex 的并行 Agent 会同时发多个请求,如果你的 Key 有并发限制,记得提前在控制台确认额度,避免跑到一半被限流打断。把入口统一好之后,下面就可以进入正题,开始拆角色了。
3. 可复制配置:AGENTS.md 角色约束与 Codex 分工
这一节是全文的核心,给你可以直接复制落地的配置。先说清楚文件放哪:AGENTS.md放在仓库根目录,Codex 和 Claude Code 启动时会自动加载,对所有对话生效。如果你只想对某个子目录生效,也可以放在子目录里,工具会按就近原则读取。
先给一份完整的AGENTS.md角色约束片段,你可以直接粘进根目录的AGENTS.md:
## 角色约束 ### 当前角色:Scout - 职责:只收集证据,圈定改动范围,不改任何代码 - 必须交付: 1) 相关文件路径清单,按重要性排序 2) 仓库中相似实现或现有模式,精确到函数/类/模块 3) 约束条件:构建、平台、依赖、权限 4) 建议的最小改动范围 - 禁止:写代码草案、提出大范围重构、替 Builder 做实现决策 ### 当前角色:Builder - 职责:只做实现,坚持最小改动 - 红线: 1) 动手前先给出 3-7 步执行计划和验证预期 2) 编码结束交出 diff 3) 提供实际执行过的测试/构建输出 4) 需要加新库或一次改超过 5 个文件时,先停下解释原因 5) 修改必须幂等,避免重复追加导致破相 6) unified diff 失败时,降级为整函数替换或查找批量替换 - 禁止:自行修改测试基线、重构无关代码 ### 当前角色:Verifier - 职责:只做审查和验收,不写实现 - 必须交付: 1) 按严重程度排序的风险清单 2) 未覆盖的测试点和边界条件 3) 基于 diff 的逐项审查结论 4) 最低成本的补救建议 - 判断依据:diff、实际执行结果、测试覆盖、已知约束 - 禁止:凭感觉输出、无验证结果时宣称"应该没问题"、越过风险建议合并这份配置的关键在于把输入、输出、禁止事项写死。模型对"禁止"的敏感度比"建议"高得多,你写"尽量不要重构",它可能照重构不误;你写"禁止重构无关代码",它才会收敛。
接下来是 Codex 的多 Agent 分工。Codex 原生支持并行 Agent,每个 Agent 在独立的 git worktree 里工作,互不干扰。操作路径是:打开 Codex,发起一个任务,点击"+ 新 Agent"就能同时跑多个子任务。Codex 自动管理 worktree 隔离,你只需要审查每个 Agent 的 diff。
但光有并行还不够,你得让每个 Agent 知道自己是什么角色。这里有两种做法:
第一种是手动调度,适合排障和精细控制。你在 Chat A 里以 Scout 身份让它检索,复制它输出的文件清单;在 Chat B 里以 Builder 身份粘贴进去开始实现;最后在 Chat C 里以 Verifier 身份审查。三个 Chat 的上下文互相隔离,Verifier 看不到 Builder 的"自我辩解",审查更客观。
第二种是自动编排,适合固定流程。Codex 的并行 Agent 配合AGENTS.md里的角色约束,你可以在任务描述里直接指定"这个 Agent 作为 Verifier,只审查不实现"。流转路径建议固定成:
scout.pass -> builder builder.pass -> verifier verifier.fail -> builder(打回原因直接发还) needs-human -> 交给你仲裁如果你用的是 Claude Code,它支持通过 Task tool 发起子智能体。你可以在对话里直接说:"你现在作为 Scout 摸清代码范围,然后启动两个子 Agent 分别实现方案 A 和方案 B,最后你来对比选优。" Claude Code 会自动并行跑子任务,你只审查主 Agent 的汇总。
这里补一个 Codex 的配置细节。如果你想让 Codex 走 TaoToken 的入口,需要在配置里指定 Base URL、Key 和 Model ID 三件套。以auth.json或环境变量方式注入时,确保三个值都齐全,缺一个都会导致请求失败。Model ID 要和你在控制台选的模型一致,Base URL 填https://taotoken.net/api。
最后强调一点:角色约束不是写一次就完事。每次开新任务,你都要在任务描述里明确当前 Agent 扮演哪个角色。AGENTS.md提供的是默认约束,但多 Agent 并行时,每个 Agent 的上下文是独立的,你得显式告诉它"你是 Verifier"。这一步偷懒,角色分离就白做了。
4. 验证请求:跑一遍 Scout-Builder-Verifier 闭环
配置写好了,得验证它真的能跑通。这一节我用一个真实的小任务走一遍完整闭环,你可以照着复现。
任务设定:仓库里有个utils/parser.py,其中parse_config函数在处理空字符串时会抛异常。我们要修掉它,但必须走三角色流程。
第一步,Scout 检索。在 Codex 里开一个 Chat,任务描述写:"你当前角色是 Scout,只收集证据不改代码。任务:定位parse_config空字符串异常的根因,交付相关文件清单、相似实现、约束条件和最小改动范围。"
它返回的典型输出会包含:utils/parser.py第 42 行的parse_config、tests/test_parser.py里已有的空字符串用例、以及"建议只改parse_config的入参校验,不动调用方"。注意它没有给代码草案,这是对的。
第二步,Builder 实现。新开一个 Chat,把 Scout 的输出粘进去,任务描述写:"你当前角色是 Builder,按 Scout 的范围做最小改动。先给执行计划,再改代码,最后交 diff 和测试输出。"
Builder 会先列计划,比如:1) 在parse_config入口加空值判断;2) 补一个空字符串用例;3) 跑pytest tests/test_parser.py。然后它改代码,给出 diff,并附上实际执行的测试日志。如果它想加新库或改超过 5 个文件,按约束它会停下来问你。
第三步,Verifier 审查。再开一个 Chat,只把 Builder 的 diff 和测试输出粘进去,任务描述写:"你当前角色是 Verifier,只审查不实现。基于 diff 和测试结果,给出风险清单、未覆盖边界和逐项结论。"
Verifier 的典型输出会指出:Builder 只处理了空字符串,但没处理None;测试只覆盖了"",没覆盖" "(纯空格);建议补一个None用例。这就是角色分离的价值——Builder 自己审查时大概率会说"已覆盖空字符串,通过",而 Verifier 会挑出它漏掉的边界。
验证成功的标志有三个:Verifier 能准确指出 Builder 的遗漏;最终代码确实比第一版更稳;你能随时抽查任意一个 Agent,让它说出"现在第几轮、这轮修什么、成功标准是什么"。
如果你想让验证更省事,可以在 Codex 里用并行 Agent:一个 Agent 跑 Builder,另一个 Agent 跑 Verifier,两者在独立 worktree 里工作,你最后对比 diff。但注意,Verifier 的输入必须是 Builder 的产出,不能让它俩同时从零开始,否则就变成"抢答"而不是"协作"了。
跑完这一遍,你会发现一个反直觉的点:多智能体协作不是给几个机器人喂同样的 Prompt 让它们抢答,而是职责分离加信息隔离。Scout 看不到 Builder 的实现细节,Verifier 看不到 Builder 的自我辩解,每个角色只拿到自己该拿的信息,审查才独立。
5. 常见报错排查:401、local proxy failed 与 OAuth
多智能体跑起来之后,报错基本集中在接入层和角色配置层。这一节把最常见的几类列出来,对照排查。
401 Unauthorized。这是最高频的。原因通常是 Key 没注入、Key 写错、或者 Base URL 和 Key 不匹配。排查顺序:先确认环境变量里OPENAI_API_KEY或对应工具的 Key 变量有值;再确认 Base URL 填的是https://taotoken.net/api,没有多余路径;最后确认这个 Key 在控制台是启用状态、额度没耗尽。多 Agent 并行时,如果只有一个 Agent 报 401,检查是不是那个 Agent 的配置没读到环境变量。
local proxy failed / connection refused。这个报错通常出现在工具尝试走本地代理但代理没起来的时候。如果你没配代理,检查工具配置里是不是残留了http_proxy或https_proxy环境变量,清掉再试。Codex 并行 Agent 场景下,多个 Agent 同时发请求,如果本地有代理层,容易被并发打挂,建议直接走直连。
reading 'choices' 报错。典型信息是Cannot read properties of undefined (reading 'choices')。这说明请求发出去了,但返回体里没有choices字段,通常是响应格式不对或返回了错误对象。排查:确认 Model ID 填对了,填错模型名时服务端可能返回非标准结构;确认 Base URL 没写错,写错路径会返回 HTML 错误页而不是 JSON。用 curl 直接打一次接口,看返回体结构最直接。
OAuth 相关报错。如果你用的是 Claude Code 这类走 OAuth 的工具,报错可能是 token 过期或授权范围不对。这类工具接入时,Base URL 和 Key 的填法和 OpenAI 兼容工具不同,要按 Anthropic 协议的格式来。遇到 OAuth 报错,先重新走一遍授权流程,再确认配置里的 Base URL 是https://taotoken.net/api对应的 Anthropic 接入地址。
角色不生效。配置写进AGENTS.md了,但 Agent 还是自审自批。排查:确认AGENTS.md在仓库根目录,且工具确实加载了它(有些工具需要重启会话);确认任务描述里显式指定了角色,多 Agent 并行时每个 Agent 的上下文独立,不指定它不知道自己是 Verifier;确认没有多个AGENTS.md冲突,子目录的会覆盖根目录的。
diff 应用失败。Builder 给的 unified diff 打不上。这是常见问题,按约束它应该降级为整函数替换或查找批量替换。如果它没降级,你在任务描述里补一句"diff 失败时改用整函数替换"。另外,worktree 隔离场景下,确认你审查的是对应 Agent 的 worktree,别拿错分支的 diff。
并发限流。Codex 并行跑多个 Agent 时,如果 Key 有并发上限,会出现部分请求被拒。表现是间歇性失败,不是每次都报错。排查:在控制台看用量曲线,确认是否触顶;减少同时运行的 Agent 数量,或给不同角色分配不同的 Key。
把这几类对照一遍,基本能覆盖 90% 的接入和配置问题。剩下的多半是任务描述写得太模糊,导致 Agent 角色漂移,回到第 3 节把角色约束写死即可。
6. 把 Agent 拉回可控协作:下一步怎么走
走到这里,你已经有了三样东西:一份可复制的AGENTS.md角色约束、一套 Codex 多智能体分工的验证流程、一份常见报错的排查清单。这三样合起来,解决的就是"coding agent 既当裁判又当运动员"这个失控场景。
我自己的用法是:日常小改动,单 Agent 加 Skills 卡片就够;一旦任务跨多个文件、涉及多个模块,立刻切三角色流程。Scout 先圈范围,Builder 做最小实现,Verifier 独立审查。三个角色的上下文严格隔离,Verifier 永远看不到 Builder 的自我评价,这样它才会真的去挑毛病。
如果你想把流程再往前推一步,可以试试长任务治理。核心思路是把大任务切成一段段可验收的小结果,每轮只盯一个改动点,每轮结束交证据(改动概要加 diff 加验证日志),设硬性上限(最多 N 轮或 T 分钟),超了就停下汇报。碰到红线(拉大依赖、改大批文件、查不出原因的报错)立刻停手。这样即使任务发散,你也能随时回滚到上一个存档点。
工具层面,大多数人用AGENTS.md加 Codex 或 Claude Code 的内置多 Agent 支持就够了,不需要自己写调度代码。只有当你需要把多 Agent 流程接进 CI/CD 做完全定制化 pipeline 时,才值得上 LangGraph 这类图编排框架。
最后留一个我常用的检查动作:每次任务结束,问 Verifier 一句"Builder 这轮漏了什么"。如果它能说出具体的边界或测试点,说明角色分离生效了;如果它只会说"看起来没问题",那多半是角色约束没写死,或者 Verifier 拿到了 Builder 的上下文被带偏了。这个动作花不了几秒,但能帮你判断协作链路是不是真的可控。
下一篇会讲安全、评测和工程化,把这条链路补完整。在那之前,先把这篇的三角色流程在你的仓库里跑通一遍,比看十篇教程都管用。