
01 An eval task has to ship with its environment and acceptance criteria
Say we write a task: fix an edge case in the parser, keep the old API, and don’t touch the tests. Putting that sentence in a prompt isn’t enough. Which commit is the repo at? Are dependencies installed? Can the agent reach the network? If a previous run already produced a fix file, this run isn’t starting from the same place. I put these conditions into a task bundle: instructions, initial environment, allowed operations, budget, and the acceptance program. The model, Harness, and grader versions are each recorded separately; a single repo commit usually doesn’t capture the full run conditions. A task bundle might look like this:02 The Runner does more than launch a process
Some terminology first: a task is one problem; a trial is one attempt at that problem by a given version. Every trial gets its own runtime environment, data directory, and artifact directory. Memory, login configuration, caches, and background processes from the previous run must not quietly affect the next. The Runner executes in the stages below. State transitions are persisted to disk so that after a scheduler restart it knows which trials haven’t started, which are still running, and which only need grading. Running a task twice costs extra money and can mix artifacts from two runs into one result.
03 Run tasks with the real MiniMax Code
The adapter only launches, reads output, stops, and collects artifacts. Tool scheduling, context compaction, and model retries stay with MiniMax Code. Rewriting an execution loop just to make evaluation convenient risks replacing exactly the Harness behavior you most want to test. MiniMax Code already hasmcode exec, which can set the working directory, config, timeout, and step limit, and emit stream-json. Inside a prepared isolated environment, it’s launched like this. The Runner fills in the variables; the corresponding directories and config must be prepared beforehand.
schemaVersion, sequence, plus runId, sessionId, and turnId. The adapter validates event version, identity, and ordering, merges deltas by item ID, and keeps the raw stream too. Truncated lines, duplicate terminal events, or a wrong runId should all be recorded as anomalies.
The terminal event exec.completed carries the execution result. status: succeeded only means this execution ended successfully; whether the code was fixed correctly still needs verification. --output-schema only validates the structure of the final answer, too. However tidy the answer JSON is, the tests can still fail.
Sometimes there won’t even be a terminal event, for example on a preflight failure or a crash, so collect the exit code and stderr as well. If a headless run gets stuck on a question that needs a human, handle it according to the pre-agreed rules for unattended or interactive tasks; answering for one group on the fly changes the experimental conditions.
When building the adapter, you can check directly against the CLI contract, event projection, and result types.
04 All tests green? Check who changed the tests
The agent can modify tests, build scripts, and dependencies in its workspace. Printing “all tests passed” — or even genuinely turning the tests green — isn’t enough to accept the result. For code-change tasks, I first freeze the final workspace and have the host check protected files, file types, and the scope of changes, then move the deliverable changes into a clean verification environment. The image, test entry point, and hidden tests are pinned by the eval side. The candidate code is still untrusted, so the Verifier that runs it needs isolation too. Exporting artifacts has its own details. Storing only a plain Git diff can miss untracked files, binaries, permission changes, or symlinks. The artifact protocol has to spell these out. If the deliverable is service state or a database change, save the corresponding snapshot and check the actual behavior from the outside.
accepted is still false. This is an example data structure, not a real score.
05 An experiment on a compaction change
With a run-and-verify pipeline in place, we can return to the opening question: does improving how a checkpoint preserves user constraints reduce constraint violations after compaction? MiniMax Code’s compaction already includes tool-output archiving, checkpoints, and programmatically appended recent state. This time only the way constraints are preserved changes; other prompts, archive thresholds, the model, and the budget stay the same. Change several things at once, and even if results improve, it’s hard to tell which change did it. I’d run this experiment at two levels. First, test the local mechanism: wait for tool calls to settle and background writes to stop, save a shared pre-compaction state, and let the baseline and candidate each continue from there. Observe whether user constraints survive, whether earlier evidence can be read back, whether work gets repeated afterward, and whether the task completes. That state can’t be just the messages. The workspace, session, compaction state, and archived artifacts referenced later all have to be restored; for tasks that depend on databases or external services, those resources have to be restored too. Archive files that are readable on the original machine but whose references break in a different directory will also skew the experiment. The public CLI can’t currently perform this fork in one step; it needs separate test interfaces for triggering compaction and restoring state. Then run end-to-end experiments from the task’s starting point, using the context capacity and trigger policy actually deployed. The candidate might trigger compaction earlier, or read files fewer times, or change the order of tool calls. All of these are effects of the full policy and should be counted.
06 Beyond the score: what records to keep
When a task regresses, I want to be able to find what it read, which tools it called, and at which step it drifted from the requirements. When the grader changes, it should be possible to re-verify old artifacts. That’s the practical use of observability in evaluation. Records can be stored by purpose. The run manifest keeps versions and experimental conditions, the trajectory keeps model and tool events, and the artifact directory holds final files, environment snapshots, and verification output. Re-grading produces a new grade revision linked to the same frozen artifact, without overwriting old scores. A model name alone isn’t enough for the run manifest. You also need the model configuration and whatever service version is available, the Harness commit, fingerprints of the expanded prompt and tool schemas, and the task and grader versions. Permission policy, resources and budget, experiment group, and repetition index should also be queryable. If the server-side version can’t be pinned, record the run’s time window and carry that limitation into the analysis. MiniMax Code’s eval reporter already exposes collection interfaces for pre-call model snapshots, tool calls and results, usage, and turn end. Collection failures don’t interrupt the agent’s normal operation — a sensible trade-off for a product. In an evaluation, though, you also need evidence-completeness flags: a call missing from the logs may simply not have been captured. Usage can be missing too.usageSource and usageIncomplete in ExecResult exist for exactly this; in failure, compaction, and similar scenarios, the accounting may be incomplete. When computing cost, keep the unknown part unknown and record the confirmed cost as a lower bound. Filling gaps with zero underestimates cost; directly adding possibly overlapping cache, reasoning, and total-token fields may overcount.
How failures are handled also needs to be decided up front. The table below is one workable convention:
Budget exhaustion and machine failure can both look like “the process is gone”; telling them apart takes event and resource records. Each retry keeps the original trial, the reason, and a new attempt ID. Report the infrastructure error rate and task coverage alongside the score; otherwise dropping a few failures makes the numbers look good.
If retries hit the limit with still no valid grade, report the gap and its impact on the conclusions. Model call failures can’t all be written off as external faults either: if this evaluation is meant to test the Harness’s recovery ability, they are part of the test. Which cases are excluded follows what was agreed before the experiment started.
07 How to compare two versions
Groups A and B first align on tasks, model configuration, and budget, then run randomly interleaved within the same time window. Concurrency, rate limits, and cache warmth also need to match. If one group runs in the morning and the other at night, service fluctuations can get mixed into the version difference. Resource allocation itself also has to be controlled. Anthropic’s research on infrastructure noise discusses how resource configuration affects agentic coding evals. So CPU, memory, network, and time limits should be recorded along with the model configuration. Decide how many times each task runs before starting. First compute each task’s pass rate in both groups, then compare the differences. Write the pass rates for task i as pᴀ,ᵢ and pʙ,ᵢ; with tasks weighted equally, the overall difference is Δ = (1/N) Σᵢ(pʙ,ᵢ − pᴀ,ᵢ). If you want to weight by the real usage distribution, fix the weights in advance. A task shouldn’t count more in the total just because it was run a few more times.
08 Don’t let the eval set turn into a dev set
Adding real failures to the regression set is useful. But if we keep tuning the Harness against the same set of tasks, we grow familiar with them, and rising scores don’t necessarily mean better performance on new tasks. The dev set is for reproducing and tuning, the validation set for choosing candidates, and the final holdout set is only used once a candidate is frozen. Split by repo, problem family, or time period, so the same task can’t appear on both sides under a different name. Once a holdout set has been looked at enough and used to change strategy, admit that it has become part of the dev set. Compaction experiments can have a targeted task set, but you should also run regressions on common tasks, check for side effects, and add new tasks regularly. Collecting only failure cases overweights hard scenarios; collecting only demo-friendly tasks makes the system look more reliable than it is. Nor does every PR need to run the whole evaluation. Run protocol, grader, and short regressions first; trigger the relevant behavioral evals when compaction, tools, or permissions change. Schedule expensive repeated experiments and new-task testing periodically within budget.pnpm verify in the source continues to check engineering correctness, while real-model task performance is evaluated separately, and the two are reported separately.
If I were starting today, I’d begin with a single task: reset the environment, launch MiniMax Code, verify independently, and leave artifacts that can be re-examined. Then test the grader with a few known-good and known-bad versions. Only after all of that works would I add more tasks and concurrency. Building large-scale scheduling first will most likely just scale up the difficulty of debugging along with it.
MiniMax Code’s public source already includes run entry points, structured events, and evaluation collection interfaces. If you want to get hands-on, you can hook up a Runner, or start by contributing a task that reliably reproduces a failure, or checking whether a grader wrongly accepts bad answers. All of this helps decide whether the next Harness change should stay.
The project is on GitHub. Come discuss with reproductions and experiments in hand, and if you found this useful, a Star is always welcome.
Implementation and references
Source was checked against14053355f39c. The task protocol, external Runner, and fork experiments in this post are design proposals; this post did not run online model comparison experiments and does not report performance gains.
- MiniMax Code: headless CLI arguments
- MiniMax Code: JSONL events and terminal states
- MiniMax Code: result and usage contracts
- MiniMax Code: usage aggregation and incompleteness flags
- MiniMax Code: eval reporter seam
- MiniMax Code: checkpoint and state preservation
- Harbor: task structure
- Harbor: separate verifier environment
- Anthropic: infrastructure noise in agentic evals