For a long time, “make the agent better” meant “wait for a better model.” That is no longer the whole story. The people building serious AI agents now agree on a simple formula:

Agent = Model + Harness

The model is the brain. The harness is everything around it. And here is the surprising part: once your model is good enough, most of your remaining improvement comes from the harness, not the model. A weak model with a great harness beats a great model with a weak harness.

This article explains what the harness is, why it matters so much, how to build one, and how to keep it healthy as models keep changing.

What the harness actually is

The rule of thumb from LangChain’s Vivek Trivedy is short: if you’re not the model, you’re the harness.

The model itself just turns text in into text out. The harness is everything that makes that useful:

  • the system prompt
  • tools, Skills, and MCP servers (plus their descriptions)
  • infrastructure like a filesystem, a sandbox, and a browser
  • orchestration logic (spawning sub-agents, routing between them)
  • hooks that run at fixed points to force certain behavior
  • observability: logs, traces, and cost tracking

That last one is easy to skip but important. If you can’t see what the agent did, you can’t tell whether a change helped. As the practitioners put it: a harness without observability is a harness you can’t improve.

Why do harnesses exist at all? Because a model on its own can’t remember things between runs, can’t run code, can’t look up today’s news, and can’t set up its own workspace. The harness fills those gaps. The design habit is always the same: decide what behavior you want, then build the piece that produces it.

deepset adds a sharper way to think about it. A harness doesn’t just help the model — it changes the job the model has to do. It takes over the three things models are worst at:

  • memory — keeping track of things over time
  • skills — knowing how to do a procedure
  • protocols — following a set structure for interaction

The clearest example is memory. Instead of asking a forgetful model to remember something, the harness writes it down and later asks the model to read it. Remembering is hard; reading is easy. The harness quietly swaps the hard job for the easy one.

The harness is also the glue that holds these together. It runs the main loop, decides how the limited context budget gets shared, and enforces what each tool is allowed to do.

flowchart TB
    M[Model<br/>the brain]
    M --> H
    subgraph H[Harness: everything else]
        direction TB
        SP[System prompt]
        T[Tools / Skills / MCP]
        FS[Filesystem + Git]
        SB[Sandbox / code execution]
        CTX[Context management]
        MEM[Memory + search]
        ORCH[Orchestration:<br/>sub-agents, routing]
        HK[Hooks]
        OBS[Observability:<br/>logs, traces, cost]
        SP ~~~ T ~~~ FS ~~~ SB ~~~ CTX ~~~ MEM ~~~ ORCH ~~~ HK ~~~ OBS
    end

One split is worth naming early. The builder harness is what ships inside an agent product — the parts above, put together by whoever built it. The user harness is what you build around a coding agent in your own project: the conventions, checks, and guardrails you add so it needs less babysitting. Most day-to-day craft happens in that second layer.

Why the harness is where the wins are

If the model keeps improving on its own, why fuss over the scaffolding? Because the scaffolding moves the score more.

HumanLayer’s Kyle gave this its catchphrase: the model is probably fine; it’s just a skill issue. His point is that most agent failures are setup problems, not model problems. So before you blame the model, look at the harness.

The benchmarks agree. On Terminal Bench 2.0, the same model scored much lower in a generic setup than in a purpose-built one. Trivedy’s team jumped from Top 30 to Top 5 by changing only the harness. deepset saw the same thing: harness-only tweaks moved agents 20-plus places in the rankings. Their summary of the shift is memorable: AI engineers are becoming environment designers. And deepset’s bottom line is that tuning the harness gives you bigger reliability gains than upgrading the model, for far less money.

There’s one point where the sources openly disagree, and it’s worth keeping rather than hiding. Both HumanLayer and deepset say “harness engineering” and “context engineering” are two nested, related skills — you need both. But they disagree on which one contains the other:

  • HumanLayer: harness engineering is part of context engineering.
  • deepset: context engineering is part of harness engineering — because context work manages what the model sees right now, while the harness also manages how the whole system behaves over time.

This article leans toward deepset’s view, since “Agent = Model + Harness” treats context management as one piece inside the harness. But the disagreement is real, and you should know both camps exist.

The parts of a builder harness

