# Agent harnesses, explained

*Published 2026-06-02 · Anurag Dhungana*

> Agent harnesses are the body around the model: tools, memory, approvals, logs, adapters, and stop conditions that turn reasoning into reliable work.

People use the word "agent" for almost everything now.

Sometimes they mean a chatbot with tools. Sometimes they mean a coding assistant. Sometimes they mean a workflow with a model call buried inside it. The word has gotten stretched enough that I think it needs a cleaner frame.

The frame I keep coming back to is simple:

The model is the brain.

The harness is the body.

The model reasons. The harness lets that reasoning touch the world.

That distinction sounds obvious, but it changes where you look when an agent fails. If the agent gets lost, the answer is not always "use a better model" or "write a better prompt." A lot of the time the answer is: the harness did not give the model the right tools, state, memory, visibility, or stopping condition.

That is the part I keep running into in my own projects.

Shrimp is a harness around an LLM. Coop is a portable format for agent definitions. Switchboard is a harness around chat platforms. Content Machine is my local system for turning Codex/Claude sessions, repo work, notes, and drafts into article ideas.

Different names.

Same pressure.

The interesting part is usually not the model, or the API call, or the first happy-path demo.

The interesting part is the harness around it.

![prompting to context to harness](https://media.anuragd.me/blog/faeba10b-2b5c-46ed-bcab-548a6971a13f.png)

## Prompting gets you started

The first layer is prompting.

You tell the model what you want: write this email, summarize this file, fix this bug, return JSON, use this tone.

For small tasks, that works. The instruction is clear, the context fits in the prompt, and the answer comes back in one shot.

The problem starts when the task stops being one shot.

Real work has steps. The model needs to inspect files, choose tools, compare results, remember what happened earlier, and sometimes ask before doing something risky. At that point, the prompt still matters, but it is not the system.

It is just one input.

## Context helps, until it becomes the problem

The next layer is context engineering.

Instead of hoping the model guesses correctly, you give it the right stuff: docs, files, prior messages, tool outputs, user preferences, examples, constraints.

This is a big jump. A plain prompt with the right context usually beats a clever prompt with no context.

But then a new problem shows up. Something has to decide what context gets loaded.

Should the agent read the README or the test file? Should it search memory or inspect the current diff? Should it trust an old note or re-check the code? Should it keep going after a tool error or stop and ask?

Those decisions do not live in the prompt. They live in the harness.

This is one of the things I learned building Content Machine. Asking an LLM for post ideas was the wrong layer. The useful move was making a system that knew where the work lived: Codex sessions, Claude memories, repos, drafts, queues, published logs. Once the right material was in the room, writing got easier.

Not because the prompt was magical.

Because the harness found the evidence.

## The harness is the loop

Most agents have a loop somewhere inside them.

![agent harness loop](https://media.anuragd.me/blog/50e37337-bb6b-447a-9b44-2314e84b4d0e.png)

Look at the task. Pick the next action. Call a tool. Read the result. Update state. Decide whether to continue.

That loop is easy to draw and annoying to build.

What tools are available? What do their inputs look like? What happens when one fails? Which actions can run automatically? Which ones need approval? Where does memory live? How does the user see progress? What counts as done?

If you do not answer those questions, the model has to improvise. Sometimes that works. Often it produces the familiar agent failure mode: a confident loop of half-correct actions that looks busy but never actually lands the task.

Shrimp came from running into this over and over.

I kept building agents where the model was not the hard part. The hard part was everything around it: the ReAct loop, the event bus, the capability registry, the approval gate, the dashboard, memory, sub-agents, browser control, app integrations.

Once that was clear, Shrimp became the obvious shape: keep the model swappable, keep the capabilities pluggable, and make the core loop visible.

The model thinks.

The harness lets it act.

## The environment has to be legible

The OpenAI harness engineering post clarified something for me: a good harness does not just give agents tools. It makes the environment legible.

That word matters.

If the agent cannot see a fact while it is working, that fact basically does not exist. A Slack thread, a Google Doc, a design decision in someone's head, a random note from last week: all of that may be true, but the agent cannot use it unless the harness exposes it in a form the agent can inspect.

This is why OpenAI talks about repository knowledge as the system of record. Their `AGENTS.md` is not the encyclopedia. It is more like a map. The deeper knowledge lives in structured docs, plans, references, quality notes, and checks the agent can actually navigate.

That matches what I have been learning in smaller systems.

Content Machine works better when everything lives in one Obsidian folder. Coop works because agent definitions live in Git instead of being trapped in a platform dashboard. Shrimp works better when tool calls, events, and approvals are visible instead of hidden inside a final answer.

The harness turns hidden work into something the agent can read.

![make work legible](https://media.anuragd.me/blog/b083ed2d-f146-4b74-872b-18ff37338070.png)

## Tools need contracts

It is tempting to think of tools as simple functions.

The model calls `read_file`, `search_web`, `send_email`, `run_tests`, whatever. Function in, result out.

That is too loose.

For an agent, a tool needs a contract. The model needs to know what the tool does, what inputs are valid, what the output means, and what failure looks like. More importantly, the harness needs to know what kind of action this is.

Reading a file and sending an email are not the same category of thing.

Searching docs and deleting data are not the same category of thing.

So the harness needs permission levels. Some tools can just run. Some should run but notify the user. Some should ask first. Some should not exist in that environment at all.

Coop is this idea from another angle.

It does not execute agents. That is the point. Coop is about the file format and validation layer: agents, triggers, tools, skills, environments, vaults, memory stores, and portability rules. It lets the definition live in Git instead of disappearing into a platform dashboard.

That sounds boring until you need to migrate something.

Then boring becomes the whole game.

If an agent definition has no schema, no validator, no warnings for lossy export, and no stable source of truth, you do not really have an agent definition. You have a screenshot of some settings somewhere.

The harness makes the contract visible.

## Adapters keep the mess out of your head

Switchboard taught me the same lesson in a less agent-shaped place.

Discord, Slack, and Telegram all have messages. They all have replies. They all have events. They all have annoying little differences that leak into your code if you let them.

Switchboard is basically a harness around those platforms. One Bot API on top, adapters underneath.

Your handler should not care whether the message came from Discord or Slack. It should care about the user, the message, the reply, and the conversation.

The rest belongs in the adapter layer.

This is the part I keep accidentally caring about.

Where does the messy outside world end?

Where does the clean interface begin?

That boundary is usually the product.

## The pattern underneath

Shrimp, Coop, Switchboard, and Content Machine are not the same project.

But they rhyme.

Each one sits around a messy capability and gives it structure.

Shrimp sits around an LLM and gives it tools, memory, approvals, and visibility.

Coop sits around agent definitions and gives them a portable file format, validation, and migration paths.

Switchboard sits around chat platforms and gives them one API.

Content Machine sits around my own work and gives it queues, evidence, and a publishing loop.

The repeated lesson is simple:

The hard part is rarely making something happen once.

The hard part is making the shape around it stable enough that you can keep using it.

That means interfaces.

It means normalization.

It means logs.

It means explicit failure states.

It means approvals.

It means boring names for things that would otherwise stay fuzzy.

It means knowing what is inside the core and what is an adapter.

That last one matters a lot.

If everything is core, the system becomes fragile.

If everything is a plugin, the system has no opinion.

Harness engineering is deciding where the boundary goes.

## Memory is not a bigger prompt

Memory gets hand-waved a lot.

People talk about it like you can stuff more text into the context window and call it a day. That works for demos. It breaks fast in real use.

An agent has different kinds of memory.

There is the short-term state of the current task. There are long-term facts about the user. There is project memory: how this repo works, what commands are safe, what past decisions matter. There is procedural memory: the way the agent learned to do a kind of work.

The harness decides where those memories live and when they get pulled back in.

It also has to treat memory with suspicion. Old memory can be stale. Summaries can flatten the important detail. A preference can be true in one project and wrong in another. If the agent cannot tell where a memory came from or when it was last checked, it will eventually make a very confident mistake.

Good memory needs provenance.

Bad memory is worse than no memory.

This is why I ended up making Content Machine live in one Obsidian folder. I had a split setup for a bit: some automation files in Development, some strategy in Obsidian, old paths hanging around as compatibility glue. It worked technically, but it felt wrong.

If there are two homes, there is no home.

So I collapsed it into one folder and deleted the symlink. That is not glamorous, but it is exactly the kind of harness decision that makes a system trustworthy.

## Observability is not optional

If an agent does ten steps and only shows you the final answer, you do not really know what happened.

Maybe it read the right file. Maybe it skipped the only file that mattered. Maybe a tool failed and it guessed. Maybe it got lucky.

For toy tasks, that might be fine.

For real work, it is not.

A good harness shows the path: tool calls, outputs, errors, approvals, retries, and changes in direction. Not because logs are pretty. Because inspection is how trust gets built.

You cannot trust an agent you cannot audit.

This is another place where the OpenAI post was useful. Their team did not only give Codex a repo. They made the app, browser, logs, metrics, traces, and local dev environment available to the agent. That is a very different thing from pasting errors into a chat.

It means the agent can observe the system directly, make a change, run the app, inspect the result, and loop.

That is harness engineering.

Not a better prompt. A better feedback loop.

Addy's "Orchestration Tax" article describes the human side of the same problem. Starting more agents is cheap. Closing the loop on their work is not. If every agent output routes straight into your brain, you become the single-threaded bottleneck.

A useful harness does not remove judgement. It protects it.

It makes the agent prove the boring parts first: tests, screenshots, traces, structured diffs, reproducible steps. Then your attention goes to the part that actually needs a human.

![orchestration tax and harness backpressure](https://media.anuragd.me/blog/ba44a024-25ae-404f-928f-67b7e3cbee99.png)

## Stopping is part of the system

One of the least glamorous parts of agents is stopping.

When is the task done? When should the agent retry? When should it ask for help? When should it give up?

If the harness does not define this, the model guesses. That is how you get agents that keep searching after they already found the answer, or keep editing after the fix is done, or declare success because they produced a plausible final message.

The harness can make the boundary explicit.

Maybe tests have to pass. Maybe a screenshot has to be generated. Maybe a destructive action needs approval. Maybe the agent must produce a specific artifact before it can say it is finished.

The model still reasons. The harness decides what "done" means.

This is also where entropy shows up.

Agent systems produce stuff quickly. Some of it is good. Some of it is weird. Some of it is locally fine but creates long-term drift. If you do not build cleanup into the harness, the system slowly teaches future agents the wrong patterns.

OpenAI calls this out as garbage collection. That phrase feels right. You need recurring cleanup, mechanical checks, and a way to turn human taste into rules the agent can keep applying.

Otherwise the harness gets heavier every week.

## Same brain, different body

This is why two products using the same model can feel completely different.

One feels chaotic. Another feels reliable.

The difference is usually not the model. It is the body around the model.

The prompt matters. Context matters. The model matters too. But the agent experience is the whole thing: tools, memory, approvals, state, logs, UI, evals, and stop conditions.

That is the harness.

And once you see it, a lot of agent work starts to look different.

The question is not only "which model are you using?"

The better question is:

What have you built around it?

Because that is where most of the product lives.

For a while, I would have called this agent engineering, or dev tools, or workflow automation, depending on the project.

Those labels are still true.

But they miss the thing I keep caring about.

I care about the shape around the intelligence.

I care about the layer that turns a powerful but slippery capability into something you can operate, inspect, move, and trust.

That is why I keep building runtimes, formats, adapters, queues, ledgers, approval gates, and validators.

The model is easy to point at.

The API is easy to demo.

The first version is easy to believe in.

The harness is what survives contact with actual use.

## Sources I found useful

- Caleb Writes Code, "Agent Harness explained in 8min.."
- OpenAI, ["Harness engineering: leveraging Codex in an agent-first world"](https://openai.com/index/harness-engineering/)
- Addy Osmani, ["The Orchestration Tax is You"](https://app.daily.dev/posts/the-orchestration-tax-is-you-gcleyobye)
- Zhong and Zhu, ["AI Harness Engineering: A Runtime Substrate for Foundation-Model Software Agents"](https://arxiv.org/abs/2605.13357)


---

Source: https://www.anuragd.me/blog/agent-harnesses-explained
