inspect-openreward
Run OpenReward environments as Inspect evals.
Provides an Inspect-native Dataset, Scorer, and a session-lifecycle wrapper solver for any OpenReward environment, so you get Inspect's eval harness, transcript viewer, metrics, and model abstraction for free — and OpenReward's tools, tasks, and rewards surface as first-class Inspect primitives. The wrapper takes an arbitrary inner solver chain, so you can keep the default react-style loop or plug in your own scaffolding (system_message, basic_agent, react, custom @solver, …) without touching session management.
Install
uv venv
uv sync
Set OPENREWARD_API_KEY and whichever model provider keys you need (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.).
Quickstart
See ./src/example/terminal_bench_2_verified.py for a runnable version with both a default, and a customer solver chain, task. ./src/example/terminal_bench_2_verified_example_output.txt contains a sample output from running the example against Kimi K2.6 Reasoning.
Benchmark results
To validate the integration end-to-end, we ran all 87 of the Terminal Bench 2 Verified environment, with Anthropic Sonnet 4.5 driving the Claude Code toolset, scoring 55.0%. This lines up closely with our September 2025 benchmark of the same combination, with the ~5% uplift likely reflecting six months of model and harness improvements.
Custom solver chains
openreward_solver is a wrapper: it owns session open/close, prompt injection, tool conversion + installation, and reward capture, and then runs whatever inner solver chain you hand it. That means any Inspect solver composition slots in — chain together system_message, prompt_template, chain_of_thought, self_critique, use_tools(..., append=True), basic_agent, react, or your own @solver — and the OpenReward session-bound tools remain available throughout:
from inspect_ai.solver import chain, generate, system_message
@task
def terminal_bench_2_verified_custom() -> Task:
env = OpenReward().environments.get(name="GeneralReasoning/terminal-bench-2-verified")
return Task(
dataset=openreward_dataset(env, split="test", limit=10),
solver=openreward_solver(
env,
chain(
system_message("Think carefully before each tool call."),
generate(tool_calls="loop"),
),
toolset="claude-code"
),
scorer=openreward_scorer(),
)
Reward / finished capture is baked into the installed tools, so it keeps working no matter how the inner chain drives tool calls (generate(...), execute_tools(...) inside basic_agent, a custom loop, …).
What each piece does
openreward_dataset(environment, split, limit=None, shuffle=False, seed=None)
Builds an Inspect Dataset from an OpenReward environment split. Each Sample carries the underlying OpenReward Task in metadata; the prompt is resolved lazily by the solver (so image prompts work, and there's no network round-trip at dataset-construction time).
openreward_solver(environment, solver=None, *, toolset=None, tool_choice="auto")
Session-lifecycle wrapper around an arbitrary inner solver chain. Per sample it:
- Opens
environment.session(task=..., toolset=toolset). - Fetches
session.get_prompt()and injects it as the user message (text and image blocks both supported). - Converts
session.list_tools()into Inspect tools, auto-detecting the provider fromstate.model.apiand sanitising the JSON schema viaopenreward.sanitize_tool_schema, and installs them onstate.tools/state.tool_choice. - Runs the inner
solverinside the open session. Ifsolver=None(the default), runsgenerate(tool_calls="loop")— the react-style loop. Pass aSolveror alist[Solver](composed viachain(...)) to customise. - Captures the terminal
reward/finishedfrom tool outputs intostate.metadatafor the scorer to read — regardless of how the inner chain invokes tools. - Closes the session on teardown.
Arguments
environment: the OpenRewardEnvironmentto open sessions against. The dataset should be built from the same environment.solver: inner solver (orlist[Solver], normalised viainspect_ai.solver.chain). Defaults togenerate(tool_calls="loop").toolset(keyword-only): optional OpenReward toolset name passed toenvironment.session(...)— e.g."claude-code"for a harness-native bash tool surface in addition to the environment's own tools.tool_choice(keyword-only): passed through to Inspect'sstate.tool_choice.
Inner chains can layer on further tools via use_tools(extra_tools, append=True) — the session-bound tools installed by the wrapper remain available.
openreward_scorer()
@scorer that reads the terminal reward captured by openreward_solver and returns an Inspect Score. Metrics: mean() and stderr(). Samples that never produced a reward (e.g. ran out of turns) score 0.0.
openreward_tool_to_inspect(tool_spec, session, provider=None)
Low-level helper for converting a single OpenReward ToolSpec into an Inspect Tool. The openreward_solver wrapper is built on top of this; use it directly if you want to bypass the wrapper and manage the session yourself.
Model provider mapping
The solver maps Inspect's model-provider identifier to OpenReward's Provider enum for schema sanitisation:
Inspect state.model.api |
OpenReward provider |
|---|---|
openai, openai-api |
openai |
anthropic |
anthropic |
google, vertex |
google |
openrouter |
openrouter |
| anything else | openai (safest superset) |
Release files for inspect-openreward 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| inspect_openreward-0.3.0.tar.gz | 249.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| inspect_openreward-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 259.8 kB
Release files / inspect_openreward-0.3.0.tar.gz
| Download URL | inspect_openreward-0.3.0.tar.gz |
|---|---|
| Size | 249.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
86e288ba56509df1af093194f25d6035762506089ac2d57b85599679aa394344
|
|
BLAKE2b-256 checksum How to use checksums |
5dc6e6ba3b44bb532d82d8c2e49a71932b8fc9cc712249e5c0b79cd2d5c966e4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / inspect_openreward-0.3.0-py3-none-any.whl
| Download URL | inspect_openreward-0.3.0-py3-none-any.whl |
|---|---|
| Size | 10.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b30a21469bcaa40b8d0e368a77270658ccd63e1f19eb94d0b7182cab3d6d8e39
|
|
BLAKE2b-256 checksum How to use checksums |
e188d59a340599cb5648afa2163064b57c8b41d986855ed0546feb58acaf7b11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|