Trivedy’s breakdown gives the parts list.

Filesystem. It does three jobs at once: it stores state that outlives a single run, it lets the agent park information outside the prompt and read it back later, and it acts as shared space between agents and people. Add Git on top and you also get history, diffs, and the ability to undo the agent’s work.

Code execution and sandboxes. Instead of building a custom tool for every task, you give the model a shell and a computer. One general ability lets it solve many problems on its own. But running code needs a safe place, so a sandbox gives it an isolated environment — which also lets the agent run its own work and check the result.

Context management. The context window is small and gets worse as it fills up (a problem often called “context rot”). The harness fights back a few ways:

  • compaction — summarize old context to free up room
  • offloading — move bulky tool inputs and outputs to the filesystem
  • progressive disclosure — load a Skill’s instructions only when they’re needed, instead of paying for everything up front

A stronger move is a context reset: wipe the window and start fresh from a short handoff note. This fixes “context anxiety,” where a model rushes to wrap up as its window fills. deepset simply calls a full window a failure, and its fix is the same: keep state in files and logs, not stuffed in the prompt.

Memory and search. This decides what knowledge reaches the model. It covers injecting project context (through files like AGENTS.md) and searching the web or MCP tools (like Context7) for anything newer than the model’s training cutoff. This is also where the “write it down, read it later” trick lives. The next frontier is longer memory that lasts weeks or months, so an agent can get up to speed by reading its own past logs.

Long-horizon execution. To keep working past a single window, you combine the pieces above: files and Git to save progress across restarts; “Ralph Loops” that re-feed the prompt into a clean window to force the agent to continue; and planning plus self-checking. HumanLayer calls the key idea back-pressure: an agent succeeds when it can check its own work — but that checking has to be cheap and quiet, or it eats up the window too.

Configuration and platform

Above the raw parts sits configuration, and this is where most users actually shape their harness. According to Addy Osmani, the two highest-leverage knobs are the config file and the tool set.

Keep the config file short. Treat AGENTS.md (or CLAUDE.md) like a pilot’s checklist, not a style guide. HumanLayer keeps theirs under about 60 lines. A study from ETH Zurich even found that most of these files were useless or worse — which argues against auto-generating them and for keeping them tight. Every line should exist because something actually went wrong. Otherwise it’s noise.

Use few, focused tools. Ten sharp tools beat fifty overlapping ones. Too many tools confuse the model and waste context on descriptions — HumanLayer calls this pushing the model into “the dumb zone.” A good habit: prefer command-line tools the model already knows (like Git or Docker) over custom MCP servers. HumanLayer even built a Linear CLI instead of an MCP server, just to save tokens. There’s a security angle too: tool descriptions are fed to the model as trusted text, so a malicious description can hijack the agent. Vetting tools isn’t just tidiness — it’s a safety boundary.

Hooks are the enforcement layer. They’re scripts that run at fixed moments — before a tool call, after an edit, before a commit — and they give you guaranteed behavior from an otherwise unpredictable agent. Advice can be ignored; a pre-commit hook cannot. The rule of thumb: success is silent, failures are verbose. A type-check hook should print nothing when it passes and only speak up when it fails, so it doesn’t waste the agent’s context.

Sub-agents are widely misunderstood, so this one needs care. The tempting idea is to give each sub-agent a role — a “frontend engineer,” a “backend engineer.” HumanLayer is blunt that this doesn’t work. The real reason to use a sub-agent is context control. A sub-agent runs a task in its own separate window and hands back only the answer. All the messy middle — failed tries, tool noise — never reaches the main agent. deepset confirms this “context firewall” idea. The other reason is cost: let an expensive model run the show while cheaper models do the grunt work. deepset takes this further with per-step routing — a strong model for planning, a small fast one for repetitive checking — and calls it standard practice now, not a fancy experiment.

Finally, the platform trend: Harness-as-a-Service. The industry is moving from LLM APIs (which just return an answer) to harness APIs (which give you a whole runtime) — the Claude Agent SDK, Codex SDK, and OpenAI Agents SDK are examples. You configure these along four dials: system prompt, tools, context, and sub-agents. deepset sees the same shift from the company side: once several teams depend on one harness, it needs access control, secrets management, isolation, and audit trails that prove certain actions always required human sign-off. Their idea of “shared agent infrastructure” — memory, skills, and protocols maintained by the whole org — is the business case: build a good harness once, share it everywhere.

