Harbor and Terminal-Bench: the Gym
Date: 2026-08-24
Status: plan. Companion to docs/2026-08-24-benchmark-workbench-agentx.md,
whose effectiveness axis (axis 2) this document re-bases on Harbor. Read
from the clone at projects/repos/harbor (v0.16.x, Apache-style OSS from
the Terminal-Bench creators).
0. The Gym framing
This is not only measurement. Harbor and Terminal-Bench are the Gym: the training ground where the coder's capability work proves itself against graded tasks, the way a model proves itself against an RL environment. Concretely, three loops run through the same suites:
- Extend the coder. A new capability lands with a Gym delta: the suite score before and after, on the same recipe. A capability that moves no score is questioned; a graded task class the coder cannot pass yet is a capability backlog item.
- Test multi-model swapping. The same suite per compute-mix lane — each catalog model through the proxy, and Fable through the foreign-harness delegation lane beside the stock claude-code adapter — turns "which lane should this task class route to" into an evidence-backed policy instead of a vibe, and eventually feeds the routing policy itself.
- Test plugins. The same suite with and without a plugin loaded;
provenance-stamped
tool.ransteps in the ATIF make the delta attributable to the exact plugin digest. A plugin's Gym delta is the registry's first honest quality signal.
RewardKit closes the far end of the loop: the same trials become RL rollouts when optimization work begins — candidates, never auto-promotions, per the standing law.
The surface shipped with this plan (310dac1): gym_runs records
graded runs idempotently by recipe digest, the bench harness posts them
through POST /api/v3/gym/runs, and /gym — a sidebar entry under
Projects — renders the scoreboard. Operator-only on every path for now:
the operator allowlist is the whitelist, deliberately, rather than a
second gating mechanism; widening it later is a decision, not a default.
The Gym project (project 14) tracks the lane.
1. What Harbor is
Harbor is the official harness for Terminal-Bench 2.0 and a general framework for evaluating agents in container environments: a task is a container image plus an instruction plus a verifier; an agent is installed into the environment, runs against the instruction, and the verifier grades the outcome. One command runs a whole benchmark:
harbor run --dataset terminal-bench@2.0 --agent claude-code \
--model anthropic/claude-opus-4-1 --n-concurrent 4
What makes it the right effectiveness engine for the workbench rather than anything hand-rolled:
- The registry is 80 datasets, not one: Terminal-Bench 2.0 first, and
then SWE-bench (plus multilingual/pro/smith variants), Aider Polyglot,
OSWorld, GAIA, CyberGym, tau3-bench, and 70 more, all runnable through
the same contract (
registry.json). - 48 agent adapters already exist — Claude Code, Codex, Gemini CLI, Goose, Grok Build, Cursor, Devin, Hermes among them — which means the competitive baseline table is free: the same task set, the same grader, our agent beside the field.
- ATIF is its trajectory format. The spec the coder already exports
(
rfcs/0001-trajectory-format.mdlives in this repo); adapters writetrajectory.jsonin ATIF after each trial, andharbor-atif2otelprojects it to OpenTelemetry. Our/exportspeaks this natively, including the plugin-provenance system steps shipped asOpenAgentsInc/openagents#32. - Environments are pluggable — local Docker plus ~30 providers (Daytona, Modal, E2B, GKE, EC2…) behind one interface with network policies (allowlist/no-network, probed rather than assumed) and resource policies. This is the same shape as the cloud-computer lane's owner-hosted/managed split, and a later OpenAgents environment provider is a natural (not urgent) extension.
- RewardKit turns the same trials into RL rollouts (judges, criteria, rewards) — the optimization loop waiting at the end of the measurement loop.
2. The adapter contract, precisely
BaseInstalledAgent (src/harbor/agents/installed/base.py) is what an
openagents coder adapter implements:
install(environment)— in-container install; for us,npm install -g @openagentsinc/cli(a pinned version).- A run command built from the instruction, with prompt-template support;
for us,
openagents coder --plainfed the instruction, on a lane that works headless in a container (an API-key/base-URL model connection via Harbor'sModelConnectionSpec, or the account lane where a token can be provisioned; the offline refusal must never look like a task failure). - Typed error patterns: Harbor classifies agent failures
(rate-limited, usage-exhausted, context-window, overloaded, safety
refusal, auth) from output patterns so retry policy can target them —
--retry-include ApiRateLimitError. The adapter must map the CLI's typed errors and exit codes onto these classes; our exit-code discipline makes that mechanical. populate_context_post_run— writelogs_dir/trajectory.jsonin ATIF. The coder's existing exporter is the implementation; the adapter runs/export(or reads the export the session already wrote) and copies it out.- Capabilities: declare
atif=Trueon day one.resumemaps to--resume --last;load_atif_trajectory(seeding a session from an ATIF file, which the Claude Code adapter implements bidirectionally) is exactly the foreign-session import direction of OpenAgentsInc/openagents.com#198 — declare it when that lands, not before. - No fork needed to start:
harbor run --agentaccepts a custom import path (create_agent_from_import_path), so the adapter can live in our tree and run against upstream Harbor immediately. Upstreaming it to Harbor's 48-adapter roster is the distribution move — every Harbor user gains-a openagents-coder— and worth doing once the adapter is stable.
3. What we measure, and what stays ours
Harbor produces graded trials with ATIF trajectories. The workbench's own
layer on top stays exactly as specified: score floors in a thresholds
file (a run below floor fails the gate), digest-pinned recipes (CLI
version, model catalog revision, plugin set, dataset@version), receipted
results in bench-results, and cost per accepted outcome as the
headline — computable directly because every trial's ATIF carries token
metrics and the model catalog carries pricing.
The comparative matrix the compute mix wants falls out of Harbor's design:
| Comparison | How |
|---|---|
| Our coder across house lanes | -a openagents-coder per catalog model through the proxy |
| Our coder vs the field | Same dataset, Harbor's stock adapters (claude-code, codex, goose…) |
| Fable via us vs Fable native | -a openagents-coder on the foreign-harness lane vs -a claude-code — measuring what our orchestration adds or costs |
| Plugin value | Same suite with and without a plugin loaded; provenance-stamped tool.ran steps in the ATIF make the delta attributable |
Start with terminal-bench@2.0 because it is agent-agnostic terminal
work — closest to what the coder is for — then widen to SWE-bench and
Aider Polyglot from the same registry with zero new harness code.
4. Sequencing
- The adapter (
OpenAgentsInc/openagents#35): out-of-treeBaseInstalledAgentsubclass, ATIF out, typed error mapping, pinned install. Acceptance:harbor run -d terminal-bench@2.0 -a <import path>completes trials locally on Docker with graded results and valid ATIF trajectories. - The baseline (folds into
OpenAgentsInc/openagents#34): a scored Terminal-Bench 2.0 run per compute-mix lane beside the stock claude-code adapter, published tobench-resultswith thresholds set from the first honest numbers. - Cadence: per-release gate and weekly trend, as the workbench spec already states.
- Later, recorded not filed: upstream the adapter to Harbor;
load_atif_trajectoryonce #198's import half exists; an OpenAgents cloud-computer environment provider; RewardKit rollouts feeding the optimization loop (GEPA-style, candidates never auto-promoted).
5. Division of labor with AgentX
Unchanged from the workbench spec, now with the right engine in each seat: AgentX measures the serving side (how the compute mix carries coder-shaped traffic per dollar — axis 1), Harbor measures the agent (does the coder finish graded tasks, at what cost — axis 2), and the thread-to-WEKA exporter (axis 3, #218) feeds AgentX-style replay with our own consented traffic. Harbor's ATIF trials are also raw material for axis 3's cousin: consented trajectories are the corpus the registry strategy wants, in the format we already speak.