The parts of a harness
The model is one input into an agent. The harness is everything else you build around it - and that "everything else" has a knowable set of parts, four questions to organise them, and one rule for deciding which ones you actually need.
When an agent underperforms, the reflex is to blame the model. Reach for the bigger one, wait for the next release, and the problem should dissolve. The benchmark leaderboards encourage this: they rank models, so we think in models. But the model is the easy part.
The evidence says the reflex is wrong more often than it’s right. Run the same model inside two different setups and its task success rate can nearly double. Same weights, same tasks. Everything that moves the number sits outside the model: what it’s shown, what it can touch, how its work gets checked. Swap a better model into a bad setup and you keep most of the bad setup’s problems, because the model was never the thing failing.
That “everything outside the model” has a name now: the harness. And the working claim of this piece, the one worth remembering if you remember nothing else, is that an average model in a well-built harness will beat a frontier model in a careless one.
I’ve written about parts of a harness before without calling them that: the ReAct loop is its control flow, parallel tool calls its dispatch, and the tool-error pieces its recovery layer. This piece names the whole set: what a harness is, what it’s made of, and how to know which parts yours actually needs.
What a harness is, and what it’s actually for
Strip an agent back to the model and there isn’t much there. A raw model is stateless: it predicts text, returns it, and forgets the exchange ever happened. It can’t run a search, can’t remember yesterday, can’t tell whether the code it just wrote passes the tests. It becomes an agent only when something wraps it with state, the ability to act, feedback on those actions, and limits it can’t cross. That wrapper is the harness. The cleanest definition going: every piece of code, configuration, and execution logic that isn’t the model itself. The line that’s stuck with the field compresses it further:
Agent = Model + Harness. If you’re not the model, you’re the harness.
Worth separating from two neighbouring terms, because they get used interchangeably and aren’t: a framework (LangChain, LlamaIndex) hands you parts, an orchestrator decides when and in what order the model gets called, and the harness is the assembled running system - tools, memory, context policy, enforcement - that those calls live inside.
The common mistake is picturing the harness as defensive, a try/catch around a flaky component, there to stop the model doing something stupid. Think of it instead as a cockpit. A cockpit doesn’t just stop the pilot crashing - its instruments, autopilot, and warning systems let the same pilot fly missions that would be unsurvivable without them. You don’t measure a harness by how many bad outputs it prevents. You measure it by how much bigger the work is that finishes. The long-running agent experiments coming out of the labs show the same thing from the other direction: give a frontier model a multi-session build task with no harness and it doesn’t produce smaller successes, it fails outright - one-shots past its context window, loses its place, declares victory on work it never verified.
And this is why the harness deserves more of your attention than the model choice does: the model belongs to the provider, but the harness is yours. Same model, different harness, completely different agent.
The gap is measured now, not claimed
For a while “the harness matters” was a thing practitioners said to each other. Over the last year it turned into a thing teams measure. One team deleted most of their agent’s tools and watched success rate, token cost, and latency all improve at once - fewer options for the model to get wrong. Another took a coding agent from the bottom of a public benchmark into the top five without touching the model. A legal-tech team roughly doubled their agents’ accuracy the same way. The pattern across all of them: the gap between a good harness and a bad one is regularly larger than the gap between model generations. A model upgrade buys you a few benchmark points. Harness work has been buying teams twenty to forty. The write-ups behind those numbers are in the reading list at the end.
Two rules decide what goes into a harness
Before walking through the components, it’s worth knowing the logic that puts any of them there in the first place. Two rules cover it.
Every component exists to deliver a behaviour the model can’t manage alone. You start from the behaviour you want - remembers the project across sessions, never sends an email without approval, stops retrying a dead API - and derive the piece of engineering that delivers it. There’s a line from one of the lab write-ups worth pinning above your desk: every component in a harness encodes an assumption about what the model can’t yet do on its own. That cuts both ways. It tells you what to build, and it tells you those assumptions go stale - a compaction strategy built for a model that lost the plot at 50k tokens is dead weight on a model that doesn’t. The test to apply: every part of the harness has to answer for a behaviour, and if you can’t say what one is there to deliver, it isn’t earning its place.
Each component is earned from a failure, not a wishlist. The pattern that keeps showing up in every serious write-up of harness work is a ratchet: the agent does something dumb, and instead of retrying with a better prompt, you change the system so that mistake can’t recur - a rule in the instruction file, a hook that blocks the action, a check the work must pass. The mindset shift underneath it is old operations wisdom: when the operator keeps making the same mistake, stop blaming the operator and change the environment. Each failure tightens the harness one notch, and the notch is permanent.
Together these rules mean the components below are not a build order or a checklist. They’re the general set you draw from, and which ones you reach for - and how heavily - depends entirely on what your agent is trying to do. A research agent leans hard on context and retrieval, a support agent on enforcement and approvals. A harness is assembled toward a goal, not stamped out the same every time.
Where the thesis stops holding
Honesty requires the other column of evidence. Recent benchmark work has found cases where harness choice lands within the margin of error - some model families perform much the same whether you give them an elaborate harness or a basic scaffold, and the big-name coding agents don’t consistently beat a minimal loop on short, well-defined tasks. Both effects are real. They just dominate in different regimes.
The way to reconcile them: harness value scales with the gap between the task and what the model can hold in one context window. A short task on familiar ground, handled by a strong model, barely touches the harness - the model reads the problem, does the work, and is finished before state, memory, or recovery ever matter. Stretch the task past one context window, across sessions, through dozens of tool calls, and the ranking inverts: the harness stops being overhead and becomes the thing doing most of the work the model can’t.
This also answers the obvious next question - won’t better models make harnesses redundant? The evidence so far points the other way. Claude Code is over 512,000 lines of code and growing, wrapped around models that improve every few months. Better models don’t retire the harness, they move the work it does - away from stopping failures, toward enabling missions the previous model couldn’t attempt. The cockpit doesn’t get simpler as the pilots get better. The missions get longer.
The components, grouped by the question they answer
Every component in the general set answers one of four questions about the model: what does it see, what can it do, how does the work stay coherent, and what happens when things scale or break. Take the groups in that order.
What does the model see?
-
Instructions. The system prompt, rules, persona, and memory files injected every single turn. The temptation is to write the encyclopedia; the failure mode is well documented. One team building an entire product with agents tried the one-big-instruction-file approach and watched it fail predictably: when everything is marked important, nothing is, and the file rots into stale rules nobody trusts. What worked was roughly 100 lines acting as a table of contents, pointing to deeper docs the agent pulls in only when a task needs them. The instruction file is a map, not a manual. Every line competes with every other line for the model’s attention, so each one has to earn its place - ideally from a real observed failure.
-
Context management. The context window is finite, and it degrades before it fills: models lose instructions buried in the middle of long prompts, and quality drops as tool outputs and history pile up. The harness fights this actively - compacting older history into summaries, writing large tool outputs to storage and keeping only a reference in context, ordering content so the important parts sit where attention is strongest. This is the component the model can’t even in principle provide for itself: it can’t see its own window filling up.
-
Memory and retrieval. Two separate jobs that share machinery. Memory carries knowledge across sessions - files the agent reloads on start, so Tuesday’s agent knows what Monday’s agent decided. Retrieval reaches knowledge that was never in training: search, RAG, internal docs. Since you can’t edit the weights, all learning after training day is context injection. And a corollary worth internalising from the agent-built-codebase experiments: what the agent can’t see doesn’t exist. The design decision that lives in a Slack thread is invisible; the one written to a file the agent reads is real.
What can the model do?
-
Tools and their contracts. Every tool’s name, description, and schema lands in the prompt on every turn, which means tools aren’t free: each one you add is context spent and a choice the model can get wrong. Ten focused tools beat fifty overlapping ones - that’s the mechanism behind the tool-deletion result from earlier, where removing most of the tools made the agent better, not worse. Validate arguments before execution rather than hoping the model formats them right. And one security fact that should be more widely known than it is: a tool description is trusted text the model reads, so a tool from an untrusted MCP server can carry a prompt injection straight into your agent’s context.
-
A general-purpose action path. The alternative to hand-building a tool for every task is giving the agent one open-ended capability: a shell and code execution. With bash and a Python interpreter the agent composes actions you never anticipated, chains them, and writes its own throwaway tools on the fly - what’s come to be called code-as-action. The trade is a real one: a narrow tool is predictable and safe, the general path is capable and dangerous. Which brings you directly to the next component.
-
A safe place to act, and state that survives. If the agent can execute arbitrary code, it needs somewhere that can absorb the consequences: a sandbox that’s isolated, network-restricted to an allow-list, disposable when a run goes wrong, and cheap enough to spin up in parallel. Alongside it, the agent needs somewhere to read and write that outlives a single turn - a filesystem, a database, an object store - because that durable state is what the memory components above are actually built on. The substrate scales with the stakes: a laptop filesystem for a prototype, a cloud sandbox and a proper database once other people depend on it.
How does the work stay coherent?
-
The loop and planning. The control flow that decides what happens next. For short work this is the ReAct loop: reason, act, observe, repeat, until a stopping condition. For long work the loop alone drifts, so the harness adds planning: decompose the goal into a plan file first, then execute against it, ticking items off where every session can see them. The plan is state, not conversation - it survives the context window that produced it.
-
Verification. An agent that can’t check its own work will declare victory on work that doesn’t run; the long-running agent experiments hit this failure constantly. So the harness closes the loop: run the tests, check the output against criteria, feed failures back in as observations. The pattern that makes this reliable is separating the doer from the grader. Models grading their own output skew positive, the same way people do. A separate evaluator - a second model call with fresh context, or better, a deterministic check - has no investment in the answer being done.
-
Enforcement. The difference between “I told the agent not to touch production” and “the system won’t let it.” Instructions are requests; hooks are guarantees - deterministic scripts at fixed lifecycle points that block destructive actions, run checks after every edit, and pause for human approval on anything irreversible. The design insight worth stealing: enforce invariants, not implementations. Pin down the boundaries that must hold and leave the agent free inside them. And write the error message a blocked action returns so it teaches the fix, because that message is the context the next attempt reasons from. The operating principle: success is silent, failures are verbose.
What happens when it scales or breaks?
-
Observability. Ordinary monitoring asks whether the system responded; agent observability asks whether the decision was right, and that needs more than a status code. Log the reasoning trace, the tool calls, and the context that fed each decision, and meter cost and latency per run - an agent that quietly triples its token spend is a failure even when every request succeeds. On top of the logging sit evaluation gates: a fixed set of test tasks you re-run whenever the model, a prompt, or a tool contract changes, because any one of those can shift behaviour without an error ever being raised.
-
Recovery. What the system does when a step fails. The rule I’ve already argued in full: retry transient failures in the harness, in code, and never show them to the model - a retry loop belongs in the infrastructure, not the prompt. Beyond retries, recovery means checkpoints to roll back to, runs that can be replayed from durable state, and the discipline to stop: a run that can’t continue should end with a clear failure, not spin in a loop burning tokens against a dead API.
-
Orchestration. Eventually one agent isn’t the right shape for the work. Orchestration is the harness growing a coordination layer: subagents that take a task into their own fresh context and return only the conclusion, keeping the main context clean; handoffs between specialised agents; and model routing, where a cheap model handles extraction and formatting while the strong one is saved for the calls that need judgement. The organising principle is the same one as ever - context is the scarce resource, and orchestration is how you stop one window having to hold everything.

