让两个 AI 互审代码跑了 30 天,结果还是被我 5 分钟内揪出了 Bug
直接给结论:用一个 AI 写代码,再用另一个 AI 扮演“杠精”来审,确实能干掉大部分低级错误和代码冗余,但它永远处理不了那种涉及外部系统状态同步的逻辑死角。如果你想完全去掉人工 Review,现在还太早。
我之前试过让同一个模型写完代码后问它「这段代码有 Bug 吗」,结果它总是用一种更温和的语气肯定自己是对的。所以这次我搞了个双 Agent 机制,完全隔离,中间不接人工。
怎么配置这两个 Agent 才能不互相拍马屁
最关键的是不能给相同的 Prompt。如果一个叫「作者」,另一个叫「审核员」,结果大概率是互相点赞。我把第二个 Agent 定义为 Skeptic(怀疑论者),给它的指令是对抗性的。
Author Agent(作者): 正常的开发指令,要求实现功能并确保测试通过。
Skeptic Agent(怀疑论者): 绝对禁止给它「检查是否正确」这种宽泛指令。我给它的具体 Prompt 逻辑是:"假设这段代码是坏的。请构造一个能让客户损失金钱的输入用例。找出这段代码重复实现的既有功能。寻找一个没有任何人设计的边界状态。"
这种「寻找失败」而非「验证正确」的逻辑差异,决定了它能不能发现问题。
这套方案能解决什么,不能解决什么
跑了 30 天,一共出现了 41 个本该被 Review 掉的真实问题,Skeptic 抓住了 38 个。
它能高效解决的坑:
- 代码重复(Architecture Drift): 比如作者 Agent 没意识到项目里已经有
formatCurrency函数,又写了一个类似的。Skeptic 能在 Diff 中快速识别出这种冗余。 - 吞掉的错误(Swallowed Errors): AI 习惯用
try/catch把所有东西包起来然后log一下就跳过。Skeptic 盯着「隐藏了什么失败」,能精准地把这些死掉的 catch 块给揪出来。 - 并发竞争(Race Condition): 这是一个惊喜。两个请求同时操作一个计数器且没有锁,测试环境下 100% 通过,但 Skeptic 通过逻辑推演发现了潜在的并发冲突。
它绝对会漏掉的坑:
剩下的 3 个 Bug 属于同一个物种:静默的数据一致性失败。
我写了一个 Stripe 的 Webhook 处理程序,逻辑是:先给 Stripe 返回 200 OK 确认收到,然后再把数据写入数据库。
async function handleStripeWebhook(event) {
// 1. 先确认收到,防止 Stripe 重试
await respond200ToStripe();
try {
// 2. 异步写入数据库
await db.orders.create({ data: event.data });
} catch (e) {
console.error("Write failed", e);
}
}
在所有测试用例里,这代码完美运行。我把这段代码喂给那个「怀疑论者」AI,问它能不能找到让客户丢钱的输入,结果它自信地给出了 Approve,还夸我代码写得简洁。
但实际生产环境下,只要数据库在 respond200 和 write 之间闪断一次,结果就是:Stripe 认为通知已送达,但我的数据库里没记录,用户付了钱却拿不到权限。这种涉及「外部系统状态」和「分布式一致性」的逻辑 Bug,AI 现在的推演能力还不足以在没有具体报错的情况下预判出来。
实操建议
如果你想在项目里尝试这种双 AI 互审,建议这么搞:
1. 不要用同一个模型: 建议作者用 Claude 3.5 Sonnet,怀疑论者用 GPT-4o,或者反过来。同模型容易产生相同的逻辑盲区。
2. 强制对抗: 给 Reviewer 的 Prompt 里必须包含 Assume this is broken(假设这是坏的)。
3. 成本预估: 这套方案会增加一倍的 Token 消耗。如果一个 Feature 迭代 10 次,你得为每次提交支付双倍的推理费用,虽然单次便宜,但累积起来在大型项目里是个数字。
总之,AI 互审可以替代那个「疲惫的 6 点钟人类 Reviewer」来处理重复代码和基础 Bug,但涉及到资金、权限、数据一致性这种关键路径,你还是得自己花 5 分钟盯着看一遍。
太绝了,我上周用 GPT-4o 搞对冲,结果两个 AI 互相吹捧,差点让我把 500 块的预算全给烧在那个内存泄漏上。