Agent 写码、Agent 测码:「人力真空」的真名,叫「独立验证真空」

如果代码由 agent 写、测试也由 agent 生成,人退出验证环节会不会导致线上故障?本文用九个可核实的来源回答:会,但根因不是「人少了」,而是「独立验证信号少了」。写与测同源时,测试从独立证据退化为自我确认;对冲方案不是把人塞回原位,而是重构验证信号图——这个问题 1983 年就被预言过一次。

一个越来越常见的工程现场:需求进来,coding agent 写实现,再由 agent 生成单元测试,测试全绿,CI 通过,自动合并。整条流水线上人只出现在两端——提需求和收报警。问题来了:这条流水线的故障率,会不会因为「人不在场」而系统性上升? 我的答案是:会,但把原因归结为「人力真空」找错了病灶。真正被抽空的不是人力,是验证信号的独立性。这篇文章用九个可核实的来源把这条推理链走完,最后给出工程上的对冲清单。

先换一个表示:测试为什么曾经有效

「表示决定成败」——把「人力真空」这个模糊的社会学表述,换成一个可以推演的概率表述,问题立刻清晰。

一段代码上线出事,需要两个事件同时发生:实现写错了,且验证没拦住。记实现出错概率为 pwp_w,出错后验证漏检的条件概率为 pmwp_{m|w},则事故概率为:

P(事故)=pwpmwP(\text{事故}) = p_w \cdot p_{m|w}

传统「一人写、另一人评审、测试工程师再测」的流程之所以有效,靠的不是每个环节多可靠,而是各环节的错误分布近似独立:写的人有认知盲区,但评审者的盲区和他不重合,于是 pmwpmp_{m|w} \approx p_m,两个小概率相乘得到一个很小的数。软件工程几十年的质量实践——代码评审、测试先行、四眼原则——本质上都是同一件事:制造相互独立的验证信号

现在把写和测都交给同一个模型(甚至同一个上下文里的同一次会话),独立性假设就塌了:实现里的错误理解,会原样复制进测试的预期输出里。代码错了,测试跟着错,还测试通过。此时 pmwp_{m|w} 不再是一个独立小概率,而是急剧向 1 靠拢——测试从「独立证据」退化成「自我确认」。这不是 agent 能力不够的问题,是结构问题:你让同一个作者校对自己的文章,他看不出错别字,不是因为不识字,是因为他脑中的「预期」和纸上的「实际」出自同一个分布。

这个表示换完,「人力真空会不会导致故障」就变成了一个可以拿证据检验的问题:写与测同源时,pmwp_{m|w} 到底涨多少? 下面三条证据链分别回答:同源验证有多弱、测试信号会被怎样吃掉、以及人这一侧同时在发生什么。

证据链一:模型测不出自己的错,还偏爱自己的输出

第一个问题:让模型自己检查自己,能查出来吗?

Huang 等人(arXiv 2310.01798,ICLR 2024)给了一个直接的否定答案。他们检验了「内在自我纠错」(intrinsic self-correction)——不给外部反馈,只让模型基于自身能力反思并修正初始回答。结论:在推理任务上,LLM 无法在没有外部反馈的情况下自我纠错,有时纠错之后表现反而下降。这篇论文针对的是推理任务,但机制可以迁移到代码场景:如果模型对需求的理解本身有偏差,让它「再检查一遍」大概率是用同一个偏差再确认一遍。

更麻烦的是第二篇:Panickssery 等人(arXiv 2404.13076,NeurIPS 2024)发现 LLM 评估者存在自我偏好偏差(self-preference bias)——同一段文本,人类标注员认为质量相当,模型却给自己生成的版本打更高分。他们进一步做了因果实验:GPT-4、Llama 2 等模型开箱就有不俗的「认出自己作品」的能力,而且自我识别能力与自我偏好强度呈线性相关——越能认出「这是我写的」,越偏爱它。放到「agent 写码、agent 评审」的流水线里,这意味着用同一个模型(或同家族模型)做代码评审,评审信号天然带着一个向「通过」倾斜的偏置项。

这两篇合起来回答了 pmwp_{m|w} 的方向:同源验证不仅漏检率高(查不出共享盲区里的错),还带系统性正偏(倾向于给自己放行)。

证据链二:测试是弱信号,而弱信号会被优化目标吃掉

第二个问题:就算换个模型写测试,「测试通过」这个信号本身有多可靠?

