Harness Engineering: The Real Leverage Is Around the Model
The model is the one part you do not control. You rent it, it updates on someone else's schedule, and for the length of a project you treat it as a black box. Everything that decides whether an agent is actually useful sits around that box: what it knows, what it can touch, how it loops, and how it proves its work. Engineering that surrounding environment is harness engineering, and it is where most of the leverage in agent systems really lives.
Hold the model fixed
Start from an uncomfortable fact: you cannot change the model. The frontier lab ships a new version when it wants to, deprecates the old one when it wants to, and your careful tuning resets each time. So stop treating the weights as the variable. Pick a capable model and coding agent, hold them constant for the length of a project, and put your engineering effort into the environment you do control.
This is not resignation. It is where the work moves. When the model is a fixed input, the interesting questions become concrete: what does the agent need to know to do this job, what does it need to be able to do, and how do you know it did the job correctly. Those three questions map to context, tools, and proof, and none of them are prompt tricks.
Two levers: context and tools
A fixed agent has exactly two external levers. The first is context, everything the agent can read: your code, your records, your conventions, the current state of the system it is operating. The second is tools, everything the agent can do: run a command, query a database, open a pull request, deploy a service. Every improvement you make to an agent is really an improvement to one of these two levers, or to the loop that operates them.
Model weights carry general knowledge. They do not carry the private, changing detail that a specific job depends on: the current operational state, your local vocabulary, your quality bar, the exception history, who is allowed to approve what. That private layer is the actual subject of harness engineering. The job is to make it available to a capable worker as retrievable context and bounded capability, on demand, at the moment it matters.
Context is a graph you route, not a prompt you stuff
The common failure is to pour everything into one giant prompt. That trades one problem for a worse one. A long context window is expensive, and past a point the agent attends to the wrong parts of it. The better shape is a large navigable store paired with a small active working set.
Think of it as a graph. Root guidance sits at the top and routes to the right sources. Runbooks capture how a recurring workflow actually runs. Examples show what good output looks like in this codebase. Checks surface a constraint at the moment it becomes relevant, not as a wall of rules up front. The agent traverses that graph per task and pulls only the nodes it needs, which keeps the working set small and the signal high.
The best place to store much of this is the repository itself. Code the agent reads becomes prompt material. Types, tests, repeated patterns, and completed migrations all teach the agent what your standards are without anyone writing them down as prose. A repository that is legible to a human is legible to an agent, and the same investment pays both readers.
Tools are only real when they are legible
A tool that exists in an API is not yet a capability the agent can use. A capability becomes real only when the agent can move through the whole loop around it: discover that the tool exists, choose it over the alternatives, call it with the right arguments, read and interpret what came back, recover when the call fails, and verify the effect against the real system rather than against its own assumptions.
Most flaky agents are flaky here. The tool returns an ambiguous error, or a success shape that hides a partial failure, and the agent cannot tell the difference. Legible tools return honest, structured results and fail in ways a reader can act on. This is the same discipline that makes a good internal API, applied to a non-human caller who will not file a bug report.
Reliability lives in the loop
An agent does not answer once. It runs a loop: form a plan, take an action, observe the result, adjust, and repeat until the work is done or a limit is hit. Reliability is a property of that loop and the checks inside it, not of the sentence you opened with. A strong prompt into a weak loop still drifts. A modest prompt into a loop with real validation and clear stop conditions holds up.
So spend your effort on the loop. Add a check that runs after each action and feeds its result back in. Give the loop honest stop conditions so it does not spin. Make failures observable, because an agent loop you cannot trace is an agent loop you cannot fix. Once you frame it this way, the hard parts of an agent look exactly like the hard parts of any distributed system: retries, timeouts, idempotency, and state.
Model the work as a graph of durable units
That framing points somewhere specific. If an agent loop is a distributed system, model it like one. A job is not a single call. It is a graph of durable units of work with edges between them, some running in order, some in parallel, each with its own retries and state.
One durable way to model it uses three primitives: functions, triggers, and workers. A function is a unit of work. A trigger is an edge that fires it, from an event, a schedule, or another function. A worker is a fixed capability the graph can call. Express agent work this way and state, retries, ordering, and observability come from the runtime instead of from prompt instructions asking the model to remember. This is the sense in which the harness is really the backend: the parts that make an agent reliable are backend parts, and they belong in a runtime, not in a system prompt.
The payoff is that known work can move into a continuous loop. Once an outcome has clear signal, real proof, and the right authority, it does not need a human to kick it off every time. It becomes a repository-owned loop with durable state and a retirement condition, and it keeps itself aligned with the current world. Open-ended product invention stays in the foreground where judgment belongs. Settled, provable work runs in the background.
Encode the rules, bound the authority, prove the result
Three practices keep the whole thing honest.
Encode requirements, do not describe them. Reliability, security, performance, and compatibility are not vibes you put in a prompt. They belong in the repository as executable constraints: a type that makes an invalid state unrepresentable, a test that fails when a rule is broken, an example the agent can copy. The agent then recovers what good looks like from the code rather than from your patience.
Separate authority from capability. Let the agent act broadly where actions are cheap and reversible, so it stays fast. Make the consequential grants, the ones that spend money, touch production, or ship to users, scoped, revocable, audited, and recoverable. Capability is what the agent can do. Authority is what it is allowed to do. Keep them as separate contracts.
Match the proof to the claim. A green unit test proves one narrow assertion and nothing more. If the claim is that a user journey works, the proof is a browser run. If the claim is that a service is healthy in production, the proof is a canary and live signals. Persistent memory of what was accepted before helps here too: an outcome an agent has already proven should not have to be re-litigated on the next run.
The harness is the product
The model stays fixed. The environment around it, context, tools, loop, and proof, is what you build, and it is what makes agents reliable. Treat that environment as a system you engineer, not a prompt you tune.
Read: stop agents building the wrong thingFeedback becomes infrastructure
The last practice is what makes a harness improve over time instead of decaying. Every accepted change, every correction, every incident, and every failed run is evidence about a missing piece of the environment. The move is to promote that lesson into the earliest place that can own it: a new check, a new example, a boundary, a tool that removes a class of mistake.
Do this consistently and your team's judgment starts to accumulate in the system itself. The agent that runs next month starts from everything the agent learned this month, because the learning lives in context, tools, and checks rather than in one person's head. That is the quiet reason harness engineering compounds. You are not only getting better output from a model. You are building an environment that carries hard-won judgment forward and hands it to the next run already equipped.
None of this requires a bigger model. It requires taking the environment as seriously as we once took the code, because for an agent, the environment is the code.
FAQ
What is harness engineering?
Harness engineering improves what an AI agent produces by shaping the environment around it rather than changing the model. You hold the model and coding agent fixed and engineer the two external levers, context and tools, plus the loop that runs them and the proof that closes the work.
How is it different from prompt engineering?
Prompt engineering tunes the words in one request. Harness engineering builds the whole environment a request runs inside: retrievable context, real tools, an execution loop, checks, authority boundaries, and evidence. A prompt is one input to a harness, not a replacement for it.
Do I need to fine-tune a model?
Usually not. For most institutional work, fixing retrieval, giving the agent legible tools, tightening the loop, and encoding your requirements as checks moves quality more than a fine-tune, and it survives the next model upgrade.
What is an agent harness?
The runtime and context around a model that turns a sparse instruction into reliable work: how the agent retrieves what it needs, which tools it can call, how the plan-act-observe loop runs, what authority it holds, and how it proves the outcome.
Why do people say the harness is the backend?
Because the parts that decide whether an agent is reliable, retries, state, timeouts, tool execution, and proof, are backend concerns. Model agent work as functions and triggers with durable state and the harness and the backend become one system.