Skip to content
Agentic Control Plane

Run It Ten Times: What a Coding Harness Does That It Doesn't Tell You

David Crowe David Crowe · · 13 min read
harness observability cost agents
Share X HN LinkedIn

Run agents? ACP lets you see, control, and price every tool call they make — allow/ask/deny policy, per-session cost, and a full audit log for Claude Code, Cursor, Codex, and OpenClaw, in one command:

curl -sf https://agenticcontrolplane.com/install.sh | bash

Getting started →  ·  see your first governed call →  ·  free up to 5 agents  ·  prefer fully on-device? add --local

Benchmarks run a harness once per task and take its word for what happened. That is fine for a leaderboard and useless for the question a team actually has before handing an agent real work: what does this thing do when it runs unattended, again and again, with a clock on it?

We ran five coding harnesses on the same task with the same model, ten times each, inside the Terminal-Bench runner, with a gateway recording every tool call independently of the harness. The pass rates were the least interesting output. What the repetition and the second record showed was a set of behaviors none of the harnesses report about themselves.

30-minute budget15-minute budget (the benchmark's own)25%50%75%100%Claude CodeClaude Code, 30 min: 8 of 10 clean trials8 / 10Claude Code, 15 min: 2 of 8 clean trials2 / 8 · 2 lost to 429sQwen CodeQwen Code, 30 min: 6 of 10 clean trials6 / 10Qwen Code, 15 min: 2 of 10 clean trials2 / 10pipi, 30 min: 4 of 10 clean trials4 / 100 / 5CodexCodex, 30 min: 1 of 7 clean trials1 / 7 · 7 lost to 429s0 / 1 · 9 lost to 429sOpenCodeOpenCode, 30 min: 1 of 5 clean trials1 / 5 · every run killed at the budget0 / 3 · 7 lost to 429s
Share of clean trials that passed Terminal-Bench 2.1 sanitize-git-repo, per harness, at the benchmark's 15-minute agent budget and at 30 minutes. DeepSeek V4 Flash via OpenRouter for every harness. Trials lost to upstream rate limiting are excluded and counted beside each bar. 2026-09-03 to 09-04.

1. The clock decides as much as the harness

The task’s own budget is 15 minutes. At that budget Claude Code passed 2 of 10 and Qwen Code 2 of 10. With the same harnesses, same model, same task and a 30-minute budget, Claude Code passed 8 of 10 and Qwen Code 6 of 10.

Nothing about the harnesses changed. Claude Code’s successful runs take 12 to 19 minutes on this task; at 15 minutes it was finishing on the wrong side of the line half the time. A single-run benchmark score at the declared budget reads as “this harness cannot do this task.” Ten runs at two budgets read as “this harness needs seventeen minutes.” Those are different facts, and only the second one is useful to someone deciding how long to let an agent run.

2. Retry budget is a harness trait

Midway through the study the host serving the model began refusing requests with 429s. That was bad luck for the schedule and good luck for the study, because it put every harness under the same stress and they responded very differently.

Harness Refusals absorbed per trial, median Outcome
pi 64 Retried with backoff and finished every run
Claude Code 33 Lost two of twenty runs to refusals; finished the rest
Qwen Code 0 recorded Finished every run
Codex 1 to 2 Quit; half its trials lost

Codex tries a WebSocket first, gets refused, falls back to HTTPS, and after a couple of 429s reports “exceeded retry limit” and ends the turn. Seven of its fourteen trials at the 30-minute budget died that way, on a task it had barely started. pi, the harness with the smallest wrapper of the five, kept retrying for minutes and completed. Under a flaky provider, the retry policy decides who finishes before the model gets a vote.

3. One harness finished the task and never exited

OpenCode’s record reads 1 pass in 20 attempts. That number is an artifact. Every OpenCode run that reached the end of its turn, seven of seven, then sat idle until the runner killed it at the budget and logged a timeout. One of those killed runs had already written the correct files and passed the verifier anyway.

The proxy in front of the model showed every request answered, so nothing was hanging on the network. OpenCode’s own log stops after “turn complete” and stays silent for twenty minutes. On a trivial task the same invocation exits in three minutes. Something in the post-turn path does not resolve on larger sessions. A benchmark records that as a failure. A CI job records it as a hung runner. Neither tells you the work was done.

4. Cache economics belong to the harness and the host together

10k100k1MClaude CodeClaude Code: 1,631,935 prompt tokens, passClaude Code: 1,162,337 prompt tokens, passClaude Code: 1,546,485 prompt tokens, passClaude Code: 1,381,806 prompt tokens, passClaude Code: 2,333,442 prompt tokens, fail:diff-onlyClaude Code: 699,674 prompt tokens, fail:secret-leftClaude Code: 1,225,208 prompt tokens, passClaude Code: 863,674 prompt tokens, passClaude Code: 969,475 prompt tokens, passClaude Code: 1,632,835 prompt tokens, passmedian 1,304kQwen CodeQwen Code: 533,964 prompt tokens, fail:otherQwen Code: 1,892,067 prompt tokens, passQwen Code: 1,916,092 prompt tokens, passQwen Code: 25,651 prompt tokens, passQwen Code: 1,723,819 prompt tokens, passQwen Code: 3,462,245 prompt tokens, passQwen Code: 565,110 prompt tokens, fail:diff-onlyQwen Code: 1,594,626 prompt tokens, fail:secret-leftQwen Code: 1,218,829 prompt tokens, fail:diff-onlyQwen Code: 1,867,601 prompt tokens, passmedian 1,659kpipi: 624,208 prompt tokens, fail:secret-leftpi: 325,606 prompt tokens, passpi: 1,273,095 prompt tokens, passpi: 2,108,459 prompt tokens, fail:otherpi: 575,508 prompt tokens, fail:secret-leftpi: 1,583,025 prompt tokens, fail:diff-onlypi: 151,571 prompt tokens, fail:secret-leftpi: 1,046,524 prompt tokens, passpi: 9,322 prompt tokens, fail:secret-leftpi: 897,751 prompt tokens, passmedian 761kCodexCodex: 487,421 prompt tokens, passCodex: 396,373 prompt tokens, fail:secret-leftCodex: 377,650 prompt tokens, fail:secret-leftCodex: 298,040 prompt tokens, fail:secret-leftCodex: 377,285 prompt tokens, fail:diff-onlyCodex: 166,286 prompt tokens, fail:secret-leftCodex: 210,574 prompt tokens, fail:secret-leftmedian 377kOpenCodeOpenCode: 198,713 prompt tokens, timeoutOpenCode: 67,735 prompt tokens, timeoutOpenCode: 7,222 prompt tokens, timeoutOpenCode: 52,823 prompt tokens, timeoutOpenCode: 1,579,228 prompt tokens, passmedian 68kpasseddid not pass
Prompt tokens per clean trial at the 30-minute budget, one dot per run, log scale, median marked. Same task and model throughout. Token counts are the serving host's usage figures as recorded by the runner.

Qwen Code and pi cached 89 to 92 percent of their prompt tokens. Claude Code cached 29 percent on the same host, with the same model, on the same task. That is not Claude Code’s normal behavior: across 22 real Claude Code sessions on Anthropic’s API in the same week, 1.6 billion prompt tokens, the cache-read rate was 97 percent.

The difference is mechanism. Anthropic caches at breakpoints the harness marks explicitly and tolerates the prompt changing between them. A third-party host caches automatically only when the prefix is byte-identical, and Claude Code’s prefix moves between turns. Qwen Code and pi keep theirs still. So the cache column of any cross-harness comparison is a property of the pair, and anyone pointing Claude Code at a non-Anthropic backend through the base-URL override should expect their cache economics to change by a factor of three.

5. Everyone misses the same secret

When a harness finished and still failed, it was almost always the same miss. The task plants four credentials in three files; the AWS access key ID inside a large tokenized-dataset JSON was the one left behind, run after run, across harnesses. Search-by-pattern finds the obvious ones. The one that looks like data in a data file survives. Ten runs turn “it missed one” into “this is the one they miss.”

6. Headless Codex was running outside the control plane

This one came from the second record rather than the runs. Codex requires each hook to be trusted once, interactively, before it runs; under codex exec an untrusted hook is skipped without a message. Our first Codex runs through the control plane completed the task and produced no session in the gateway at all. The fix is a flag on the exec command. The lesson is that a CI runner with hooks installed for Codex runs outside the control plane until someone has opened the interactive session once, and nothing in the run will say so.

What the second record was for

Every one of these was invisible from inside the harness. The benchmark saw timeouts, not completed work. The harness saw its own retry limit, not a policy that lost half its trials. Claude Code’s built-in meter reported a session cost with an unknown basis; pi’s reported zero. The cache rate looked like a harness property until real sessions on a different host said otherwise.

The gateway sat outside all of that, recording each call as it happened, under each harness’s own client name, from inside the container. Its count of tool calls per run agreed with the harness’s own trajectory files in every case we checked, which is the boring result you want from a second set of books. Where it earned its keep was in what the harness did not write down at all.

Method

  • Runner: Harbor 0.22, task terminal-bench/sanitize-git-repo (find and replace four planted credentials in a cloned repo; tests require exactly three files changed and byte-identical results). Each harness ran as a Harbor agent subclass that installs the control plane’s hook inside the container before the trial.
  • Model: deepseek/deepseek-v4-flash via OpenRouter for every harness in its native wire format. Harness versions: Claude Code 2.1.259, Codex 0.153.1, OpenCode 1.18.27, Qwen Code 0.23.0, pi current on 2026-09-03.
  • Budgets: the task’s declared 900-second agent timeout, and 1,800 seconds. Both conditions were run for every harness. Trials that ended in an upstream rate-limit error before completing are reported as lost, not failed.
  • Infrastructure caveat: OpenRouter routed every request for this model to a single host and did not fail over when it returned 429s, regardless of the account’s provider settings. Twenty-two trials were lost to that overnight and replaced in daytime runs. Retry behavior is reported from the harness’s own logs.
  • What we did not do: ten runs per condition is enough to see the effects above and not enough to rank harnesses by a few points of pass rate. The model is a cheap one; absolute pass rates say more about it than about the harnesses. The policy layer had little to refuse on this task, and we did not test whether the planted credentials were flagged when read into context; both belong to a task chosen for them.
Share X HN LinkedIn
Get the next data drop
What agents actually cost, new tool-surface captures, and the occasional incident post-mortem — sent when we publish something worth your inbox, not on a schedule. Unsubscribe anytime.
Share: Twitter LinkedIn
Related posts

← back to blog