你是否曾经在晚上 11 点写了一个技术计划,确信一切无懈可击,但第二天早上发现忘记添加身份验证?
我深有同感,而且不止一次。最糟糕的不是这个疏忽——而是当你用人工智能来规划时,计划听起来是如此连贯,以至于你的大脑停止了对问题的挖掘。Claude 会生成一个带有章节、依赖项和执行顺序的文档,一切看起来都是高级工程师的作品。但问题是,没有人反驳过它。
Aseem Shrey 发布了一篇文章,精准点出了这个问题,并为此提出了一个优雅的解决方案:让第二个模型审查第一个模型的计划。而且不仅仅审查一次——循环审查,直到审查员说“通过”。
问题:没有人反对你的 AI
当你仅依靠一个模型来规划和执行时,你得到的结果确实连贯但没有争议。AI 不会反驳自己。它不会说“嘿,这个身份验证模型不完整”,或者“你的 shell 脚本中的引用有问题”。
这就像你自己写了一份文档,自我审查,然后对自己说“这可真是完美”。当然是完美的——毕竟是你自己写的。注意这个点:同行评审会存在于科学、工程和医疗领域是有原因的。并不是因为作者愚蠢,而是因为创作者通常是自己作品最差的审查者。
我以前在写我的 Jedi 代码审查委员会时讨论过这个问题。不过当时谈论的是如何审查代码。而 Aseem 的建议是先审查计划,在写出任何代码之前就发现问题。这相当于提前一阶段处理问题。
操作方法:Claude 规划,Codex 审查
这个过程基于 Claude Code 的一个“技能”实现——一个 Markdown 文件,无需额外的基础设施或外部服务。当你调用 /codex-review 时:
- Claude 会将计划写入一个临时文件。
- 计划会以只读模式发送到 Codex CLI(它可以读取你的代码库获取上下文,但不改动任何东西)。
- Codex 审查后会给出结论:
VERDICT: APPROVED或VERDICT: REVISE。 - 如果返回的是 REVISE,Claude 会修正计划并重新提交。关键在于,Codex 会恢复之前的会话,因此能够记住它之前的反馈,并验证问题是否真的被解决了。
- 审查最多迭代 5 次。在实践中,通常 3 次就足够了。
简而言之,这是两个 AI 之间的一次“拉取请求”,一个提出计划,另一个专注于找漏洞。全程无需人为干预。
3 轮迭代解决了 14 个漏洞
在 Aseem 的文章中,以一个多代理系统的控制面板为案例,循环审查从原计划中找到了 14 个问题:
第一轮(8 个问题):写入端点没有身份验证。Shell 脚本的引用存在错误。数据模式的字段冲突。嵌套数组没有限制。未处理并发问题。仅支持手动测试。
第二轮(剩余 6 个问题):非原子操作的声明。ACL 权限分配过于宽泛。未指定密钥轮换机制。状态建模不一致等问题。
第三轮:所有问题解决,计划获得通过。
下表概括了迭代前后:
| 原计划 | 修改后 |
|---|---|
| 一次性通过的计划 | 经过 3 轮迭代审查 |
| 缺乏身份验证模型 | 提供每个代理的 API 密钥与 ACL 矩阵 |
| 错误的 Shell 脚本 | 类型安全的命令行接口,支持重试 |
| 易冲突的数据模式 | 单一数据源 |
| 缺乏并发处理 | 原子化声明 + 版本控制 |
| 仅手动测试 | 增加集成测试与安全测试 |
从初始的 0 个问题,到检测并修复 14 个问题,整个过程中无人阅读过计划文档的任何一行。
为什么“迭代”比“单次审查”更重要
单次审查确实能发现问题,但它无法验证修改是否解决了问题。Aseem 解释得很好:循环迭代可以解决“修复了一个地方,但破坏了另一个地方”这类问题。
这也正是真实代码审查中会发生的事情。你告诉一个同事,“这个锁不安全”,他们修复了,但新改动又可能引入了其他路径中的死锁。如果只看一次,这类问题很容易被忽略。如果看两次,就能抓住漏洞。
让这个体系有效运转的技术细节:Codex 支持会话的 resume 功能。它不会在每一轮都从零开始,而是记住之前的反馈内容,并确认修复措施是否有效——而不是用来敷衍问题的临时补丁。
我想尝试的事情
读完这篇文章后,我很想尝试搭建一个类似的流程。我把 plan.md 作为几乎所有重大功能开发的第一步,而目前通常是自己复查。实际上,这等同于没有经过真正的审查。因为当你在 Linear 上连续工作了三小时之后,思路难免会疲劳。
引入一个 /second-opinion 的想法听起来很自然。当然不是为所有事情而设计——我不会为改变 CSS 的改动走三轮审查流程。但对于涉及数据模型、身份验证、并发或需要花费几天时间来实现的东西,拥有一个自动化的“对抗者”来提醒你“如果两个代理同时请求资源会怎么样”是无价之宝。
特别吸引我的几点:
- 它只是一个 Markdown 文件。 没有服务器、API 包装器或杂乱依赖。一个
SKILL.md文件就充分搞定。 - 按需调用。 它不会在每次提交或每个计划时运行——你可以决定哪些时候值得调用这个工具。遇到重要的事情时,加把劲就够了。
- 对抗性设计。 你不是请求审查员“看看计划”,而是明确要求它找漏洞,试图击垮这个计划。这种设计思路完全改变了结果。
明显的问题
有一个显而易见的问题是,文章并没有完全回答:必须用 Codex 吗?还是任何模型都可以当审查员?
我的直觉是,这取决于模型的多样性。关键在于偏差的差异性。如果 Claude 负责规划,Claude 也负责审查,那无异于你自己审查自己——它们共享相同的盲区。引入一个接受不同训练、有不同启发方式的模型,才是真正实现“魔鬼代言人”的关键。
话虽如此,使用 Codex CLI 实现确实有一个重大的现实优势:它的会话 resume 功能。审查员记住每一轮内容的能力不是“锦上添花”——这才是让这个循环成为真正改进工具的核心,而不是简单、独立的三次重复审查。
不适用场景
Aseem 自己提到过:当速度比全面性更重要时,这种方法就不值得应用。在凌晨三点的生产线上进行紧急修复时,你不需要进行三轮对抗审查;这时,只需打个补丁,做个测试,然后立即发布。
我也可以想象,对于小型计划来说,例如“为一个表单添加字段”,这个额外的工作可能得不偿失。我为自己设的规则是:如果计划超过一页,或者涉及到两个以上的模块共享内容,就值得来一个 /second-opinion。
道理
这个理念中最有意思的不是技术实现(非常简单),而是思维方式的转变。在此之前,普遍的共识是“用 AI 来规划,然后按计划执行”。没有人会质疑计划的合理性,计划似乎是神圣的——因为它是由智能模型生成的。
但未经审查的计划,就是潜伏着 bug 的计划。无论作者是 GPT-4、Claude、Codex 还是拥有二十年经验的工程师,缺少对抗性审查,没有人提出“如果这不成立该怎么办”,那么你就是在和隐藏复杂性玩轮盘赌。
一个 Markdown 文件。两个模型。三轮迭代。十四个漏洞减少了。这么简单的东西能装进一个 gist 文件里,真是令人惊讶。