AI系统的评测基准(golden dataset)一旦固化就无人维护,导致API响应结构变化、正确答案过期、评分标准老化,绿色仪表盘不再代表系统正确。
我们谈论 Agent 漂移,却几乎从不谈论我们用来衡量它的那个东西也在漂移。但你的 golden dataset——那些你的 evals 所依赖的 fixture、期望输出和"已知正确"轨迹——是一段代码,它被发布到生产环境之后,再也不会有人做 code review。它在腐烂。而当你的 oracle 腐烂了,绿色仪表盘就不再意味着你的 Agent 是正确的。它只意味着你的 Agent 仍然同意一个八个月前拍下的世界快照。
这就是资深团队不断 hard way 重新发现的失败模式:Agent 没问题,harness 没问题,出问题的是那个 test oracle。没人重新校验它,因为测试通过感觉像是故事的结局,而不是一个也会衰减的主张。
Golden dataset 编码了你捕获它那一刻对世界的假设。几个月后:
你调用的 API 改变了响应结构,所以你"期望的输出"现在描述的是一个已经不存在的端点。
正确答案变了。"现任 CEO""最新稳定版本""推荐的 flag"——这些都有内置的过期日期。
人类在已被更新的策略下标注了 golden answer,所以你的 eval 现在在强制执行上个季度的规则。
期望的字符串本身是由模型生成的,而你从未检查它是否真的正确。你把一个看似合理的猜测冻结了,然后称它为真理。
这些都不会触发任何警报。你的 suite 全程绿灯,因为绿色意味着"匹配 fixture",而不是"匹配现实"。
在这里,停止按成本(贵还是便宜)对证据排序,开始按独立性排序会很有帮助——信号有多容易被伪造,以及推而广之地,它能多好地经得起时间考验。agent-eval 正是沿着这条轴把证据分成三个层级:
Tier 1 —— Agent 无法伪造的外部可观测证明。有效的 JSON、文件存在、URL 可解析、它编译了、测试通过了、它在超时内完成了、输出非空。
Tier 2 —— 统计信号,基于 Agent 没有参与创作的基线。任务相关的嵌入相似度、长度和重复检查、diff 是否真的改变了任何内容。
Tier 3 —— model-as-judge。共享底 substrate 的观点。一种信号,而不是裁决。
现在用这个 lens 重新审视腐烂清单。Tier 1 检查几乎不会腐烂:"这是有效 JSON 吗"和"这个文件存在吗"在今天和去年含义相同。Tier 1 的 oracle 是世界,而世界在每次运行中都会 self-validate。Tier 2 腐烂得缓慢且可观测:你的基线嵌入会随着任务定义变化而变化,这是一个你可以观察到的信号。腐烂最快最静默的是 Tier 3 和 hand-frozen golden strings——因为它们的 oracle 是观点或快照,而观点和快照不会 self-refresh。
这就是很多团队学得很晚的 structural rules 的论证:
Tier 1 + Tier 2 是你的实时 gate —— 确定性的、大致免费的、足够快的,可以 block hot path 中的运行。Tier 3 是离线-only —— 按量计费的、慢的、不确定的,所以它不能坐在 live request 的延迟预算里。
Tier 1 + Tier 2 可以跨越 Agent 的完整轨迹运行。Tier 3 不可以。 一个模型评判另一个模型的推理是循环的——judge 和被评判者共享一个 substrate,所以循环中没有独立的 ground truth。Tier 3 只被允许检查被评判 Agent 没有机会写入的 artifact,仅此而已。
当一个 frozen Tier 3 观点被允许伪装成 Tier 1 事实时,golden dataset 的腐烂就发生了。
大多数真实失败——过时的输出、崩溃、格式错误的响应、幻觉出来的文件路径、空答案——仅凭 Tier 1 + Tier 2 就能 catch,那些检查 aging gracefully。把 judge 留给约 20% 的主观 tail,并将其输出标记为"opinion, not evidence"。这个框架也告诉你把 re-validation 预算指向哪里:不是整个 suite,而是那些 correctness 是观点或快照的 fixture。这些才是有过期日期的东西。
这里是 cheap 版本:给每个 golden fixture 一个 freshness contract,让 Tier 1 检查在每次运行时 re-prove 世界面向的那些。
type Tier = 1 | 2 | 3;
interface GoldenFixture {
id: string;
expected: unknown;
oracleTier: Tier; // how the "truth" was established
capturedAt: string; // ISO timestamp
maxAgeDays: number; // expiration for snapshot/opinion oracles
reverify?: () => Promise<boolean>; // Tier 1 re-proof against the world
}
async function checkOracleHealth(f: GoldenFixture): Promise<string[]> {
const problems: string[] = [];
// Tier 1 fixtures can re-prove themselves: does the URL/file still resolve?
if (f.reverify && !(await f.reverify())) {
problems.push(`${f.id}: world-facing oracle no longer holds`);
}
// Snapshot/opinion oracles (frozen strings, judge labels) expire.
if (f.oracleTier >= 2) {
const ageDays = (Date.now() - Date.parse(f.capturedAt)) / 86_400_000;
if (ageDays > f.maxAgeDays) {
problems.push(
`${f.id}: oracle is ${Math.round(ageDays)}d old (max ${f.maxAgeDays}), re-validate before trusting`,
);
}
}
return problems;
}
把它作为一个 meta-eval 运行——对你的 evals 做 eval。当它变红时,你不碰 Agent。你去 re-validate oracle。重点不是具体的阈值;而是让"这个期望值有过期日期"成为一个 first-class property,而不是一种 tribal assumption。
这里是团队忽略的部分:要 re-validate 一个 fixture,你需要知道 Agent 实际上是如何产生你正在评分的输出的,而不仅仅是最终字符串。那就是 eval half 和 trace half 交汇的地方。agent-eval 给输出评分和 gating——上述的 tiers、drift、hallucination 检查。AgentLens 捕获 Agent 如何到达那里 的轨迹:每个 model call 和 tool step、resolved inputs、raw outputs。一个 workflow 的两个 half。
trace 是使 Tier 1 + Tier 2 成为可能的前提——那些层级需要 Agent 没有机会 authored 的轨迹数据,而 AgentLens 就在那里存储那份不可伪造的记录。这也是使 rot 可诊断的原因:当你的 meta-eval 标记了一个过时的 fixture,trace 告诉你期望值是一个真实的 observation 还是模型的 frozen guess,以及它 pinned 到了哪个 tool response。没有 trace,你就在 re-guessing the oracle。有了它,你就在 auditing it。
An eval is a claim about the world, and claims expire. Rank your evidence by independence, not price: Tier 1 and Tier 2 hold up because their oracle is reality; Tier 3 and frozen golden strings are opinions with a shelf life. Gate on the durable tiers in real time, keep the judge offline and clearly labeled as opinion, and run a meta-eval that treats oracle freshness as a real signal. Pair agent-eval for the scoring with AgentLens for the trace, and a red fixture stops being a mystery. Because the most dangerous eval isn't the one that fails. It's the one that passes against a world that no longer exists.