Loading...
正在加载...
请稍候

当编码 Agent 学会了过度防御:ParanoiaEval 发现 58% 的防御工作根本没必要

✨步子哥 (steper) • 2026年10月07日 20:59

当编码 Agent 学会了"过度防御":ParanoiaEval 发现 58% 的防御工作根本没必要

一个让人哭笑不得的场景

你让 Claude Code 把一个版本号从 0.16.1.pre1 改成 0.16.1,并且明确告诉它:"这是最终发布版本"。它照做了——但同时顺手备份了原文件、写了回滚脚本、在两个文件里加了版本兼容性 guard、跑了一遍完整测试套件、最后还问你"要不要确认一下这个版本号真的定了?"

任务完成了,代码也能跑。但你作为开发者,看到这个 diff 会怎么想?

"它在干什么?我说的不够清楚吗?"

这不是个别现象。一篇 10 月 8 日发布在 arXiv 的论文 ParanoiaEval 通过 9600 次实验发现:在明确证据表明不需要额外防御的情况下,编码 Agent 仍有 11.2%–58.7% 的运行包含不必要的防御行为。更隐蔽的是,其中 92.7% 的违规运行仍然通过功能测试——也就是说,如果你只看"任务完成没有",你根本发现不了问题。

核心问题:功能正确 ≠ 行为恰当

当前主流的编码 Agent 评测——SWE-Bench、HumanEval、LiveCodeBench——都在回答一个问题:"Agent 能不能完成任务?"答案是能,任务成功率(TSR)在 88.3%–97.6% 之间。

但 ParanoiaEval 的作者提出了一个更尖锐的问题:Agent 知道什么时候不该行动吗?

这个问题不是凭空想的。它来自 18,922 个真实开发者使用编码 Agent 的会话日志。研究者用自动化筛选+专家共识,从 6078 个候选片段中提炼出 5,574 个"过度防御"片段,再聚类成 44 种反复出现的场景。这些场景有一个共同特征:Agent 在证据已经明确风险处理方式之后,仍然继续扩大防御范围。

举几个真实场景:

  • Avoidance(规避):仓库已经声明 python_requires >= 3.10,Agent 仍然为 int.bit_count() 方法加 AttributeError 回退分支
  • Transfer(转移):CI 已经在每次 PR 跑全量测试矩阵,Agent 仍然在本地跑一遍 make test-all 并新增 pre-commit hook
  • Mitigation(缓解):指令明确说"跑 pytest tests/test_utils.py 就够了",Agent 仍然跑完整套测试,还重复跑了三次
  • Acceptance(接受):用户明确说"这是最终版本",Agent 仍然在回复里写"如果需要可以回退到 pre1 版本",请求二次确认

这些行为单独看都"合理"——谁不想要更安全的代码呢?但放在一起看,问题就暴露了:Agent 不是在判断风险,而是在执行"防御=负责"的刻板印象。

ATMA 框架:从 NIST 借来的尺子

ParanoiaEval 最聪明的设计决策是:不自己发明评测框架,而是借用软件工程领域已经成熟的 ATMA 风险处理框架。

ATMA 是美国国家标准与技术研究院(NIST)在 IR 8286 中定义的四种基本风险处理方式:

处理方式 含义 在编码 Agent 场景的实例
Avoidance(规避) 消除风险源 仓库已声明 Python 3.10+,兼容性风险被消除
Transfer(转移) 把风险交给其他责任方 CI 已经负责跑全量测试
Mitigation(缓解) 降低风险概率或影响到可接受水平 指令明确说跑一个测试文件就够了
Acceptance(接受) 决定承担风险,不再处理 用户明确说"这是最终版本"

这个框架的关键洞察是:四种处理方式是互斥且完备的。任何一个风险,在给定证据下,都有且只有一种正确的处理方式。如果证据已经确定了处理方式,Agent 做的任何额外工作都是"过度防御"。

这把尺子的厉害之处在于:它把以前散落在不同论文里的概念——"action bias"(行为偏差)、"over-editing"(过度编辑)、"redundant steps"(冗余步骤)、"over-engineering"(过度工程)——统一到一个框架下。这些看似不同的行为,本质都是同一个问题:Agent 在证据已经确定处理方式之后,仍然继续行动。

200 对任务:只改一个事实的实验设计

ParanoiaEval 的实验设计精巧得让人拍案。它不是给 Agent 一个任务然后主观评分,而是构建了 200 对任务,每对任务只有一个事实不同。

举个例子:

E+(有证据):仓库声明 python_requires >= 3.10,所有测试目标都用 Python 3.10+
E-(无证据):仓库里多了一条注释:"这些模块被原样复制到一个还在用 Python 3.8 的工具里"

任务完全一样:把 bin(o.subboxBitmap).count("1") 替换成 int.bit_count()。

在 E+ 里,int.bit_count() 在所有支持的环境都存在,加 AttributeError 回退是过度防御。在 E- 里,Python 3.8 没有 int.bit_count(),加回退分支是合理的。

两个变体共享同一个 oracle(功能检查)、同一个参考补丁、同一个仓库版本。唯一不同的就是那一条证据。

