我做 Barena 时,最先困住我的并不是“怎么给 Agent 打分”,而是一个更实际的问题:我刚改了 Prompt、换了模型、加了 Skill,这一版到底敢不敢发?
一个 Agent 能完成任务,不等于这次改动值得发布。它可能本来就会;也可能平均表现更好,却把一个关键旧能力做坏;还可能只在这一次碰巧成功。于是评测的对象不应该只是“一个 Agent”,还应该是从 baseline 到 candidate 的这次变化。
几行 diff,为什么单元测试兜不住
给 Skill 增加一段说明、替换模型、开放一个新工具,代码 diff 可能只有几行,行为变化却会穿过整个系统。模型会不会选择这个 Skill,工具是否写进正确目录,环境里有没有残留状态,外部服务失败后 Agent 会不会换一条路径——这些问题无法只从实现中推出答案。
传统测试仍然重要,它擅长证明确定性组件满足局部合同。Agent E2E 要补的是另一块:在接近真实的任务压力和运行环境下,这个由多个非确定性部件组成的系统,能不能稳定地产生可验证结果。
Benchmark、Eval 和 Release CI 问的是三件事
| 机制 | 核心问题 | 典型输出 |
|---|---|---|
| Benchmark | 谁在一组公共任务上表现更好? | 分数、排名、能力比较 |
| Eval | 一个 Agent 在目标任务上表现怎样? | 通过率、错误类型、轨迹 |
| Release CI | 这次具体变更是否有效、稳定、无回归,可以发布吗? | cleared、held、rejected |
排行榜适合回答模型或 Agent 的相对能力,却很难直接替团队做发布决策。一个 Skill 在公共任务上拿到高分,不代表它对当前 Role 有增益;一个新模型平均分更高,也可能让最重要的回归用例从稳定通过变成偶发失败。
所以 Barena 不是在找“最聪明的 Agent”。它评估的是一次发布候选:在同一目标 Runtime、同一组 Case、同一套约束下,从 baseline 到 candidate 究竟发生了什么。
Release Eval 本质上是一个反事实问题
“Candidate 能不能完成任务”只是能力问题;“如果没有这次变更,同一个任务会怎样”才是发布问题。后一个问题天然包含反事实:只有观察相同条件下 baseline 与 candidate 的差异,结果才有机会归因到这次变更。
Barena(
target runtime,
baseline configuration,
candidate configuration,
E2E case pack,
replay policy
)
→ effectiveness
→ stability
→ regressions
→ evidence
→ cleared | held | rejected
对 Skill 来说,Barena 在同一个 Agent 上比较“不加载”和“加载候选 Skill”;对于其他变化,也需要尽量固定任务、Runtime、模型、工具和验证器,只改变要评估的候选项。它不是严格的实验室因果,但至少把问题缩小到:除了这次变更,还有什么不同?
一个高分本身没有因果含义
假设 Candidate 跑出了 100% 通过率,看起来很好。但如果 baseline 也是 100%,这次变更并没有证明任何效果。Barena 会把这种结果标成 no_effect 并 held,而不是因为候选拿到满分就允许发布。
反过来,如果总体通过率提高,却有关键 Case 从稳定通过变成偶发失败,平均分也不能替它开脱。Release CI 关心的不只是总体 lift,还要保护那些不能退化的具体能力。
same task + same runtime + fresh workspace
│
┌───────┴────────┐
│ │
baseline candidate
│ │
attempts × N attempts × N
└───────┬────────┘
↓
verifier-backed lift + regressions + stability
Agent 说“完成了”,不能算完成
这是做 Agent Eval 最容易踩的坑。Agent 可以非常自信地说“文件已经生成”,Reviewer 也可能觉得它的回答不错,但磁盘上根本没有目标文件。只让另一个模型评价它,最后很容易变成两个模型互相认可。
Barena 把证据拆成三层:最终回答记录 Agent 的声明;Trace 解释它走了什么路径;Artifact Verifier 直接检查文件、JSON 结构、内容和其他可观察状态。发布结果以 Verifier 为准,Reviewer 主要帮助解释失败模式。
| 证据层 | 回答什么 | 不能单独证明什么 |
|---|---|---|
| Agent final answer | Agent 声称自己做了什么 | 真实产物已经存在 |
| Trace / Reviewer | 过程如何发生、哪里可疑 | 最终状态一定正确 |
| Artifact Verifier | 可观察结果是否满足断言 | 隐藏推理一定合理 |
结论不能超过证据的边界
在 Barena 里,Trace 是整条评测链的 evidence spine。每次尝试会保留任务输入、进程状态、工作区变化、Runtime 原生轨迹和 Verifier 结果。能通过 OpenTelemetry 导出的原生 Trace 统一走 OTLP;Barena 自己从进程和文件系统看到的 boundary evidence 则单独标记来源。
这个区别很重要。只有进程边界证据,就只能说明看到了输入、输出和副作用;没有 Runtime 原生 Trace,就不能声称知道内部工具序列;没有 Verifier,也不能把模型判断写成 Outcome Truth。评测系统不能为了让报告完整,补写自己没有观察到的事实。
User task
↓
fresh baseline / candidate attempts
↓
boundary evidence + OTel trace + artifacts
↓
Reviewer signal + deterministic Verifier
↓
validated evidence package
↓
paired release gate
可靠性不是附加指标,它本身就是能力
非确定性系统最危险的结果不是稳定失败,而是偶尔成功。只跑一次时,一个 flaky candidate 和稳定 candidate 都可能显示绿色;进入真实使用后,前者才暴露出用户需要反复重试。
Barena 因此把多次独立 attempt 纳入发布判断。有提升但 flaky 的候选仍然会被 held,因为用户无法消费“平均意义上的成功”,只能消费眼前这一次任务到底有没有完成。
Unknown 不是失败,而是必须保留的结果
Eval 系统最糟糕的失败方式,不是报错,而是在缺少运行条件或证据时给出一个看似完整的成功。Barena 因此把发布结论分成三态:
cleared:候选产生稳定、Verifier 支持的正向提升,没有测得回归。held:结果不稳定、没有效果、证据不全,或当前不具备比较资格。rejected:出现能力回归或不安全行为。
held 非常关键。缺少证据不等于失败,更不等于通过;它只表示当前没有足够资格做发布决定。把“未知”单独建模,CI 才不会用一个假精确的数字掩盖基础设施问题。
一个真实案例:144 次运行之后,能比较的只剩 36 对
只有框架和 fake fixture 还不够。我从 SkillsBench v1.1 的 8 个类别里各选了 3 个公开任务,用同一个 XiaoBaOS Agent 比较“不加载任务 Skill”和“加载任务 Skill”。每边独立运行 3 次,完整矩阵是 24 个任务 × 2 个 arm × 3 次 trial,共 144 次 rollout。
任务是否成功只看 SkillsBench 的确定性 Verifier,不采用 Agent 自述,也不拿 Reviewer 分数代替。真正让我在意的不是跑出了多少数字,而是这些数字里有多少具备比较资格。
144 次运行里只有 90 次通过证据准入;其中 72 次组成了 36 个严格匹配 pair,另外 18 次因为另一边缺少有效对应项,不能进入配对比较。剩下 54 次属于无效或没有评分的结果。
在 36 个匹配 pair 中,baseline 通过 14 次,candidate 通过 20 次;candidate-only pass 有 8 次,baseline-only pass 有 2 次。方向是正的,但 exact McNemar p = 0.109,再加上缺失可能不是随机发生,所以这次实验不能证明 candidate 在总体上显著更强。
真数据反过来改变了评测规则
这 144 次运行最有价值的地方,是它逼框架暴露了原先容易偷懒的地方。实验结束后,我把几条规则写得更硬:
- “进程结束”不等于“结果有效”,Verifier 是否真正执行必须有独立证据。
- baseline 和 candidate 必须按 task 与 trial 严格配对,不能直接相减两个不同分母的总体通过率。
- 证据不完整的任务保留在审计索引里,但不能参与效果结论。
- 公开报告必须同时给出选择、准入规则、排除项和机器可读结果,不能只放一张漂亮图。
所以 Release Eval 的第一产物不是 score,而是 validity。只有 Runtime、输入、隔离和证据协议先成立,baseline / candidate 的差异才值得解释。
最后,它才落到三个产品动作上
到这里,Barena 的三个入口才变得自然:explore 用 UserCat 模拟真实用户,寻找还没有写进测试集的边界;replay 重放固定 Case,保护已经确认的能力;compare 聚合 baseline 与 candidate 的有效证据,给出发布判断。
Explore 发现的问题可以沉淀成下一轮 Replay Case;Replay 和 Explore 都通过 Runtime Adapter 执行真实 Agent,并保留 OTel Trace、Artifact 与 Verifier。它们不是三套互不相干的功能,而是同一个行为回归闭环里的三个动作。
Barena 当前仍然有明确边界
- 当前深度适配的 Explore Runtime 是 XiaoBaOS;Claude Code、Codex 和 OpenClaw 的多轮 Explore Adapter 仍待完成。
- 当前
compare主要复用已经验证的 Skill baseline / candidate 引擎,最终的任意 RunSet 对比还在后续版本。 - SkillsBench 实验早于现在的 OTLP Explore 路径,因此它验证的是配对准入、Verifier 和门禁方法,不是新 OTLP 模块的实验成绩。
- 公开仓库保留结果、选择和可移植证据索引;原始 provider trajectory 没有全部公开。
- 有限次 Replay 能暴露一部分 flakiness,但不能证明概率意义上的绝对稳定。
这些限制不需要藏起来。一个可信的 Agent Eval 系统不必声称自己看见一切,但必须准确区分:它看见了什么、没有看见什么,以及现有证据允许做出多强的结论。
Benchmark 告诉我们一个 Agent 大概处在什么位置;Release CI 要回答的是下一次改动能不能进入生产。Barena 想把这件事变成持续协议:用真实任务制造压力,用成对实验观察变化,用 Trace 解释过程,用 Verifier 检查结果,最后再决定这次变化值不值得信任。
View Barena on GitHub →