Highlights
- Multi-agent environments. An
Agentyou run like a function and anEnvthat writes the control flow between agents as plain Python — oneEpisodeper task, with bundledsingle-agent,best-of-n, andagentic-judgeenvs (#1939) and turn-level interleaving between agents (#2049). - ACP integration. Supported harnesses (Codex, Claude Code, ...) run through ACP adapters with resumable sessions (#2257), and stateful harnesses keep one live process across turns over runtime processes (#2249).
- Client-side tasksets. The client owns the taskset and ships each task's data to a stateless env server; resume identity is the task's content, so a changed task re-runs instead of silently matching (#2039).
- Improved performance. The interception server owns and multiplexes the live clients (#2218, #2279), and the train client's tokenizers come from a process-wide elastic renderer pool (#2218).
- New harnesses and integrations.
browser_usefor CDP browser control (#2192), Hermes Agent (#2173), OpenClaw (#2174), NeMo Gym V1 (#2212), pluggable skills in harnesses (#2102), and execution-time network isolation with egress allow/block lists on Docker and Prime (#2024, #2115).
Breaking
Configs
- Every run axis lives under
[env].--taskset.*/--harness.*become--env.taskset.*and per-agent--env.<agent>.*(--env.agent.harness.idon a plain run); per-run caps andretriesmove onto the agent (#1939). - Runtime is an agent field.
[env.agent.harness.runtime]moves to[env.agent.runtime]andHarnessConfig.runtimeis gone — where a rollout provisions its box is the seat's decision, not the harness's (#2106). env.max_concurrentremoved; serving is its own block.serve.max_concurrentbounds a worker's episodes andenv.max_concurrent_agents(default 1) bounds one episode's agents;--pool.*→--serve.pool.*,--address→--serve.address,--id/--args/--extra-env-kwargs→--legacy.*;EnvServerConfigis gone (#2157).ServingConfigrenamed toServeConfig(same fields:pool,address,max_concurrent) (#2237).TrainClientConfig.pool_sizereplaced bymultiplex, with inverted meaning.pool_sizewas "how many renderers";multiplexis "concurrent rollouts per renderer" (default 256) — drop the old value to take the default, or set it toconcurrency / desired_renderers(#2218).share_runtimeremoved from the agentic judge.--env.id agentic-judgeis isolated judging; same-box grading is the explicit--env.id shared-agentic-judge, and the judge always follows the solver's runtime policy (#2234).
Artifacts (trace, episode)
traces.jsonlholds episodes. Each line is oneEpisode—{id, env, ok, errors, traces}— written whole after the env-rollout finishes; traces gainokandagent.name/agent.trainable(#1939).- Trace API renames.
Trace.stamp→record_run,capture_error→record_error,error→last_error; theagent_name/trainable/runtimepassthroughs are removed — readtrace.agent.name/.trainable/.runtime(#2172). - The agent is stamped on the trace.
trace.agentis{config, runtime, name, trainable}:agent.model/agent.sampling/agent.harnessbecomeagent.config.*, and the top-leveltrace.runtimefield moves toagent.runtime; consumers without the run's packages read records viaWireTrace/WireEpisode(#2106). Timing.generation→Timing.agent(GenerationSpan→AgentSpan,Trace.split_generation→split_agent_time) (#2187).Episode.envis a typedEnvInfo(persisted as{"id": ...}— readepisode.env.id), andEpisode.error→Episode.last_error(#2187).vf.StrictBaseModelis gone. The whole record tree parses non-strict — unknown fields are ignored instead of rejected, so additive schema evolution no longer breaks older readers (#2187).
Authoring surface
- Deprecated group rewards.
@group_reward,run_group, and group resume are removed;-r nmeans n independent episodes, and sibling comparison lives in an env'sfinalize()(e.g.best-of-n) (#1939). - Tool declaration is explicit. The
Task.tools/Taskset.toolsclassvars,server_config, andresolve_server_configare removed — overridetoolsets(cls, config)(a classmethod) and construct each server with exactly the config it needs (#2199). - Agents no longer take a live client.
Agent(config, client=...)/make_agent(client=...)are removed — put the endpoint onAgentConfig.client. Harness hooks see a config-valuedctx.client(ClientConfig, not a liveClient); the rollout's live client is atRolloutSession.client(#2218).Agent.run(shared_tools=...)is nowAgent.run(tools=...)(#2094). - Import moves. Config classes live in
verifiers.v1.configs.*(#2106), andscoring/push/artifacts/decorators/loaders/retriesmove underverifiers.v1.utils.*(scoring→utils.score,push→utils.platform) (#2204);RolloutRunis renamedRolloutand takes bundledRolloutTimeouts(#2204, #2205);TaskTimeout.harness→TaskTimeout.agent(#2172). Publicvf.*re-exports are unchanged.
CLI
- The
serveCLI is removed. Host an env server programmatically viaserve_env, or through a trainer (prime-rl'suv run env) (#2237).
Changelog
- fix(v1): don't install envs from the Hub during config parse by @eexwhyzee in #2084
- chore: bump GitHub Actions to latest major versions by @mikasenghaas in #2083
- feat(v1): add capture_patch/resolve_head git utils for SWE tasksets by @rasdani in #2054
- chore: make stable release manual-dispatch only by @mikasenghaas in #2085
- feat(v1): multi-agent api by @hallerite in #1939
- fix: rename Agent.run shared_tools kwarg to tools by @mikasenghaas in #2094
- chore: remove redundant agent artifacts + lab artifacts by @mikasenghaas in #2092
- chore: rename env-rollout to episode by @mikasenghaas in #2095
- docs: hand-written v1 agent and env docs by @mikasenghaas in #2096
- fix: point mint.json at renamed v1 env page by @mikasenghaas in #2097
- fix(v1): close agent-owned clients by @xeophon in #2098
- chore: apply automatic markdownlint fixes by @snimu in #2099
- chore: lint Markdown in pre-commit by @snimu in #2103
- feat(v1): execution-time network isolation for Docker (Linux+macOS) with allow/block egress lists by @xeophon in #2024
- feat(v1): client-side tasksets + stateless env server (v1-only) by @mikasenghaas in #2039
- feat: pluggable skills in harnesses by @mikasenghaas in #2102
- feat(v1): interleaving agents by @hallerite in #2049
- fix: sync docs to public-docs on release tags only by @mikasenghaas in #2108
- fix(v1): prepare Docker runtime once by @xeophon in #2112
- fix(v1): keep standalone Docker tool test runtimes unrestricted by @xeophon in #2113
- Fix oversized evaluation sample uploads by @xeophon in #2114
- Support Prime sandbox egress policies by @xeophon in #2115
- feat: move the runtime onto the agent and stamp the agent config onto the trace by @mikasenghaas in #2106
- feat(v1): configurable agentic-judge grading policy, uploads, and reward weights by @mikasenghaas in #2109
- feat: store raw score and weight on trace rewards by @mikasenghaas in #2119
- Fix Prime runtime config example by @xeophon in #2122
- Tear down MathRubric workers in tests by @xeophon in #2126
- Let rollout timeout own null harness generations by @xeophon in #2133
- Fix provider state graph identity by @xeophon in #2130
- fix(v1): trace Responses custom tools by @hallerite in #2129
- Remove redundant v1 structure by @xeophon in #2146
- Resolve Ruff 0.16 findings by @xeophon in #2147
- Update Ruff and ty tooling by @xeophon in #2148
- feat(v1): expose MCP tools to Codex by @hallerite in #2140
- Fix repository links in v1 docs by @hallerite in #2153
- Align Docker and Prime network policy modes by @xeophon in #2124
- Split deterministic v1 tests from live E2Es by @xeophon in #2127
- Pin standalone MCP clients to v1 by @xeophon in #2155
- fix: blame the runtime, not the harness, when the box dies mid-rollout by @mikasenghaas in #2156
- Upgrade Harbor to 0.20.0 by @xeophon in #2161
- feat(v1)!: two-level concurrency, and serving as its own config block by @hallerite in #2157
- chore: bump renderers to 0.1.9.dev9 by @mikasenghaas in #2175
- Simplify Prime background job polling by @xeophon in #2182
- Simplify episode and trace serialization by @xeophon in #2183
- Simplify installed package checks by @xeophon in #2184
- Simplify dynamic CLI model construction by @xeophon in #2186
- chore: timezone-stable uv.lock and trace record cleanups by @mikasenghaas in #2172
- feat(v1): config-layer taskset system_prompt for the GEPA handoff by @Ziems in #2171
- feat: composable taskset views by @mikasenghaas in #2190
- fix: e2e tests sample at the provider default temperature by @mikasenghaas in #2191
- feat(v1): grade in an isolated box, with Harbor-native artifacts by @rasdani in #2144
- feat(v1): episode-level derived aggregates and typed EnvInfo by @mikasenghaas in #2187
- chore: tighten task.py docstrings by @mikasenghaas in #2193
- feat: add browser_use harness for CDP browser control by @hubert-marek in #2192
- feat: explicit tool-server construction on Task and Taskset by @mikasenghaas in #2199
- docs: drop prose describing the removed toolset config discovery by @hallerite in #2200
- Add Hermes Agent harness by @xeophon in #2173
- chore: bundle per-stage rollout timeouts into RolloutTimeouts by @mikasenghaas in #2205
- Add OpenClaw harness by @xeophon in #2174
- Fix shared Docker state bridge routing by @xeophon in #2123
- Harden interception and MCP capabilities by @xeophon in #2132
- chore: consolidate v1 root modules into utils by @mikasenghaas in #2204
- Fix OpenClaw ACP session resume by @xeophon in #2209
- chore: rollout module cleanups by @mikasenghaas in #2208
- fix(v1): read episode retry cause from last error by @hallerite in #2220
- Merge agent sampling overrides with run defaults by @xeophon in #2226
- fix(v1): preserve optional artifact absence by @xeophon in #2228
- Use live config sources in evaluation skill by @xeophon in #2227
- Update CI to DeepSeek V4 Flash 0731 by @xeophon in #2232
- fix(v1): record Harbor diagnostics as metrics by @xeophon in #2224
- feat: build one client per rollout, share renderers process-wide by @mikasenghaas in #2218
- feat: seed unscored rewards/metrics as None placeholders by @mikasenghaas in #2235
- feat(v1): Harbor separate verifier environments by @rasdani in #2152
- feat!: remove the serve CLI, rename ServingConfig to ServeConfig by @mikasenghaas in #2237
- fix(v1): make the harness MCP tool-call timeout configurable by @hubert-marek in #2239
- Fix stale V1 config references by @xeophon in #2240
- Cancel superseded test runs by @xeophon in #2243
- refactor(v1): reuse Pydantic adapters across validation by @xeophon in #2233
- feat(v1)!: move run info from trace to episode by @mikasenghaas in #2244
- fix(v1): stage Harbor environment in workdir by @parkerpettit9 in #2236
- docs(v1): simplify overview and trim removed-feature details by @xeophon in #2246
- feat(v1): per-token advantages on the node by @mikasenghaas in #2245
- Support restricted shared agent runtimes by @xeophon in #2213
- Split agentic judges with isolated runtimes by default by @hallerite in #2234
- Reject non-finite tool timeouts by @xeophon in #2255
- Use GPT-5.6 Luna for CI evals by @xeophon in #2258
- feat(v1): persist harnesses over native runtime processes by @hallerite in #2249
- feat(v1): run Codex and Claude through ACP by @xeophon in #2257
- chore(deps): bump aiohttp from 3.14.1 to 3.14.3 by @dependabot[bot] in #2259
- Revert "feat(v1)!: move run info from trace to episode" by @mikasenghaas in #2264
- Keep MCP services alive in Prime runtimes by @eligotts in #2261
- Handle late ACP session updates by @hallerite in #2262
- fix(v1): make creation limiters user-global by @mikasenghaas in #2265
- Persist and resume model-free task validation by @rasdani in #2221
- fix(v1): de-flake the live E2E suite by @mikasenghaas in #2267
- fix(v1): bound creation limiter waits by @xeophon in #2273
- Add NeMo Gym V1 integration by @xeophon in #2212
- docs: remove agent.md, simplify env.md, update mint.json nav by @xeophon in #2275
- fix: fail agentic-judge episodes on the solver's own error by @mikasenghaas in #2276
- fix(train-client): filter failed tool calls by @mikasenghaas in #2266
- fix(v1): interception server owns and multiplexes model clients by @mikasenghaas in #2279
- Respect pyproject package rules for sandboxed MCP tools by @rasdani in #2263
- Fix sandbox sdist build coordination by @hallerite in #2271
- fix(v1): isolate ACP client without leaking its uv env by @hallerite in #2283
- chore: bump renderers to 0.1.9 by @hallerite in #2284
- Restore NeMo Gym MCP tool names by @xeophon in #2289
- Fix concurrent sdist build deduplication by @xeophon in #2288
- Update Pi ACP terminal turns by @xeophon in #2292
- chore(deps): bump gitpython from 3.1.51 to 3.1.57 by @dependabot[bot] in #2287
- Update pinned V1 harness releases by @xeophon in #2290
New Contributors
- @eexwhyzee made their first contribution in #2084
Full Changelog: untagged-ea23470cc3f3ddbbca02...v0.3.0