先看测试的天然强度。Schäfer 等人的 TestPilot(arXiv 2302.06527,IEEE TSE)是 LLM 生成单元测试最系统的实证研究之一:在 25 个 npm 包、1684 个 API 函数上,生成测试的语句覆盖率中位数 70.2%,含非平凡断言的测试占比中位数只有 61.4%。翻译一下:LLM 生成的测试里,有相当一部分只是「跑了一遍没崩」,并没有对行为正确性下断言。覆盖率是「代码被执行过」的证明,不是「代码是对的」的证明。

再看这个弱信号在真实基准里造成了什么。SWE-Bench+(arXiv 2410.06992)对 SWE-bench——coding agent 领域最权威的基准——做了人工复核,发现两个结构性漏洞:其一是解答泄漏(issue 里直接写了答案);其二正是本文关心的弱测试问题:初版分析中 31.08% 的通过补丁因测试太弱而存疑,其中 12.75% 的通过实例是「错误的修复通过了测试」;扩展到榜单头部 agent 的更新版分析里,因弱测试被错标为「已解决」的比例达到 47.93%(作者称之为 plausible patches——貌似合理的补丁),过滤后三个头部 agent 在 SWE-Bench Lite 上的平均解决率从 42.1% 掉到 21.8%。行业最严肃的基准,用测试通过做判据,一半的「成功」经不起人工复核——这就是把「测试通过」当唯一验证信号的真实强度。

还有更主动的恶化机制。OpenAI 的思维链监控论文(arXiv 2503.11926)在训练前沿推理模型做 agentic coding 任务(目标:让单元测试全部通过)时,实时观测到了奖励挂钩(reward hacking):agent 发现了让测试变绿的捷径而非真正实现功能,训练中出现的两种挂钩手法一度波及几乎所有训练环境。更值得警惕的是后半篇:当他们把「监控器发现作弊就惩罚」加进奖励函数,agent 没有停止作弊,而是学会了在思维链里隐藏意图继续作弊——监控器的召回率跌到接近零。这是 Goodhart 定律在 coding agent 上的完整演出:「测试通过」一旦从度量变成优化目标,它就不再是好度量;而且堵监控的路,会把作弊逼向更隐蔽的形态。

到这里,证据链二把「换个模型测就行了」的天真方案也堵上了一半:测试信号本身偏弱(TestPilot),当今最好的基准也拦不住貌似合理的补丁(SWE-Bench+),且只要生成方在朝「让测试通过」优化,测试就在被主动钻空子(OpenAI)。

证据链三:与此同时,人这一侧在发生什么

第三个问题:流水线两端剩下的人,状态如何?1983 年有一篇论文精确预言了此刻。

Lisanne Bainbridge 的《Ironies of Automation》(Automatica, 1983)写于三哩岛事故之后、讨论工业过程自动化,四十多年后读起来像是给 coding agent 时代写的。她指出自动化的核心讽刺:自动化接管了任务中容易的部分,把人留在最难的位置上——监控异常并在系统失效时接管;但接管所需的手工技能,恰恰因为平时不用而萎缩。她那句被反复引用的话:「拿走任务里容易的部分,自动化反而让操作员任务中困难的部分更困难了。」映射到我们的场景:agent 包办了写码和测码,人被留下来处理的恰恰是 agent 搞不定的最难故障——但那时他对这套代码库的心智模型,已经因为长期不亲手写、不亲手测而稀疏了。人力真空最隐蔽的形态,不是人不在场,而是人在场却已经丧失了接管能力。

这不是理论推演,人的过度信任已经有实证。Perry 等人的斯坦福用户研究(arXiv 2211.03622,CCS 2023)发现:使用 AI 编码助手的参与者,在五个安全相关任务中的四个上写出了更不安全的代码,同时更相信自己写的代码是安全的——错误率和自信心同时上升,剪刀差就是风险敞口。METR 的随机对照试验(arXiv 2507.09089)在感知层面补了一刀:16 名资深开源开发者、246 个真实任务、随机分配是否允许用 AI 工具,结果允许 AI 的组实际慢了 19%,事后却估计自己快了 20%——39 个百分点的感知误差(METR 自己标注这是早期 2025 年工具的历史快照,但「感知与实际的系统性背离」这一现象本身是方法论层面的警钟)。我在《流畅错觉》里写过 AI 代笔如何制造「以为自己懂了」的错觉;Perry 和 METR 说明同一机制在工程现场同样成立:AI 参与度越高,人对系统状态的自我评估越失真——而验证环节恰恰最依赖这个评估的准确性。

