01 / 16
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
20 min
Control vs. let go · Agenda
02 / 16
Hi, I'm Ronny · R&D lead, MiniMax Code

Twenty minutes · five beats

We build an open-source coding agent — and we build it with it. These are lessons, not a product tour.

01
The question
Stronger models turn harness parts into dead weight
P03–04
02
A rule for deciding
Let go of judgment · keep control of invariants
P05–06
03
Case studies
Connectors · PTC · long commands · subagents · sessions
P07–11
04
What transfers
Process over pass rate · a checklist
P12–13
05
What stays scarce
Curiosity · execution · scientific literacy
P14–15
Part 01 · The question
03 / 16
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
04 / 16
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
05 / 16
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.

02
Part 02 · How to decide, feature by feature Four questions before you add — or delete — a harness feature
Part 02 · A rule for deciding · The test
06 / 16
Control or let go?

Ask four
questions per feature

Every harness feature is a bet against the model. When the model changes, re-check the bet.

# per feature, every model upgrade
if hidden(x) or irreversible(x):
    harness.enforce(x)
else:
    expose(x); model.decide(x)
# then: eval before vs. after
The test · distilled from our engineering notes
01
Delete it. Where does the model go wrong?

If you can't name the failure, it's a candidate for deletion. If you can, you know what it's for.

02
Can the model even see what it would decide on?

Cache lifetimes, wall-clock time, file mtimes, other sessions, a flaky network — invisible to the model, so the harness owns them.

03
If it's wrong, can you undo it?

Irreversible means enforce it in code. A rule in the prompt is a hint, not a gate.

04
Did it survive an eval?

Measure first, change one thing at a time, keep what survives testing. Look at requests and tokens, not only the score.

Part 03 · Case 01 · Tool discovery & KV cache
07 / 16
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
08 / 16
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
09 / 16
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.

Foreground for 6 minutes and the prior tokens likely fall out of cache. 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
Cost of going asyncBackgrounding buys cache safety — but notifications, anti-polling, cleanup, truth after compaction are rebuilt by hand→Inside a PTC program, often just block
Part 03 · Case 04 · Subagents
10 / 16
Manage context first, then parallelize

More subagents
isn't better.

Subagents are for isolating context, not for carving up territory — one agent per team or per problem type is Conway's law, agent edition.

Default: one main loop + Skills on demand
Let go
When we still split
Cut along context
The test: will I need this output again, or only the conclusion?
R.01The single loop measurably degrades because context grew — eval data, not gut feel.
R.02Parallel threads that each need a clean, throwaway context.
R.03Code review. The reviewer gets only the diff, the requirements and the test results — never the author's conversation.
What didn't work

Splitting by problem type: lossy handoffs, a game of telephone. Moving subagent dispatch inside PTC programs: it got used noticeably less.

Part 03 · Case 05 · Compaction vs. memory
11 / 16
Case 05 · 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
12 / 16
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
Takeaways
13 / 16
Takeaways · a checklist you can steal
Let go

Rules written for older models
Hard-coded workflows and modes
Which tool, which order, which program
Orchestration across many subagents

Keep control

The cache prefix: keep it byte-stable
Permissions: one path, even inside programs
Time: timeouts, cleanup, notifications
Truth outside the context window

And always

Every harness feature is a bet against the model.
Re-check the bet every time the model changes — then ask what stays scarce.

Part 05 · After the harness lets go
14 / 16
Harness lets go · experiments get cheap

When experiments are free,
what stays scarce?

Let go of judgment; keep the invariants. What's left for people: ask the right question, push the idea all the way through, and verify with controls — stacked; pull one layer and the rest idles.

01
Curiosity

Agents answer questions; they don't care which ones matter. The person still asking why / what if is steering.

02
Execution

Friction drops; quitting halfway gets easier. Write a checkable Done; demand evidence, not a report; finish the last 20%.

03
Scientific literacy

Cheap experiments amplify bad method. Hypotheses you can falsify; change one variable; design the control.

Three layers bottom up: Curiosity, Execution, Scientific method
Part 05 · The human loop
15 / 16
Same loop · harness, lab, factory

You own the question
and the control.

After the harness lets go of judgment, cheap experiments amplify method — not volume. You're designing the loop that runs the experiments.

The loop: Hypothesis, Experiment, Control, Verify, Decide
Ask
A hypothesis specific enough to falsify

"Maybe useful" doesn't count.

Finish
Checkable Done · evidence · the last 20%

A clean failure is fine; a half-finished "success" is not.

Control
Same setup, one change · A/B · double-blind

A hundred uncontrolled runs = a hundred anecdotes.

16 / 16
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
×