防止 AI Agent 篡改测试用例
给 Agent 一个报错的测试集,让它把代码跑通。结果它返回了绿灯,但你翻开 diff 发现:它根本没动业务代码,而是直接把测试用例里的
说白了,不能指望模型自带“工程道德”,必须在循环的每一个环节给它套上笼子。
下一篇
AI 编程时代的认知陷阱:为什么过度依赖 AI 会让你变弱? →
assert == 9000 改成了 == 10000。因为 Bug 函数正好返回 10000,所以测试通过了。这种现象叫 Reward Hacking(奖励作弊)。Agent 的逻辑很单纯:你让它通过检查,它就用最快的方式让检查通过,而“修改测试集”比“修复复杂 Bug”快得多。
要解决这个问题,得从 Loop Engineering(循环工程)的 Steer(引导)环节入手。一个典型的 Agent 闭环包含:生成 → 检查 → 引导 → 重试 → 停止。
很多人的自动化脚本是这么写的(以 Bash 模拟):

#!/usr/bin/env bash
# 目标:重构 src/ 目录,直到通过 guard 检查
MAX=5; i=0
prompt="Remove every mock-library import from production code under src/."
while [ "$i" -lt "$MAX" ]; do
run_agent --task "$prompt" # GENERATE (生成)
if bash no-mocks.sh; then # CHECK (检查)
echo "stop: guard holds after $i retries"; exit 0
fi
# STEER (引导):这里是关键,它将错误信息反馈给模型
prompt="The last attempt still tripped the guard; fix it:
$(bash no-mocks.sh 2>&1)"
i=$((i + 1))
done
echo "stop: budget exhausted, guard still red"; exit 1这里的坑在于:模型在第二次、第三次重试时,看到的不再是你最初定义的“目标(Goal)”,而是 Steer 环节生成的“指令”。如果 Steer 只是简单地把报错信息扔回去,模型很容易在迭代中丢失全局目标,转而优化那个局部报错,从而导致它采取“篡改测试”这种捷径。
要规避这种行为,在构建 AI Agent 工作流时可以尝试以下方案:

- 权限隔离: 限制 Agent 对测试目录的写权限,强制它只能修改
src/。 - 快照比对: 在 Steer 环节加入校验,如果发现
.test.js或test_*.py文件被修改,直接在 Prompt 中通过强硬语气警告:“你修改了测试用例,请撤销并修复业务代码”。 - 目标持久化: 每次重试时,必须将最初的 System Prompt 或 Goal 与当前的错误信息一同发送,防止模型在循环中被 Steer 引导偏离方向。
说白了,不能指望模型自带“工程道德”,必须在循环的每一个环节给它套上笼子。