Building your own harness

Birgitta Böckeler gives the clearest framework for the harness you build around a coding agent. Every control you add can be sorted two ways.

First, is it a guide or a sensor?

  • Guides act before the agent works — system prompts, how-to docs, conventions. They raise the quality of the first attempt.
  • Sensors act after the agent works — tests, linters, reviews. They let the agent catch and fix its own mistakes.

You need both. Guides alone means the agent repeats mistakes nobody checks for. Sensors alone means it never gets steered in the right direction to begin with.

Second, is the control computational or inferential?

  • Computational controls are exact and fast — tests, linters, type checkers. Cheap and reliable. These are your backbone.
  • Inferential controls use a model to judge — AI review, “LLM as judge.” They handle fuzzy questions that exact checks can’t, but they’re slower, pricier, and less predictable.

The rule: use exact checks wherever they work, and save the model-based judges for things that truly need judgment. You can make the judges steadier with a few calibrated examples.

flowchart TB
    G[Guides — act before<br/>prompts, docs, conventions]
    A((Agent acts))
    S[Sensors — act after<br/>tests, linters, reviews]
    G --> A
    A --> S
    S -->|failures feed back<br/>into the guides| G

So your real job isn’t to review every output. It’s to improve the harness — this is the steering loop. When a problem keeps happening, you fix a control so it can’t happen again. Osmani calls this a ratchet: add a rule only after a real failure, and remove it once the model no longer needs it. Hashimoto’s test is simple — set things up so the agent never makes that mistake again.

deepset spells the loop out: run on real tasks, watch for failures, sort each failure by type, fix the right layer, repeat. Two things make it work: tracing (without logs, you’re just guessing) and a sorting step so each fix lands in the right place.

flowchart TB
    RUN[Run on real tasks]
    OBS[Watch failures<br/>using traces]
    CLASS[Sort each failure by type]
    UPDATE[Fix the right layer]
    RUN --> OBS
    OBS --> CLASS
    CLASS --> UPDATE
    UPDATE --> RUN

That sorting step deserves its own list, because fixing the wrong layer wastes time. deepset names four failure types:

FailureWhat you seeWhat to fix
ContextMissing the right info at the right time — made up a schema, forgot the goalRetrieval, memory, context management
ConstraintHad the info but did something wrong — edited files it shouldn’t, called a needless toolA guardrail — permission limit, linter rule, scope boundary
VerificationProduced something that looks right but isn’t, and nothing caught itA feedback loop — tests, a validator, a second model as reviewer
PlanningTook the wrong approach entirely — one step where five were needed, got stuck in a loopOrchestration — break it up, use sub-agents, detect loops

deepset’s guardrail advice is to constrain more, not less: start strict, loosen as you gain confidence. And all of this only works if you can see what happened — no tracing, no real diagnosis.

There’s a second way to sort things, this time by what quality you’re trying to protect. Böckeler describes three areas, from most solved to least:

  1. Maintainability — the easy one. Exact checks reliably catch duplication, complexity, and low test coverage.
  2. Architecture fitness — checking that the code keeps the shape you want, using “fitness functions.”
  3. Behaviour — whether the code actually works correctly. This is the hard, unsolved one. Today’s approach leans too much on AI-written tests that aren’t good enough yet.

The evidence is concrete: out of the box, “Claude is a poor QA agent” — it flags a real problem and then talks itself into approving anyway. This is exactly where a human should step in. Even a great harness only partly captures the judgment, accountability, and taste a person brings. The goal isn’t to remove the human — it’s to point their attention where the automated checks still can’t judge for themselves.

One more practical note: not every codebase is easy to harness. Strong typing, clear module boundaries, and good frameworks make a codebase easier for agents to work in — Ned Letcher calls these “ambient affordances.” New projects can build them in from the start. Old, messy codebases are the hardest — and, frustratingly, that’s exactly where a harness would help most.

Multi-agent patterns and grading