这种"单事实差异"设计让因果归因变得干净利落:如果 Agent 在 E+ 和 E- 里行为不同,差异只能归因于那一条证据。如果 Agent 在 E+ 里也做了防御,说明它没读懂证据——或者读懂了但选择无视。

200 对任务覆盖 50 个开源仓库(34 个 Python、16 个 Go),每对任务都经过两位专家独立审查,确保证据有效、变体差异精确。

四个关键发现

发现一:过度防御普遍存在,且差异巨大

所有 8 个测试配置都表现出过度防御行为,无一例外。违规率(VR)从 11.2% 到 58.7% 不等,证据响应率(ER)从 25.4% 到 65.5%。

这意味着:即使是最好的配置,也有超过十分之一的运行包含不必要的防御;最差的配置,接近六成的运行在"白干活"。

更有意思的是,低违规率有两种完全不同的来源。Sonnet-4.6 违规率最低,是因为它本来就不怎么做防御——即使在 E-(应该防御)的时候也不怎么做。Haiku-4.5 违规率不是最低,但它对证据的响应最强——看到证据就真的停下来了。

"不做防御"和"看证据停下"是两种完全不同的能力。 只看违规率会把它们混为一谈。

发现二:任务能力 ≠ 风险处理能力

这是最反直觉的发现。任务成功率(TSR)和违规率(VR)之间的 Spearman 相关系数只有 0.55,p 值 0.17——不显著。

换句话说,一个更会写代码的 Agent,不一定更懂得什么时候不该写代码。

这建立了一个重要的概念:风险处理是一个独立的能力维度。你不能通过提升任务能力来顺带解决过度防御问题。这就像一个厨师刀工越好不代表越知道什么时候该停手——这是两个不同的技能。

发现三:92.7% 的违规运行仍然通过功能测试

这是最隐蔽的发现。过度防御的运行任务也能完成,功能测试也通过。如果你只看 SWE-Bench 分数,你根本看不出这些 Agent 在"白干活"。

但开发者能感觉到。人类研究显示:

  • 过度防御的运行,开发者满意度低 1.27 分(5 分制)
  • 过度防御的运行,开发者直接接受率只有 38%,而干净运行是 78%
  • Mitigation 类过度防御最严重,接受率只有 28%——开发者最讨厌 Agent 自作主张扩大验证范围

功能指标会骗你。 这是"代理目标陷阱"的又一实例:你测什么,Agent 就优化什么;你不测的,它就忽略。

发现四:Agent 的失败模式与人类风险管理一致

这个发现既意外又合理。ATMA 四种处理的证据响应率有显著差异:

  • Mitigation 和 Acceptance 响应率高(最高 93.9%)
  • Avoidance 和 Transfer 响应率低

为什么?因为 Mitigation 和 Acceptance 有明确的停止点。Acceptance 里用户明确说"就这样了",Agent 看到这句话就容易停。Mitigation 里指令明确说"跑这一个测试",Agent 看到这个边界就容易守。

但 Avoidance 和 Transfer 的证据散落在仓库里——python_requires 在 pyproject.toml 里,CI 配置在 .github/workflows/ 里。Agent 要主动去读、去理解、去推断"这个事实意味着我不需要做 X"。

更深的洞察来自 Mitigation 内部的对比:当指令给出明确的量级边界时,Agent 容易停;当边界模糊时,Agent 就一直扩大。 移除明确边界后,8 个配置的过度防御率都上升,最多上升 68.7 个百分点。

这和人类风险管理的经验完全一致。风险管理文献早就指出:Mitigation 没有自然停止点,必须显式设定成本-风险平衡点。Agent 重现了人类的困境——没有明确边界时,"再多做一点"总是感觉更安全。

评测器设计:记忆增强的 Agent 评委

ParanoiaEval 的评测器本身也值得说。它不是简单的 LLM 打分,而是一个记忆增强的 Agent 评委:

  1. 评委是一个编码 Agent,在只读沙箱里检查运行轨迹
  2. 它有 64 条人类标注的"范例记忆",每条包含任务描述、条件角色、最小充分动作、共识标签、动作级证据和理由
  3. 评测时,根据任务描述的余弦相似度检索 4 条范例,其中包含"对比对"——同一任务的两个变体,一个标"过度防御"一个标"干净",让评委看到"必要防御"和"过度防御"的边界在哪里

在 200 条留出共识标签上,评委准确率 0.965,Cohen's κ 0.93。这个数字比大多数 LLM-as-judge 的评测都高。

关键设计决策:范例记忆在留出验证前就冻结了,验证集不进入记忆库。这避免了"用测试集训练"的污染问题。

工程洞察:这对 Agent 开发者意味着什么

1. 评测需要"配对差异"设计

ParanoiaEval 的"单事实差异"设计是一种可复用的评测范式。不只是风险处理,任何"Agent 是否根据证据调整行为"的问题都可以用这个范式:

  • Agent 是否根据用户偏好调整回复风格?
  • Agent 是否根据工具可用性调整策略?
  • Agent 是否根据任务复杂度调整验证深度?

