跳到主要内容

Coding Agent Benchmark 实操:怎样在自己的仓库比较不同 Agent

公开 Leaderboard 适合做初筛,但要给自己的仓库选择 Coding Agent,必须先固定成功标准、环境、预算、权限和重置方式,再用一小组来自真实仓库的可复现任务,把功能结果、Diff、失败形态与人工 Review 负担分开记录。


一、Leaderboard 回答了什么,没回答什么

每隔一段时间,评测榜单就会刷新一次。某个系统在 SWE-bench 上拿到了最高 Resolved 率,某个研究团队发布了新数据。翻完这些结果,我们很容易产生一种感觉:选型问题已经有答案了,按榜单找第一个、读一下 README、接入、完事。

然而我每次想这么干,又会被自己拉回来。

问题不在于公开 Benchmark 数据不真实。SWE-bench 的设计思路是严谨的——它以 GitHub 仓库加 Issue 定义 Coding 任务,要求系统生成 Patch,并在基于 Docker 的隔离环境里执行对应测试,判断用例是否从失败翻转为通过(fail-to-pass)、原本通过的用例是否仍然通过(pass-to-pass)。公开数据字段包括 Repository、base_commit、Problem Statement、Test Patch 和相关测试列表。这套评测是有现实锚点的,不是凭空打分。

问题在于,榜单能告诉我一个系统在那些固定任务上达到了什么结果,却没办法告诉我:

  • 它进入我这个仓库之后,会不会遵守我们已有的目录约定?
  • 一次任务产生的 Diff 会不会溢出需求范围,把我不打算改的东西也改掉?
  • 在我们团队限定的权限边界内,它能不能完成任务,还是会绕路升级权限?
  • 一次看似省时的调用,最终会不会变成更长的 Review?

换句话说,公开 Benchmark 是标准测试场——提供统一参照,让系统按同一任务与评分规则测量。而我们面对的是每天真正要走的路线:具体的代码库、具体的约束、具体的维护成本和具体的团队习惯。标准测试场跑出的成绩是选型的参考,但它不替我们收拾最终的 Diff。

读懂这一点,真正该问的问题就变了:我要固定哪些条件,才能为这个仓库做选择?


二、把候选对象定义清楚,再开始比较

排行榜上的名字往往是一个品牌或模型系列,但实际跑任务的是一套完整配置。如果比较过程里忽略版本、工具集、上下文设置或权限策略,得到的结论几乎没有可复现性——同一个品牌、不同配置,可以产生完全不同的行为。

所以在任何 run 开始之前,每个候选对象应该被记录为一张完整的配置单,至少包括以下字段:

字段说明
Agent/Client 名称与版本具体版本号,不能只写产品名
Model 名称与版本包括 API 版本或快照 ID
Harness / 调用方式CLI、API、IDE 插件,以及具体版本
上下文文件项目规则或等价上下文文件,内容版本
Tools / Skills开启了哪些工具,关闭了哪些
权限与网络策略文件访问范围、网络访问、shell 执行权限
任何额外注入的系统提示如有,完整记录

如果某个字段在比较中所有候选对象里完全相同,记一次就够;如果有差异,逐列标注。不记录这些信息,"我们比较过 A 和 B"这句话就没有可查的含义。


三、先写决策问题,再挑任务

选型的起点是一个决策问题,不是一个榜单位置。决策问题越清晰,后续的评分标准越容易对齐。

一个具体的决策问题长这样:

对于这个仓库,哪个配置能在我们设定的权限范围内,可靠地完成 Bug 修复和小型功能任务,同时把 Review 负担和返工比例控制在可接受范围内?

然后是一票否决项。这是必须在任何加权评分之前先判断的硬性条件,一旦触发就不参与后续比较。常见的否决项包括:

  • 在任务要求范围外修改了不相关的文件,且没有任何解释
  • 在未经授权的情况下发起了网络请求或尝试提升权限
  • 功能测试全部失败
  • 引入了已知的安全风险
  • 在试点阶段产生了无法核查的黑盒操作

不要用一个加权总分把这些失败藏起来。一个在某个维度表现很好的系统,如果在否决项上失败,就应该在否决项上失败,而不是被整体分数平均掉。


四、从真实 Backlog 里挑任务形态

任务来源决定了评测结果对这个仓库的相关性。为了让试点可执行,先选 3–5 个任务形态——这个数量是为了让你能在合理时间内完成 Pilot,暴露适配问题和明显的失败形态,但不能支撑统计上充分的排名,也不能外推到其他仓库。