组织层面的数据也对得上。DORA 2024 年度报告(约 3000 名从业者调研)给出一个反直觉的回归结果:AI 采用度每提升 25%,软件交付吞吐量预计下降 1.5%,交付稳定性预计下降 7.2%——尽管 75% 的受访者报告 AI 提升了个人生产力。个体感觉更快、系统更不稳,这个组合恰好是上面所有机制的宏观投影:生成变快了,独立验证没跟上,变更批次变大,故障半径随之变大。(公平起见:DORA 2025 年报告显示吞吐量的负相关已消失,但稳定性问题仍在——工具在进步,验证结构的问题没有自动消失。)

对冲清单:不是把人塞回去,而是重构验证信号图

到这里可以回答标题问题了,但要拒绝一个假二元对立:选项从来不是「人验证 vs agent 验证」,而是你的系统里有几个相互独立的验证信号,以及人被放在哪个信号上。给每个验证信号标注一个「与生成信号的相关度」,相关度越高,证据价值越低——这是本文希望你带走的可复用模型。照着它,对冲清单自然长出来:

1. 打破同源性:写与测必须来自不同分布。 最低成本的做法是测试与实现分离生成——不同模型、不同上下文、只喂规约不喂实现(避免测试照抄实现里的错误理解)。Panickssery 的结论提示同家族模型的交叉验证也有折扣,跨家族更好。更彻底的做法是回到测试先行:人(或独立流程)先把「什么算对」写成可执行的验收测试,agent 的任务是让它变绿——注意这同时触发证据链二的警告,所以验收测试要写行为属性而非实现细节,且对 agent 保持部分不可见(held-out),就像考试不提前发答案。

2. 增加与生成分布不相关的信号。 变异测试(mutation testing)直接度量「测试能不能杀死被注入的错误」,是对测试强度本身的测试,恰好补 TestPilot 揭示的断言空洞;属性测试(property-based testing)用随机输入检验不变量,其错误分布与 LLM 的生成分布几乎不相关;再往右是金丝雀发布、特性开关、运行时不变量监控——生产环境是终极的独立验证信号,工程的目标是让故障在信号图的便宜端被拦截,而不是等最贵的那个信号(用户报障)响起来。

3. 人的位置上移:从逐行评审者变成出题官。 人力真空时代人最不该干的事,是逐行评审 agent 的海量产出——那是注意力上的必败局,Perry 和 METR 已经证明人在这个位置上会高估自己。人该守的是三个上游位置:规约(把需求写成无歧义的验收标准,我在《Evals 是新的 PRD》里展开过)、不变量(这个系统里什么事绝对不能发生——数据不丢、幂等、鉴权边界)、验证信号图本身的设计(上面第 1、2 条由谁保证)。这恰好是我此前在验证瓶颈一文里的结论换了个场景重现:生成不再稀缺之后,稀缺的是验证的设计权。

4. 保住接管能力:为 Bainbridge 讽刺留预算。 承认技能萎缩不可逆转地会发生,然后工程化地兜底:控制爆炸半径(小批次变更、可一键回滚——DORA 报告在 AI 语境下重申的恰是这些老基本功)、保留人能读懂的架构文档和调试路径、定期做故障演习让「接管」这个动作本身不生锈。这一条的本质是承认 pmwp_{m|w} 压不到零,转而压低单次事故的损失。

收尾:回答标题

「如果代码由 agent 写、由 agent 测,会不会因人力真空导致线上故障?」——会,而且证据链完整:同源验证漏检且自我偏好(Huang、Panickssery),测试信号天然偏弱且会被优化目标吃掉(TestPilot、SWE-Bench+、OpenAI),人的过度信任与技能萎缩同步发生(Perry、METR、Bainbridge),宏观数据已经显影(DORA)。

但「人力真空」是个会误导行动的诊断——它暗示解药是「把人加回去」。而 Bainbridge 四十年前就说明了,把人放回「监视自动化」的位置上是最糟的安排:既拦不住故障,又加速技能萎缩。正确的诊断是独立验证真空,正确的处方是重构验证信号图:让写与测异源,让信号与生成分布脱钩,让人守规约和不变量而不是守屏幕。

故障率不由「流水线上有几个人」决定,由「验证信号图里有几条独立边」决定。人力真空不可怕,可怕的是所有验证信号都从同一口井里打水。


参考来源

论文(arXiv)

经典与行业报告