Anthropic’s Prithvi Rajasekaran offers the most hands-on lessons, from building long-running apps.

The main pattern is generator/evaluator: one agent builds, a separate agent judges. Splitting the doer from the judge works because agents are bad at grading themselves — they praise their own so-so work. The evaluator scores the output against clear standards, and its feedback drives the next round (they saw 5 to 15 rounds). For app-building, the evaluator got the Playwright tool so it could click through the live app like a real user.

flowchart TB
    P[Planner<br/>turns a short prompt into a spec]
    G[Generator<br/>builds one feature]
    E[Evaluator<br/>grades it, clicks through the app]
    DONE[Done<br/>spec satisfied]
    P --> G
    G --> E
    E -->|feedback,<br/>repeat 5–15x| G
    E --> DONE

To grade fuzzy output like visual design, you have to make quality gradable. The team used a four-part rubric, shared by both the builder and the judge: design quality (does it feel like one coherent thing?), originality (real choices vs. generic “AI slop”), craft (typography, spacing, contrast), and functionality (is it usable?). They weighted design and originality more, since the model was already good at craft and functionality. Giving the judge a few graded examples kept its scores steady. The method has a hard limit, though: it can’t grade what the model can’t sense — “Claude can’t actually hear,” so musical taste was out of reach.

Scaling this up used three agents: a planner that turns a short prompt into an ambitious spec, a generator that builds one feature at a time, and an evaluator that clicks through and grades. Two things kept them coordinated: a sprint contract (they agreed on what “done” meant before any coding) and communication through files (the filesystem as shared workspace). The payoff was dramatic — a solo run made a broken game ($9, 20 minutes) while the full harness made a working, polished app ($200, 6 hours). The lesson: an evaluator is worth its cost only when the task is beyond what the model can do alone.

This also settles the sub-agent debate. HumanLayer says don’t give sub-agents roles; Rajasekaran gives them jobs (plan, build, judge). Both are right. Those jobs earn their keep not because “planner” is a personality, but because each one creates a clean context boundary. The value is the boundary, not the label.

Where this is heading

Since harnesses are built to patch a model’s weaknesses, better models must make some of those patches pointless — and that’s exactly what people report.

Models and harnesses are increasingly built together: products like Claude Code and Codex are trained with their harness in the loop. That helps, but it also risks overfitting — the best harness for a model isn’t always the one it trained with. You can even see this in small things, like a model preferring one edit format over another.

Rajasekaran’s practical takeaway: every harness part assumes some model weakness, and that assumption can expire. As Opus 4.5 became 4.6, his team removed parts they no longer needed — context resets and the sprint construct both went, because the newer model could plan on its own and no longer rushed to finish. The guiding rule: find the simplest thing that works, and add complexity only when you must. The subtle point is that the set of useful harnesses doesn’t shrink as models improve — it shifts. So whenever a new model lands, revisit your harness. Harness engineering will stick around as a skill, the same way prompt engineering did.

deepset sums up the direction as “from static scaffolding to dynamic governance”: longer memory that spans weeks, shared harness infrastructure across teams, and standard protocols (like MCP) that turn the tool layer into a commodity. The hard open problems are clear too: running hundreds of agents at once, agents that fix their own harness, and assembling tools and context on the fly.

The short version

  • Agent = Model + Harness. Once the model is good enough, the harness is where your wins come from. Check the harness before blaming the model.
  • Decide the behavior, then build the part. Every harness piece exists to cover a specific model weakness — memory, skills, or protocol.
  • Build the feedback loop first. Logging, sorting failures, and turning each real mistake into a lasting rule matter more than any one clever feature.
  • Use exact checks; ration the model-based ones. Tests and linters are your cheap, trustworthy backbone. Save “LLM as judge” for things that truly need judgment.
  • Sub-agents are context boundaries, not personalities. The win is the firewall and the cost savings, not the job title.
  • Harnesses are living things. As models improve, old assumptions expire — so revisit your harness with every model upgrade.

The one thing the experts still argue about — whether context engineering contains harness engineering or the other way around — is less a problem to solve than a sign of how young this field is. But everyone agrees on the destination: reliable agents come from engineering the system, not from waiting on the model.

Sources