Skip to main content
Use HarnessFreeBenchmark when the upstream evaluation requires a dedicated multi-role interaction, user simulator, or domain state machine that the Benchmark itself must run. Do not choose this path merely to avoid writing a Harness. If one agent loop can serve multiple Benchmarks, implement it as a Harness. Execution belongs in the Benchmark only when the current Benchmark defines the protocol, termination conditions, and trajectory semantics.

How It Differs from an Ordinary Benchmark

HarnessFreeBenchmark inherits every BaseBenchmark contract and additionally requires run_task():
Use none as the Harness ID in the run command:
Here, none means there is no external Harness. It does not require evaluation_environment_mode to be none; Benchmark-driven execution can still use reuse or fresh evaluation.

Implement run_task()

The following excerpt shows only what differs from BaseBenchmark. Assume prepare_task() has written the upstream runner request into the task Environment and stored its public paths under official_runner in PreparedTask.metadata:
This excerpt cannot run by itself because data loading, task preparation, and the upstream runner depend on the actual protocol. It demonstrates the ownership boundary: the runtime manages the Environment lifecycle and error flow, while run_task() runs the Benchmark-specific loop and translates its output into RunResult.

Keep Execution and Scoring Separate

Even if the upstream runner already produces a reward, let evaluate() translate it into the final verdict instead of scoring inside run_task(). This preserves the runtime’s distinction between execution and evaluation failures:
If another command must run to obtain the reward, execute the verifier through the env passed to evaluate() and classify a verifier crash as EVAL_ERROR. See Evaluation Modes and Artifacts for the Environment lifecycle and Results and Aggregation for status composition.

Responsibility Boundaries

  • prepare_task() places the upstream runner, data, and request material in the Environment; repeating it during a retry must not corrupt task state.
  • run_task() owns the Benchmark-specific interaction loop, Model-call orchestration, and trajectory conversion, but it must not create or close the Environment itself.
  • collect_artifacts() only extracts submissions from the task Environment; it does not score them.
  • evaluate() interprets runner output or invokes the official verifier while preserving any existing execution error.
  • Pass credentials for the Model, simulator Model, or judge Model through existing Model-configuration boundaries; they must never enter results, logs, or publishable metadata.
For a complete production implementation, inspect TauBenchBenchmark. It uses the none Harness, starts the upstream interaction runner in run_task(), and evaluates in the same task Environment through reuse mode.