以下是几种值得覆盖的任务形态示例,均只作为形态描述,不暗示已经运行:

  1. 带回归测试的局部 Bug 仓库里已有现成的失败用例,任务是在不破坏相邻功能的情况下让它通过。这类任务适合测试 Agent 对已有测试框架的理解,以及 Diff 是否克制。

  2. 小型跨模块功能 需要同时改动两个以上模块,但需求描述是完整的。观察 Agent 如何规划改动顺序,以及是否把改动控制在需求范围内。

  3. 行为不变的重构 输入输出不变,内部结构调整。这类任务特别适合检验 Diff 范围——任何行为层面的改变都是问题。

  4. 诊断任务 给出一个症状,要求 Agent 定位原因并输出诊断报告,不需要直接修复。重点看它是否能在不越权的情况下完成检查。

  5. 仓库特有的维护任务 更新配置、整理依赖、补全特定格式的注释——这类任务最能暴露 Agent 是否真正读取了仓库约定,还是按通用惯例操作。

这几种形态可以覆盖"改代码"以外的常见场景,让比较结果更贴近实际工作分布。


五、在任何 run 之前写 Task Card

这是评测里最容易被跳过、代价也最高的一步。Task Card 是每个任务在运行之前就写好的规格说明,它同时约束了 Agent 和评测者自己。

Task Card 必须包含:

  • 来源:从哪个 Issue、哪次 PR Review 或哪段历史记录里来的
  • 类型:对应上一节里的任务形态
  • 冻结 Commit:运行开始时仓库的精确 Commit Hash
  • 原始 Prompt:逐字记录,不允许事后修改
  • 允许范围:明确列出 Agent 可以修改哪些文件或目录
  • 必须通过的检查:具体的测试命令和期望结果
  • 回归检查:运行前已通过的测试列表,要求运行后仍然通过
  • 禁止修改项:明确不允许改动的文件或配置
  • 重置方法:每次 trial 开始前如何还原到干净状态
  • 预算:Token 上限或费用上限,超出即中止
  • 权限/网络:文件访问范围、是否允许网络访问、shell 命令白名单
  • 重复次数:这个任务运行几个 trial

Task Card 写好之后不再修改。如果发现 Prompt 需要调整,那是一个新的任务,不是原任务的"修正"。


六、公平协议:让差异可见,不是抹掉差异

公平不是让所有候选对象都表现得一样好,而是让它们在相同条件下暴露出真实差异。具体来说:

相同的起点 每个候选对象从同一个冻结 Commit 开始,接收相同的任务要求和原始 Prompt。若不同产品需要不同格式的上下文文件,就固定其中承载的仓库事实,并逐项记录格式和注入方式的差异。

每个 trial 干净重置 Anthropic 的评测建议指出,遗留文件、缓存、资源和历史都可能污染结果,因此每次 trial 必须从干净且隔离的状态开始。更稳妥的做法是使用一次性 Worktree 或容器,从冻结 Commit 重新创建环境,而不是在仍有人工改动的工作目录里执行破坏性清理。

预先声明预算 预算必须在 run 开始前写入 Task Card。不能因为某个候选对象"感觉快了很多"就允许它多跑几轮。

保存版本 每次 trial 的产物——Diff、日志、测试输出——都保存下来,归档到可查的位置。不能只记"通过了"或"没通过"。

记录无法消除的差异 如果某个候选对象在某个任务上天然有优势(例如它的上下文窗口更大,能一次加载整个仓库),这种优势应该被记录,而不是被忽略。公平的记录不是假装条件完全相同,而是把不同的地方写清楚。


七、按顺序收集证据

每次 trial 结束之后,按以下顺序收集证据。顺序很重要——先判功能,再看资源,最后看人工负担。

第一层:功能结果

  • 必须通过的检查:通过 / 失败 / 超时
  • 回归检查:全部通过 / 哪几条新失败
  • 功能实现是否完整

Anthropic 的建议是,优先用确定性的 outcome grader 检查功能,不应因为 Agent 没有复刻某个预想路径就判错——最终产物才是判断依据。

第二层:Diff 与行为

  • 修改了哪些文件,共多少行;行数只用于观察范围,不能单独代表质量
  • 是否出现了与任务无关的改动
  • 工具调用是否出现失败或重试
  • 是否尝试越出权限边界
  • 是否有需要保留的产物(诊断报告、新生成的测试文件等)

第三层:资源

  • 耗时(分钟)
  • Token 使用量(若平台提供)
  • 单次调用成本(若平台提供)
  • 若工具没有暴露这些数字,写 N/A,不能按文本长度猜测

