July 2026No. 0110 min read

Harness engineering is the system around the model

Claude Code and Codex look like a smart model typing in your terminal. Build real agent workflows for a while and you find the model is one component in a much larger machine, and most of what reads as magic is that machine doing its job. This is my map of it: ten primitives, each one added where the previous one hit its limit.

One caveat before the map. None of these primitives are standardized, and nobody has agreed on the names. This is my way of carving up what systems like Claude Code and Codex are doing under the hood. Other people slice it differently.

I’ve also argued elsewhere that the moat is moving into the harness. This post is the mechanical companion to that claim: what the harness actually is, one primitive at a time.

A model, alone

The smallest version of this stack is a bare model. You send a prompt over an API, you get text back. That alone is useful. In the early ChatGPT days that’s what most of us did: craft a good prompt, get back an explanation, a plan, a decent email.

The boundary is just as plain. The model sees what’s in the prompt plus whatever its training already contains. If your repo, your ticket, or last night’s incident is missing from that input, the model guesses, and we have a word for confident guessing: hallucination. So before asking whether the model is smart, ask what we handed it to work with.

PROMPT TEXT MODEL PROMPT IN / TEXT OUT sees only the prompt and what training already contains
Fig. 01 · A bare model: prompt in, text out · slide 2 of the deck

Model, runtime, harness

The word agent gets thrown around for everything now. OpenAI’s Agents SDK pins it down usefully: a model configured with instructions and tools, placed in an environment it can act on. The loop it runs, reason, act, observe, repeat, is the agentic loop; ReAct is the classic named version of that pattern.

That gives us three things worth keeping separate, because mixing them up is where a lot of agent arguments go sideways. The model is the reasoning engine. The runtime is the loop where the model observes, decides, and calls tools. The harness is everything around that loop.

HARNESS · the system around the loop RUNTIME · observe · decide · act MODEL the reasoning engine is the smallest piece of the machine
Fig. 02 · Model, runtime, harness: three layers that usually get blamed as one · slide 4 of the deck

When an agent fails, we usually blame the model first. Sometimes that’s fair; models genuinely differ in capability. But at least as often, one of the layers around the model didn’t support it. The rest of this post walks those layers.

Instructions

The first primitive is instructions. You tell the model who it is, what kind of work it does, the tone, the constraints, the coding style, the review rules, the things it should never do. AGENTS.md and CLAUDE.md are this primitive. So are system prompts, custom instructions, repo rules, and Cursor rules.

They earn their place by moving repeated guidance into the environment. You stop typing “use pnpm, not npm” every session; the harness loads it for you.

But instructions are passive. They can say “follow the project conventions”; they can’t discover those conventions. They can say “be careful with migrations”; they can’t open the migrations folder and look. A long instruction file feels like control because it’s long, but length is not runtime enforcement. Instructions help the model behave better without handing it the world.

Context, delivered and managed

The second primitive is context delivery: the mechanism that gets material in front of the model. Every time you @-mention a file, attach the failing test, or paste a stack trace, you’re using it. This is where a bare model and an agent inside a harness stop resembling each other. Ask a model to fix a bug with no files and you get the generic shape of a fix. Hand it the source file, the failing test, and the trace, and you have a very different animal.

But dumping context is not context engineering. A repo is too big for the window. A production incident has logs, dashboards, runbooks, and a Slack thread. Pour all of that in and the prompt just gets noisier. The window is finite, and even inside the window attention is not free. Wrong context can be worse than missing context, because it hands the model a plausible distraction.

repo logs chat history docs CONTEXT WINDOW the plausible distraction
Fig. 03 · Raw context pours into a finite window; the wrong chunk costs more than the missing one · slide 8 of the deck

So the question changes from “can we provide context” to “who decides what context matters right now”. That’s the third primitive, context management: retrieval and re-ranking, session summaries, compaction, prompt caches. The names keep changing while the job stays the same: protect the model’s attention.

Tools, and where they run

Context management makes the agent smarter inside the conversation, but the agent is still a talker. It can identify the file, propose the command, say the next step is to run the failing test. When the work requires action, the model needs a way to ask the outside world to do something.

That’s the fourth primitive, the tool interface. A tool has a name, a description, an input schema, sometimes an output schema, and the model decides to call it with specific arguments. That’s the model’s side of the contract. MCP lives at this layer; it standardizes how services expose tools so any agent can discover and call them. If you’ve used OpenAI function calling, Anthropic tool use, or plain bash and grep inside an agent, you’ve used this primitive.

The schema answers what to call, and says nothing about the operational questions. Say the model correctly decides to run the test command. Where? On my laptop, in a container, in a cloud sandbox? With network access? With secrets? With write access to the whole repo? And how much do we trust what comes back? Tools fail, return messy text, fetch web pages that carry prompt injection, get partial data from APIs.

The fifth primitive answers those questions: the execution environment, where tool calls become bounded reality. Filesystem scope, network policy, credentials, sandboxes, containers, worktrees, browser profiles. Whole companies exist for this layer, Daytona and E2B among them, and Docker has sandboxes aimed at the same problem. Codex running each task in an isolated sandbox reads like a deployment detail until you see it as harness design. This is also where trust becomes mechanical: instead of telling the model “please do not touch secrets”, the environment never hands them over.

Work that survives the turn

An environment gives the agent a place to work, but one clean sandbox is not enough for long work. Real tasks pause, resume, fork, and fail halfway. If the only record of progress lives inside the model’s context, a crash or a compaction erases it.

The sixth primitive is durable state: the workbench that survives the current turn. Plan files, checkpoints, git branches with changes, test logs, session summaries, memory stores. The split with context management matters here: context management decides what enters the model right now, and durable state keeps facts, artifacts, and progress alive outside the prompt. The storage format matters less than the property it buys you: progress you can inspect outside the model’s current attention.

