Skip to main content
Convert dataset records into stable TaskSpec values first, then decide which fields the Harness may see and which state must remain evaluation-only.

Distinguish the Four Data Carriers

A Harness can read the entire PreparedTask, including its ground_truth and metadata. Do not copy TaskSpec.metadata into it without filtering. Keep evaluator-only data in TaskSpec.ground_truth or a typed BenchmarkPlan, and set PreparedTask.ground_truth to None. These objects still belong to the runtime and result-audit boundary, so they must not contain credentials or other secret material that must never be persisted. Write a reference answer to RunResult.ground_truth only when it is safe to publish with the result.

Define Public Configuration

Define Benchmark parameters with RuntimeBenchmarkConfig and config_field(), and normalize types early in __post_init__():
Do not download data, install dependencies, or read credentials during module import. Access data through an explicit loader or dependency-preparation path. If a revision, split, or access requirement is invalid, fail with an actionable message.

Load Deterministic Tasks

load_tasks() should pin the upstream revision and produce stable task_id values. The following metadata contains only reproducibility information that may appear in logs and execution input; the answer remains separate in ground_truth:
The inherited select_tasks() method already applies the runtime’s shared task-selection logic. Override it only when the Benchmark needs semantics beyond ordinary ID filtering. Whichever rule you use, keep the returned order deterministic.

Build a Typed Plan for Each Attempt

When evaluator state must be derived from both configuration and the task, define a BenchmarkPlan subclass and resolve it once for the current attempt in build_plan():
build_plan() must not open an Environment, call a Model, or mutate RunRequest. After the initial ExecutionPlan is built, Recipes adjust the plan according to their own contracts. Benchmark documentation therefore must not assume that the runtime enforces one framework-wide precedence rule for Recipe fields. When provider mapping is required, document and test its preservation rules in the corresponding Recipe Integration.

Prepare Execution Input

prepare_task() may create a workspace or upload public material in the task Environment, but its return value may contain only data visible during execution:
Use the supplied EnvironmentSession when you need to create files or directories; do not bypass the Environment and call a provider SDK directly. Retries may invoke this method again, so preparation must be safe to repeat. Otherwise, explicitly clean up the workspace you created before execution.

Registration and Dependencies

Register the implementation with @BENCHMARKS.register() and import its module from src/agentcompass/benchmarks/__init__.py:
From the repository root, inspect component discovery and the parameter schema:
Dependencies required by the framework in every installation belong in the default project dependencies. A Python driver used only by this Benchmark belongs in a dedicated optional dependency group with a declared DependencySpec. Runtime dependencies needed by the task or verifier belong in the corresponding Environment and must be pinned there. Successful registration proves only that the module imports; it does not validate data, credentials, the verifier, or a real run.