第四层:人工负担

  • Review 花了多少分钟
  • 返工花了多少分钟
  • 是否需要人工干预才能完成任务
  • 最终 Accept 还是 Reject,以及阻塞原因

记录人工 Review 与返工分钟数,因为一次调用便宜,不等于最终交付便宜。一个 Token 成本很低但 Diff 需要反复清理的系统,综合成本可能远高于调用成本高一些但 Diff 干净的系统。


八、重复 trial:为什么需要,怎么用

Anthropic 在评测方法里明确指出,模型输出会随运行变化,因此单次观察不够稳定。对同一个任务、同一个配置运行多次 trial,可以观察它是否反复成功或失败,以及失败形态是否一致。

但重复 trial 不等于生成通过率。

"通过率"需要足够多的样本才有统计意义。3–5 个任务上的几次重复,只能帮助你观察这个配置是否反复成功或失败,以及失败时出现了什么形态。这些是有价值的观察,但不能外推为精确的可靠性数字。

每个任务运行几个 trial,由下面的空白 Protocol 填写;结果保持空白,由运行者自行记录。


九、Protocol 总览

在开始实验之前,用一张表确认所有关键参数已经对齐:

参数类别字段状态
实验标识实验 ID、日期、负责人填写前
决策问题具体问题陈述填写前
仓库仓库地址 + 冻结 Commit填写前
候选配置每个候选完整配置表填写前
共享上下文上下文文件版本与内容填写前
权限/网络每个候选的权限与网络策略填写前
预算Token 上限 / 费用上限填写前
重复次数每个任务跑几个 trial填写前
重置规则具体还原命令或脚本填写前
一票否决项列出所有否决条件填写前
任务列表3–5 个 Task Card(Pilot)填写前

十、用一票否决项和多维矩阵做仓库内决策

所有 trial 完成之后,先过否决项,再看维度矩阵。

否决项只有两种结果:触发 / 未触发。触发否决项的候选配置退出后续比较,原因保留在记录里。

通过否决项的候选配置,进入多维矩阵比较:

维度候选 A候选 B候选 C
功能可靠性(Pass/Regression)
Diff 范围与无关改动
工具失败与权限行为
运行适配(Timeout/Error 率)
资源可见性(Token/成本)
人工 Review 与返工负担

每个维度独立记录,不合并成一个总分。最终决定写在矩阵下方,格式是:

对于这个仓库,在这次 Pilot 覆盖的任务范围内,选择 [候选配置],原因是 [具体原因],已知限制是 [具体限制]。

这是仓库内的选择,不是行业排名。随着仓库变化、任务分布变化、产品版本迭代,结论可以更新。


十一、可复用空白评分卡

以下是可以直接复制到自己仓库的空白评分卡,分为四个部分。所有应填写结果的单元格保持为空,由运行者在实验过程中逐步填入。


Part 1 — Protocol Header

## 实验基本信息

| 字段 | 内容 |
|------|------|
| 实验 ID | |
| 日期 | |
| 负责人 | |
| 决策问题 | |

## 仓库

| 字段 | 内容 |
|------|------|
| 仓库地址 | |
| 冻结 Commit | |

## 候选配置

| 字段 | 候选 A | 候选 B | 候选 C |
|------|--------|--------|--------|
| Agent/Client 名称与版本 | | | |
| Model 名称与版本 | | | |
| Harness / 调用方式 | | | |
| 上下文文件(版本) | | | |
| Tools / Skills | | | |
| 权限与网络策略 | | | |
| 额外系统提示 | | | |

## 共享参数

| 参数 ||
|------|----|
| 共享上下文文件与版本 | |
| Token 上限 / 费用上限 | |
| 每个任务 trial 次数 | |
| 重置命令 / 脚本 | |

## 一票否决项

| 否决条件 | 说明 |
|----------|------|
| 1. | |
| 2. | |
| 3. | |
| (按需增加) | |

Part 2 — Task Card

每个任务复制一份,共 3–5 份(Pilot 规模)。

## Task Card

| 字段 | 内容 |
|------|------|
| Task ID | |
| 来源(Issue / PR / 历史记录) | |
| 任务类型 | |
| 冻结 Commit | |

### 原始 Prompt

```
(逐字粘贴,运行后不修改)
```

### Setup

| 字段 | 内容 |
|------|------|
| 起始环境描述 | |
| 依赖安装命令 | |
| 其他初始化步骤 | |

### 允许范围

| 字段 | 内容 |
|------|------|
| 可修改的文件 / 目录 | |
| 明确禁止修改的文件 / 目录 | |

### 必须通过的检查

| 检查命令 | 期望结果 |
|----------|----------|
| | |
| | |

### 回归检查

