Ported terminal-bench tasks that run through the TerminalBenchAdapter
plugin. Each task ships a Docker Compose stack (docker-compose.yaml +
environment/Dockerfile) with all dependencies pre-seeded (PostgreSQL,
application code). The agent is given a single bash tool scoped to the task
container; grading runs tests/test.sh, which writes a reward float to
/logs/verifier/reward.txt.
| Task | Difficulty | Stack | Bugs |
|---|---|---|---|
fix-billing-holds |
medium | Python 3.11 FastAPI, PostgreSQL 15 | fee calculation + data migration |
fix-airline-segmentation |
medium | Python 3.11 (pandas/scikit-learn), PostgreSQL 15 | RFM K-means pipeline correctness |
- Docker daemon running locally.
- Adapter plugin installed into the tolokaforge workspace:
uv pip install -e external_adapters/tolokaforge-adapter-terminal-bench
- LLM API key in
.env(at least one ofANTHROPIC_API_KEY,OPENAI_API_KEY).
scripts/with_env.sh uv run tolokaforge run --config examples/terminal_bench/run_config.yamlEach task ships its own config:
scripts/with_env.sh uv run tolokaforge run --config examples/terminal_bench/run_billing_holds.yaml
scripts/with_env.sh uv run tolokaforge run --config examples/terminal_bench/run_airline_segmentation.yamlThe same task packs also run under a vendor coding-agent CLI installed inside
the trial container instead of the engine's own LLM loop.
run_harness.yaml is the driver config; it names
agent_harness: claude-code and agent_model: openrouter/anthropic/claude-sonnet-4-6.
Swap either field to matrix over harnesses or models:
scripts/with_env.sh uv run tolokaforge run --config examples/terminal_bench/run_harness.yamlSix harnesses ship (claude-code, codex, gemini-cli, kimi-code,
opencode, grok-build). The Gemini/LiteLLM gateway path ships as a
whole-entry overlay in gemini_litellm_overlay.yaml.
Per-harness recipes (Kimi K2.7 middleware, opencode routing, Gemini gateway),
provider-env envelopes and result-bundle layout live in the end-to-end guide:
docs/RUNNING_TERMINAL_BENCH.md. When
to reach for harness mode vs engine-loop mode is covered in
docs/CODING_HARNESSES.md.
- Discovery —
TerminalBenchAdapterscans this directory for subfolders that contain bothdocker-compose.yamlandtask.yaml/task.toml. - Environment synthesis — for each discovered task the adapter
materialises a staging directory holding a copy of the task pack, a
tests/test.shscript, empty_logs/mountpoints, and a synthesiseddocker-compose.tolokaforge.yamlthat resolves the terminal-bench variable set at synthesis time and injects enginerunner+db-serviceservices. The adapter emits anEnvironmentPatch(stack.compose_file=…, stack.runner_service="runner")onTaskConfig; every compose service resolves toServiceSpec(isolation="ephemeral"), so the orchestrator selectsPerTrialRuntimeBackendautomatically. - Image pre-build — the adapter declares one
ComposeImageBuildper task ondocker_stack_requirements(); the orchestrator runsdocker compose -f <synthesised> build <agent-service>once per run, before any trial provisions. - Provision —
PerTrialRuntimeBackend.provisioncopies the staging directory into a per-trial context, writes a.envwithTOLOKAFORGE_TRIAL_SLUG=<sanitised trial-id>, and runsdocker compose up -d --wait. The synthesised compose file pins the agent container astbench_${TOLOKAFORGE_TRIAL_SLUG}_<agent-service>. - Execution — the runner-side
bashtooldocker execs into that container by name; no compose lifecycle runs inside the tool. - Grading — after the agent finishes, the Runner executes
cd /tests && bash test.sh, then reads/logs/verifier/reward.txt. The float value (0.0–1.0) is the final score;binary_pass = reward >= 0.5.
To verify your setup without spending API calls, build one task image and run its test suite on the unsolved baseline:
cd examples/terminal_bench/fix-billing-holds
docker build -t tbench_fix-billing-holds:smoke ./environment
T_BENCH_TASK_DOCKER_CLIENT_IMAGE_NAME=tbench_fix-billing-holds:smoke \
T_BENCH_TASK_DOCKER_CLIENT_CONTAINER_NAME=billing_smoke_main \
T_BENCH_TASK_LOGS_PATH=/tmp/tbench/logs \
T_BENCH_TASK_AGENT_LOGS_PATH=/tmp/tbench/agent_logs \
T_BENCH_CONTAINER_LOGS_PATH=/logs \
T_BENCH_CONTAINER_AGENT_LOGS_PATH=/logs/agent \
T_BENCH_TEST_DIR=/tests \
docker compose -p billing_smoke up -d --wait
docker compose -p billing_smoke cp tests/. main:/tests/
docker compose -p billing_smoke cp run-tests.sh main:/tests/test.sh
docker compose -p billing_smoke exec -T main bash -c \
"mkdir -p /logs/verifier /logs/agent && cd /tests && bash test.sh"
docker compose -p billing_smoke down -v --remove-orphansYou should see some tests pass (baseline health + pre-bug assertions) and a reward printed to stdout.
Terminal-bench tasks run under PerTrialRuntimeBackend. Backend selection is task-driven: the manifest the adapter emits declares every compose service as ephemeral, so Orchestrator._select_backend_from_tasks() returns per_trial and every trial gets its own compose project — no config change is required. TrialExecutor's provision → await_ready → endpoints → teardown bracket, per-trial network isolation, and PROVISION_ERROR attribution all apply. See docs/RUNTIME_BACKENDS.md § "Adapter compatibility with per_trial".
docs/CODING_HARNESSES.md— coding-harness mode: when to use each mode, per-harness quick referencedocs/RUNNING_TERMINAL_BENCH.md— end-to-end how-to for both engine-loop and harness modesdocs/ADAPTER_ARCHITECTURE.md— how adapters plug into the orchestratordocs/RUNTIME_BACKENDS.md— runtime backends + adapter compatibilityexternal_adapters/tolokaforge-adapter-terminal-bench/— the adapter sourcetolokaforge_coding_harnesses/README.md— the harness registry package