01 / 11
Harness Engineering · Lessons from MiniMax Code

As models get stronger,
what should the harness control
— and what should it let go?

SpeakerRonny (Tao He) · R&D lead, MiniMax Code
Engineering notes · trade-offs · what didn't work
15 min
Part 01 · The question
02 / 11
The model got smarter

Which parts of
your harness just
became dead weight?

And which parts matter more than ever?
Q.
What the industry is doing
03 Signals
Subtraction.
— the harness is shrinking where the model caught up
S.01Anthropic cut Claude Code's system prompt for newer models by more than 80% — partly by loading Skills and tools on demand.
S.02A single main agent with Skills often beats subagent architectures on quality — and is often cheaper and faster.
S.03The Claude Code team has publicly floated removing Plan mode — the model may no longer need it.
Part 01 · The question · Where to look
03 / 11
Same model × different harness = different agent

A harness decides four things.
Each has a part to let go — and a part to keep.

— 01 / Seeing
What it sees
Prompt · tool definitions · compaction · memory
Let go: rules written to correct older models
Keep: the context budget and a stable cache prefix
— 02 / Acting
What it can do
Tools · permissions · sandbox · approval
Let go: which tool, in what order, composed how
Keep: gates on side effects you can't undo
— 03 / Continuing
How it continues
Background tasks · sessions · compaction · handoff
Let go: when to wait, what to summarize
Keep: timeouts, cleanup, the source of truth
— 04 / Proving
How it's proven
Tests · diffs · traces · evals
Let go: nothing.
This is the part of the harness that should grow.
Part 02 · A rule for deciding
04 / 11
The principle
Let go ofjudgment. Keep control ofinvariants.

Judgment — anything the model can now decide better than your if-statements: which tool, what plan, how to split the work, what to summarize.

Invariants — anything the model can't see, can't undo, or can't be trusted to remember: the cache prefix, the clock, process lifetimes, state that must survive.

Part 03 · Case 01 · Tool discovery & KV cache
05 / 11
Case 01 · Connector tools

Inject them every turn, or find them at call time?

Connectors are third-party MCP servers in the cloud, signed in as the user: connect once, use from any device — so the set of connected apps can change at any time.

V1The obvious design
Injected into tools[]
  • Wrap every app tool as connector__<app>__<tool>, fetch the connected list before every turn
  • Short timeout, to protect time-to-first-token
  • Network blip → empty app list: the model can't call anything
  • Fetch fails, or the user connects / disconnects between turns → tools[] changed, cached prefix gone
V2What we shipped
Discovered inside a tool call
  • One small CLI the model calls; the system prompt and a Skill teach it how
  • A tool call can afford a longer timeout
  • Apps never enter the tools array
  • Connect / disconnect no longer touches the cached prefix
Trade-offThe model takes one extra step→discovery now depends on good descriptions→but the prefix stays byte-stable
Part 03 · Case 02 · Too many tools eat your context
06 / 11
Case 02 · Too many tools eat your context

Cut → defer → program

Each step lays the groundwork for the next
Measure at every step
Step 0 · Cut
Load less

Merge tools around user intent, make descriptions distinguishable, group by domain. Past 30–50 tool definitions, models get worse at picking the right one.

Where it stops

You can't delete the MCP servers users install themselves.

Step 1 · Tool search
Defer what's rare

Core tools stay resident. Rare built-ins and large MCP sets move behind search automatically past a size threshold.

Where we got burned

If it can't be found, it doesn't exist. Catalogs fetched over the network every turn slowed first token — we moved them back to resident.

Step 2 · PTC
Write the program

A run_code tool: JavaScript calls tools.* through the same permissions and hooks. Failures return results, not exceptions.

Where we got burned

run_code next to every native tool: barely used, and tokens went up 5%. It worked only once most tools became code-only.