The mistake is building all twelve on day one
A component list invites a predictable misreading: treat it as a build order, wire up all twelve before the agent has done a day’s work, and end up maintaining a system built for failures you never actually had. Every documented failure mode of harness building is some version of this. The instruction file stuffed with rules for hypothetical problems, where every unnecessary line makes the necessary ones matter less. The elaborate retry-and-recovery machinery around a tool that fails once a month. The compaction pipeline engineered for a context problem the next model release quietly solved, now sitting in the codebase as dead weight that still has to be understood, tested, and worked around.
The discipline that avoids this follows from the two rules in section three. Start with the model and almost nothing, add a component only when a real failure demands it, and remove one when a better model makes it redundant. The first half of that sentence is the ratchet running forward; the second half is the part teams forget. The framing from section three earns its callback here: every component encodes an assumption about what the model can’t do, and assumptions need re-testing every time the model underneath you changes. A harness accumulates components the way a codebase accumulates dependencies - each one justified when added, and collectively a liability unless something is auditing whether they’re still earning their place.
This is also why you can’t download a finished harness, and why the good ones all look different. Two teams drawing from the same twelve components will assemble different systems, because their agents fail differently. The component set is general. The harness never is.
Re-audit the harness, not just the prompt
If the model is one input, then the question to keep asking isn’t “which model should we use?” but “what is our harness assuming about the model we’re on now?” Walk the four questions against your own system: what does it see, what can it do, how does the work stay coherent, what happens when it breaks. Where you find a component you can’t tie to a behaviour, cut it. Where you find a recurring failure with no component answering it, that’s the next one to build.
There’s one question this piece has deliberately left open: what all of this sits on. A harness runs one agent well, but the moment there are many agents, owned by many people, running for a long time, a new layer of problems appears underneath it - durable execution, identity, cost attribution - and the industry is only starting to name it. That layer is a piece of its own.
Worth reading
This piece pulls together threads from a handful of write-ups worth reading in full - no summary does them justice. If you want to go deeper:
- Agent Harness Engineering - Addy Osmani. The best single synthesis of harness engineering as a discipline.
- The Anatomy of an Agent Harness - Viv Trivedy. Where “Agent = Model + Harness” comes from, and the cleanest derivation of why each component exists.
- Effective Harnesses for Long-Running Agents - Anthropic. The strongest public write-up on getting agents to work across many context windows.
- Harness Engineering: Leveraging Codex in an Agent-First World - OpenAI. A product built with zero hand-written code, and where the instruction-file and invariant lessons in this piece come from.
- Skill Issue: Harness Engineering for Coding Agents - HumanLayer. Where “success is silent, failures are verbose” comes from.
- We Removed 80% of Our Agent’s Tools - Vercel, and Improving Deep Agents with Harness Engineering - LangChain. The hard before/after numbers behind the claims in this piece.