State preserves work without coordinating it. A plan file says what should happen; it doesn’t decide when to retry. A log records that a command failed; it doesn’t decide whether a human should approve the next step. Once a workflow has a lifecycle, you need the seventh primitive, orchestration: lifecycle hooks, retries, approval gates, heartbeats, step ordering, model routing. Claude Code hooks are a concrete example, and agent frameworks expose lifecycle events for the same reason: real systems need places to intercept behavior. This layer is where agent work starts looking less like chat and more like a runtime.

Delegation, and keeping delegates consistent

Orchestration helps one agent do more, but one agent still has one attention stream, and real work branches. Mid-task you want someone to go research a source, inspect a repo, review a diff, verify a page rendered. Run all of that serially and two things happen: the process gets slow, and the context we just spent three primitives protecting gets crowded.

The eighth primitive is subagents. The harness splits work into bounded loops: one explores the codebase, one reviews the diff, one verifies sources, and the main agent keeps responsibility for integrating the results. OpenAI’s Agents SDK documents two patterns worth knowing, agents as tools, where a manager keeps control and calls specialists, and handoffs, where the conversation itself moves to the specialist. Either way, a subagent is a model with a narrower job, narrower context, and usually narrower tools. That narrowness is the benefit: each worker reasons over a smaller surface.

Delegation then creates its own failure mode. If every subagent invents its own process, you get parallel inconsistency, and it feels faster right up until everyone comes back with a different interpretation of the job. That’s what the ninth primitive fixes. Skills are reusable procedures for recurring work: how to review a PR, how to run browser QA, how to publish to a specific repo. Slash commands, playbooks, runbooks, recipes: all the same primitive. A good skill encodes when to use it, what inputs it expects, what steps to follow, and which tools to prefer. Skills move repeated expertise from “remember to do that thing” into a named capability the harness can invoke.

Receipts

Skills make work repeatable. Whether the work succeeded is a separate question. A skill can say “run the tests”; did they pass? It can say “check the browser”; was the screenshot clean? The procedure is necessary and it’s still not evidence.

The tenth primitive is the proof layer, and it has three faces. Verification asks for receipts: tests, builds, type checks, lint, browser screenshots, evals, primary sources for research work. The agent says it’s done; the harness asks it to show the work. You don’t trust the final sentence because it sounds confident.

I still remember the first time an agent inside a harness finished a coding task and said, unprompted, “now let me run the tests.” This was before skills existed, and I credited the model. Part of that was the model. A big part was a harness written to put verification in front of the model at the right moment, and for a long time that behavior was a real differentiator between tools that people kept attributing to model smartness.

Verification tells you something failed. It rarely tells you why. A test fails: was the context wrong, did a tool return bad output, did the agent edit the wrong file, did a subagent miss a constraint? Without a run record, debugging is guesswork. So the second face is observability: traces, tool-call timelines, logs, cost, latency, prompt versions, approval events. The interesting bug usually sits three tool calls before the final message, where the agent searched for the wrong symbol or trusted the wrong page. You can’t improve what you can’t inspect.

The third face is what makes the whole thing compound: harness evolution, failures becoming infrastructure. A repeated context miss becomes a retrieval rule. A bad tool result becomes a stricter schema. A dangerous command you caught in a trace becomes a permission gate. A missed edge case becomes a test, a recurring correction becomes a memory, a repeated workflow becomes a skill. It’s the postmortem loop applied to agents: change the system so the same class of failure has a harder time coming back. Without this layer every session re-teaches the same lesson; with it, the harness compounds.

RUN IT BREAKS same class, new wrapper CHANGE THE SYSTEM gate · schema · test · skill · memory NEXT RUN starts from a better place
Fig. 04 · The evolution loop: each failure changes the system the next run starts from · slide 26 of the deck

The whole machine

Put the ten primitives together, then go back to the reverse-engineered Claude Code architecture diagrams that circulated a while back. A caveat first: those are community analyses of leaked source, so treat them as reference sketches, not official Anthropic documentation. But after this walk, the diagram stops reading as random complexity. Session manager, permission gate, context compressor, memory store, skill registry, MCP runtime, tool dispatch, subagent spawner, worktree isolation: each box maps onto a primitive, and each one is there for a reason. At some level this is how Claude Code works, how Codex works, and how Gemini CLI works. That’s the payoff I wanted you to have.

01 · instructions 02 · context delivery 03 · context mgmt 04 · tool interface 05 · execution env 06 · durable state 07 · orchestration 08 · subagents 09 · skills 10 · proof + learning AGENT RUNTIME observe · decide · act
Fig. 05 · The full blueprint: ten primitives around one agent runtime · slide 28 of the deck

The test I use now

When an agent fails, asking whether the model was good enough is only the first question. Walk the layers. Was an instruction missing? Was the context wrong? Did memory go stale? Was a tool schema vague? Did the command run in the wrong environment? Did the workflow need state that didn’t survive? Did it need orchestration? Should the work have been delegated? Was there no skill for a job you’ve clearly done ten times? Was there no verification, no trace to look inside? And did we learn anything from the last failure?

Most of the time, the model did not fail because it was dumb. It failed because our definition of done got bigger than the harness.

Harness engineering is how agents move from clever demos to dependable systems. The model still matters, and better models keep raising the ceiling. Reliability, though, gets built in the system around the model, and building that system is where I’m spending my time.

This post also exists as a 28-minute video deep dive, with the same diagrams drawn live. Watch it on YouTube.

Written by Ankit Desai. New posts ship every few weeks, each with a video edition.