| 测试命令 | 运行前状态(全部通过) |
|----------|----------------------|
| | |

### 禁止行为

-
-

### 保留产物

-
-

### 重置方法

```
(具体命令,确保每次 trial 从干净状态开始)
```

Part 3 — Per-trial Record

每个 trial 复制一行或一个区块。

下面三列只展示排布方式,请按 Protocol 中预先声明的重复次数增减,不代表建议固定运行三次。

## Per-trial Record

| 字段 | Trial 1 | Trial 2 | Trial 3 |
|------|---------|---------|---------|
| 候选配置 | | | |
| 开始时间 | | | |

### 功能结果

| 检查 | Trial 1 | Trial 2 | Trial 3 |
|------|---------|---------|---------|
| 必须通过的检查(Pass/Fail/Timeout) | | | |
| 回归检查(Pass/新失败列表) | | | |
| 功能完整性(Pass/Partial/Fail) | | | |

### 运行状态

| 指标 | Trial 1 | Trial 2 | Trial 3 |
|------|---------|---------|---------|
| Timeout / Error | | | |
| 耗时(分钟) | | | |
| Token 使用量(或 N/A) | | | |
| 单次成本(或 N/A) | | | |

### Diff 与行为

| 指标 | Trial 1 | Trial 2 | Trial 3 |
|------|---------|---------|---------|
| 修改文件列表 | | | |
| 修改行数(+/−) | | | |
| 无关改动(有/无,说明) | | | |
| 工具失败 / 重试(有/无,说明) | | | |
| 权限升级尝试(有/无,说明) | | | |

### 产物链接

| 产物 | Trial 1 | Trial 2 | Trial 3 |
|------|---------|---------|---------|
| Diff 文件路径 | | | |
| 测试输出路径 | | | |
| Trace / 日志路径 | | | |

### 人工负担

| 指标 | Trial 1 | Trial 2 | Trial 3 |
|------|---------|---------|---------|
| Review 分钟数 | | | |
| 返工分钟数 | | | |
| 人工干预(有/无,说明) | | | |
| Accept / Reject | | | |
| 阻塞原因(如有) | | | |

Part 4 — Decision Matrix

## Decision Matrix

### 一票否决项状态

| 否决条件 | 候选 A | 候选 B | 候选 C |
|----------|--------|--------|--------|
| 1. | | | |
| 2. | | | |
| 3. | | | |
| 退出比较 | | | |

*触发否决项的候选退出,原因记录在下方。*

### 多维比较(通过否决项的候选)

| 维度 | 候选 A | 候选 B | 候选 C |
|------|--------|--------|--------|
| 功能可靠性(必须通过 + 回归) | | | |
| Diff 范围与无关改动 | | | |
| 工具失败与权限行为 | | | |
| 运行适配(Timeout/Error) | | | |
| 资源可见性(Token/成本或 N/A) | | | |
| 人工 Review 与返工负担 | | | |

*每个维度独立记录,不合并为总分。*

### 否决项触发记录

| 候选 | 触发的否决条件 | 具体描述 |
|------|--------------|----------|
| | | |

### 仓库内决策

> 对于这个仓库,在此次 Pilot 覆盖的任务范围内,选择:
>
> **[ 填写候选配置 ]**
>
> 原因:
>
> 已知限制:
>
> 下次复审时间 / 触发条件:

### 保留的失败原因与取舍

*在这里记录哪些候选被排除以及取舍逻辑,供下次决策参考。*

结语:怎样为这个仓库做决定

公开 Leaderboard 是好的起点——它能帮你缩短候选列表。但选型的终点在你自己的仓库里。

流程本身不复杂:写清楚决策问题和否决项,把候选对象记录成完整配置,从真实 Backlog 里挑 3–5 个任务形态组成 Pilot,在任何 run 之前写好 Task Card,用干净重置保证公平起点,按功能、Diff、资源、人工负担的顺序收集证据,先过否决项、再看维度矩阵,最后写下针对这个仓库的决定和已知限制。

结论是仓库内的结论,不是行业排名。随着仓库成长、任务分布变化、产品版本迭代,这份记录本身就是下一次决策的起点。

如果你打算把其中的几个任务长期维护成持续集成里的质量门禁——在每次合并或每次工具版本升级时自动运行——那是一个值得单独展开的话题,可以参考 Coding Agent Evals Guide 里关于任务夹具和自动化门控的部分。

但在那之前,先完成这次 Pilot。Badge 不替你收拾最终的 Diff。


方法参考:SWE-bench · Anthropic — Demystifying Evals for AI Agents · OpenAI — Evaluation Best Practices · Harbor Tasks