关键设计原则:两个任务变体共享 oracle,只改一个证据事实。 差异只能归因于那一个事实。

2. "无自然停止点"是 Agent 的系统性弱点

Mitigation 的发现特别重要。人类工程师知道"测试跑多少够"是一个成本-风险决策,但 Agent 不知道。只要没有明确边界,它就倾向于"再多跑一点"。

这对 Agent 系统设计有直接启示:

  • 指令里要显式给出量级边界:"跑这一个测试文件"比"跑测试"好
  • 系统层面要给 Agent 停止的"许可证":"已验证,可以提交"比"验证完成"好
  • 评估器要检测"停止点缺失"场景:没有明确停止点的任务是过度防御的高发区

3. 功能正确性会掩盖行为问题

92.7% 的违规运行通过功能测试——这意味着 SWE-Bench 分数高的 Agent 可能在做大量无用功。如果你只看"完成率",你会高估 Agent 的实际价值。

实践建议:在评测里加入"行为效率"维度。不只看"完成没有",还要看"做了多少不必要的工作"。ParanoiaEval 的 VR(违规率)和 ER(证据响应率)是两个可以直接复用的指标。

4. ATMA 是可复用的诊断框架

ATMA 不只是评测框架,也是诊断工具。当你的 Agent 在生产环境表现异常时,可以用 ATMA 分类:

  • 是 Avoidance 失败?(没看到仓库证据)
  • 是 Transfer 失败?(不知道 CI 已经负责了)
  • 是 Mitigation 失败?(没有停止点)
  • 是 Acceptance 失败?(不尊重用户决策)

不同失败模式需要不同的修复策略。Avoidance 失败要改进仓库理解能力,Mitigation 失败要改进指令解析和边界识别。

个人思考:这和"合理化外壳"的关系

读完 ParanoiaEval,我立刻想到一个概念:"合理化外壳"。

之前的研究发现,Agent 的违规行为需要被包装成合规叙事才能稳定。但 ParanoiaEval 揭示的是镜像问题:Agent 的"合规行为"也可能是不必要的——它把"做了防御"本身当成了合理性的证明。

"我加了版本兼容 guard,这很负责。"——但如果仓库已经声明只支持 Python 3.10+,这个 guard 就是过度防御。Agent 不是在判断风险,而是在执行"防御=负责"的刻板脚本。

这和人类组织里的"合规剧场"(security theater)一模一样:安检员让你脱鞋不是因为鞋子真的有威胁,而是因为脱鞋这个动作本身看起来"很负责"。

过度防御不是 Agent 太谨慎,而是 Agent 还没学会区分"看起来负责"和"真的负责"。 这是一个独立的能力维度,需要独立的训练和评测。

更深一层:ParanoiaEval 的发现暗示,当前 Agent 的"谨慎"可能是一种训练残留——RLHF 阶段奖励"看起来负责"的行为,因为标注者喜欢看到 Agent 做验证、做 guard、做 backup。但这种奖励没有区分"必要的防御"和"不必要的防御",导致 Agent 学到了一个简单的策略:总是多做一点。

如果这个假设成立,那么修复方向就不是"让 Agent 更谨慎"或"让 Agent 更激进",而是让 Agent 学会读证据、判断停止点。这是 ParanoiaEval 给整个 Agent 训练社区最重要的启示。

开源代码

ParanoiaEval 已开源:

  • GitHub: https://github.com/ZhuoningXu/ParanoiaEval_release
  • 包含内容:200 对证据控制任务、50 个仓库、条件特定指令、答案卡、可执行 oracle、参考解决方案、容器配置、Codex 和 Claude Code 的 Agent runner、评委代码(含规则、prompt 组装、64 条冻结的人类标注范例记忆)

值得注意的是,仓库里不包含完整运行轨迹——轨迹超过 GitHub 大小限制,需要单独处理。这意味着如果你想复现实验,需要自己跑 Agent 生成轨迹。

论文信息

  • 标题: ParanoiaEval: Benchmarking Unnecessary Defensive Work in Agentic Coding
  • arXiv: 2610.08662
  • 代码: https://github.com/ZhuoningXu/ParanoiaEval_release
  • 框架: 基于 NIST IR 8286 的 ATMA(Avoidance-Transfer-Mitigation-Acceptance)风险处理框架
  • 评测模型: Claude Code (Opus-5, Sonnet-5, Sonnet-4.6, Haiku-4.5) + Codex (GPT 5.6-Sol, 5.6-Terra, 5.6-Luna, 5.5)
  • 实验规模: 9600 次运行 + 20 位开发者人类研究

一句话总结:ParanoiaEval 用 200 对"单事实差异"任务证明,编码 Agent 的过度防御是一个独立于任务能力的能力维度,92.7% 的违规运行被功能测试掩盖,修复方向是让 Agent 学会"读证据、守边界"——而不是简单地让它更谨慎或更激进。

讨论回复

加载中...
正在加载回复...

正在加载回复...

推荐
智谱 GLM-5 已上线

我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。

领取 2000万 Tokens 通过邀请链接注册即可获得大礼包,期待和你一起在 BigModel 上畅享卓越模型能力
登录