Result150 code tasks + 63 office-doc tasks: scores flat, tokens −13% / −35%, requests 104 → 93 and 102 → 70. PTC doesn't make the model smarter — it does the same work in fewer round trips.
Part 03 · Case 03 · Long-running commands
07 / 11
Case 03 · Foreground → background

Should the agent just wait for npm run dev?

5min
Default prompt-cache lifetime on Anthropic's API. A waiting agent sends no requests.

Run a command in the foreground for 6 minutes and the tens of thousands of tokens before it are most likely no longer cached: slower first token, bigger bill. And the model guesses durations wrong.

The model can't see the cache clock → the harness owns time
What we do · auto-backgroundingOne process, start to finish
Born in background

Every command starts as a background task; the foreground just waits alongside it

01
60 s foreground

Far below a 5-minute cache lifetime, with room for the model's own generation

02
Same task_id

No kill-and-rerun; the model is told not to start it again

03
3600 s, no reset

Foreground time counts; backgrounding or reading output never extends the deadline

04
Part 03 · Case 03 · The bill for going async
08 / 11
Case 03 · What synchronous execution gave you for free

Go async, and you rebuild six things by hand

02 · Anti-polling
Every poll is a full request

"You'll be notified — don't poll." Blocking waits capped at 30 s; a hint after two identical reads.

06 · Precondition
Can't read it? Don't background it

No task_output this turn → plain foreground mode; the background option isn't even in the schema.

AlsoNotifications, output budget, cleanup, truth after compaction — four more to rebuild.
Block inside the program+1 request
model→tests run in the programa few minutes · no request sent→result
Background it, then poll1 full request per poll
60 s → background→program returns early→task_outputnot done · poll again→result
Measured on a PTC run: backgrounding the long commands took it from 7.48M to 8.94M tokens — as expensive as not running PTC at all. Blocking, with the task tools moved inside the program, landed 16.5% below no-PTC.
Same question, different answerAt the top level: background it→inside a PTC program: just block
Part 03 · Case 04 · Compaction vs. memory
09 / 11
Case 04 · Long sessions

The window is a workbench, not a warehouse

Layer 4Global memory
Keepa short index, scoped; viewable, editable, disable-able
Layer 3Project memory
AGENTS.mdshort, stable rules; re-injected after every compaction
Layer 2Session artifacts
Files & gitprogress, todos, design docs — the vehicle for handoffs
Layer 1Working context
Compactionacts only here — lossy; clear old tool results before summarizing
What bit us
01A long memory file was truncated — cutting the most important rules at the top. Nobody noticed.
02Agents said "context is almost full, I'll continue next turn" — they didn't know compaction existed.
03Users kept asking for a handoff doc over an invisible summary.
Control: the budget — a trigger users can only move earlier; compaction never counts as a user step. Let go: what goes in the summary.
Part 04 · What transfers
10 / 11
How we decide what survives

Harness engineering is an experimental science

01
Measure first

Requests, tokens, cache behavior — PTC looked flat on score and was a clear win on requests

02
Change one thing at a time

Change several at once and you can't tell which one did it

03
Judge the trajectory, not just green tests

All tests pass? Check who changed the tests. Did it re-read files, repeat work, drop a constraint?

04
Keep what survives testing

Run each task more than once; look at which tasks flipped, not only the average

01 02 03 04
Process > pass rateHow it got there matters
11 / 11
Closing
Thank you

Thanks.

Tell me what you deleted from your harness — and what you had to put back.
Ronny · MiniMax Code
X · @Ronny_MiniMax
Read the details
MCode Engineering Notes
01
Subagents
More subagents isn't better
manage context first, then parallelize
02
Tools
From tool search to PTC
too many tools will eat your context
03
Long sessions
Compaction vs. memory
why long sessions make agents dumber
04
Long commands
Foreground → background
how long should an agent wait on bash?
Open source · github.com/MiniMax-AI/minimax-code
Created by MiniMax Agent
×