添加 Benchmark
Benchmark 负责数据集协议、任务构造、任务准备、评分逻辑和指标聚合。它不应该负责模型调用、agent loop、sandbox 生命周期,也不应该硬编码某个 provider 的镜像选择。 当你要引入新的任务族、新的评测协议或新的 scoring 逻辑时,添加 benchmark。如果只是要把现有 benchmark 适配到某个远程 sandbox 的镜像、workspace 或资源参数,应该添加 recipe。Benchmark 文件
在src/agentcompass/benchmarks/ 下新增模块。通常包含一个 RuntimeBenchmarkConfig、一个可选 BenchmarkPlan,以及一个继承 BaseBenchmark 的实现。
Benchmark 职责
| Hook | 作用 |
|---|---|
id | 稳定 CLI/config id,也会被 recipe、analyzer、结果路径和文档引用。 |
description | agentcompass list dump 导出的用户可见描述。Benchmark 和 harness 必须提供非空 description。 |
config_class | 解析 --benchmark-params 和默认配置。数据路径、版本、split、采样参数应放在这里。 |
load_tasks() | 加载原始任务并返回 TaskSpec。应保持确定性,并在数据缺失时尽早失败。 |
select_tasks() | 可选自定义采样逻辑。基类已经支持 sample_ids。 |
build_plan() | 为单个 task 生成 benchmark-side runtime state,后续 recipe 可以改写它。 |
prepare_task() | 将 TaskSpec 转成 benchmark-to-harness 的 PreparedTask 契约。 |
evaluate() | 对 harness 的 RunResult 评分,并返回标准化后的最终结果。 |
aggregate_metrics() | 可选聚合逻辑。默认路径会聚合 binary correctness。 |
TaskSpec.metadata 适合保存原始记录、镜像名、expected files、benchmark-specific id 等信息;PreparedTask.input 和 PreparedTask.output 才是 harness 应消费的正式契约。
注册与验证
在src/agentcompass/benchmarks/__init__.py 中导出:
添加 Harness
Harness 负责 agent 或 model 的执行 loop。它消费PreparedTask、RunRequest.model 和 EnvironmentSession,并返回标准化的 RunResult。它不应该加载数据集、判断 benchmark correctness,或硬编码某个 provider 的 sandbox 镜像。
当你要接入新的 agent framework、coding assistant、GUI agent、direct model-call path 或 tool-use 策略时,添加 harness。
Harness 文件
在src/agentcompass/harnesses/ 下新增模块。通常包含一个用户可配置的 RuntimeHarnessConfig、一个 HarnessPlan,以及一个继承 BaseHarness 的实现。
Harness 职责
| Hook | 作用 |
|---|---|
id / description | 稳定 CLI id 和导出描述。已有 official website 时应写入 description。 |
supports() | 在执行前校验 environment 和 model protocol 是否兼容。协议不支持时应给出清晰错误。 |
config_class | 解析 --harness-params 和默认配置。公开参数不要散落在 metadata 里。 |
plan_class | 由 config 派生出的 runtime state。最终 plan 可被 recipe 查看或改写。 |
start_session() | 初始化 client、agent config、后台进程或每次 run 的状态。 |
run_task() | 执行一个 PreparedTask,返回 RunResult,尽量保留 trajectory、artifact、usage 和 error。 |
close_session() | 释放外部进程、client、临时 session 或远程框架状态。 |
prepared.input.workspace、files、media、tools、messages 等正式字段,而不是反向依赖某个 benchmark 的私有 metadata。这样同一个 harness 才能复用到多个 benchmark。
注册与验证
在src/agentcompass/harnesses/__init__.py 中导出:
添加 Environment
Environment provider 负责执行 primitive:命令执行、文件传输、文本读写、目录同步、endpoint discovery 和 teardown。它不应该知道 benchmark scoring,也不应该处理 agent 行为。 当 AgentCompass 需要在新的本地进程、容器运行时、云 sandbox 或远程执行 provider 上运行同一套 benchmark/harness 矩阵时,添加 environment。Environment 文件
在src/agentcompass/environments/ 下新增模块。每个 provider 通常包含 session class、config dataclass 和 BaseEnvironment 实现。
Environment 职责
| Surface | 作用 |
|---|---|
exec() | 实现 subprocess-like 语义,处理 shell、cwd、env、timeout、detach,并返回 ExecResult。 |
| File primitives | 实现 upload、download、write_text、read_text、upload_dir、download_dir。 |
endpoint() | provider 暴露可访问 URL 时返回 URL,否则返回 None。 |
RuntimeEnvironmentConfig | 文档化 image、resources、region、credentials、workspace root 等公开参数。 |
open() | 从 recipe-adjusted ExecutionPlan 构建 provider session。 |
close() | 稳定释放远程资源,并容忍部分初始化失败的 session。 |
config/defaults.yaml。Benchmark-specific image、snapshot、workspace 或 resource 映射应放在 recipe 中。
注册与验证
在src/agentcompass/environments/__init__.py 中导出。可选 SDK 依赖需要用 import guard:
添加 Recipe
Recipe 是 benchmark family 和 environment provider 之间的兼容层。它在 sandbox 启动前改写单个 task 的ExecutionPlan,通常用于选择镜像、workspace、resource request、snapshot、环境变量或 evaluation layout。
当 task metadata 已经包含 provider 需要的信息,并且用户不应该在 CLI 手动传入这些参数时,添加 recipe。
Recipe 文件
在src/agentcompass/recipes/<benchmark_family>/ 下新增模块。不同 provider 的行为差异较大时,推荐一个 provider 一个文件。
Recipe 职责
| 规则 | 原因 |
|---|---|
| Match narrowly | 检查 benchmark id、environment id 和必要 task metadata,避免误触发。 |
| Preserve user overrides | 用户显式传入 image、resources、workspace、credentials 时,优先保留或做兼容性检查。 |
| Fail before sandbox startup | 重型 benchmark 缺少必要 task image 时,在 apply() 中给出清晰 ValueError。 |
| Rewrite plans, not configs | 改写复制后的 ExecutionPlan,不要修改原始 RunRequest。 |
| Keep execution out | Recipe 不应运行命令、创建 session、评分结果或调用模型。 |
| Share helpers by benchmark family | 多个 provider 共享 workspace layout 时,放到 recipes/<benchmark_family>/common.py。 |
execution.enabled_recipes 为空时,recipe 会自动匹配。用户也可以通过 --enabled-recipes 限定 recipe 选择。
注册与验证
从 package initializer 导出 recipe:Recipe matched 和新 recipe id:
添加 Analyzer
Analyzer 在任务生成RunResult 之后运行。它检查 trajectory、metrics、error、latency、模型输出或 tool calls,并把 AnalysisResult 写到每个 details JSON 的 analysis_result.<AnalyzerId> 下。跨任务聚合字段会渲染到 analysis_summary.md 和 analysis_summary.json。
当逻辑属于后置诊断或统计时,新增 analyzer。不要把可重新运行的诊断逻辑塞进 benchmark 或 harness。
Analyzer 文件
在src/agentcompass/analyzers/basic/ 下新增文件;如果是一组较大的 analyzer,也可以创建新的 sub-package。每个 analyzer 都要继承 BaseAnalyzer,使用 @ANALYZERS.register() 注册,并实现 analysis()。
Analyzer 属性
| Attribute | 作用 |
|---|---|
id | 稳定 analyzer id,用于 registry、CLI selection、details JSON 和 summary。 |
description | 用户可见描述,会被 agentcompass list dump 导出。 |
category | summary 分组。可使用 AnalyzerCategory.ERROR、EFFICIENCY、BEHAVIOR、ABILITY、BASIC_BADCASE、ENV_FRAMEWORK_ERROR。 |
datasets | 支持的 benchmark id 列表。空列表表示所有 benchmark。 |
data_requirements | analysis 前检查的 JSONPath requirements;缺失字段时跳过该样本。 |
conf | 从 execution.analysis_params.<AnalyzerId> 合并来的 analyzer 配置。常见字段包括 only_incorrect 和 threshold。 |
distribution_fields | 需要跨任务聚合的 details 字段。值为 numeric_stats 或 value_counts。 |
base_analyzer / priority | benchmark-specific analyzer 覆盖 generic analyzer 的机制。同一 family 中 priority 更高者生效。 |
AnalysisResult.is_badcase 应设置为:True 表示 badcase,False 表示明确通过,None 表示 statistics-only analyzer,不参与 badcase ratio。
聚合字段
需要进入跨任务 summary 的字段必须声明在distribution_fields 中:
| Method | 适用字段 | Summary 输出 |
|---|---|---|
numeric_stats | 数值或数值列表。 | count、min、mean、percentiles 和 max。 |
value_counts | 字符串或字符串列表。 | value frequency 和 ratio。 |
AnalysisResult.details 中返回的 key 才能被聚合。
注册与验证
把 analyzer 从 package initializer 导出,确保 registry import side effects 能看到它:开发者说明
- Analyzer 应只读取和诊断已有结果,不应修改 benchmark 执行行为。
- Benchmark-specific analyzer 应优先使用
datasets限定适用范围。 - 当 benchmark-specific analyzer 需要覆盖 generic analyzer 时,使用
base_analyzer和priority。 - 如果缺少可选 trajectory 字段,返回带
error的AnalysisResult,不要直接抛异常中断整批 analysis。
