If you use Claude Code, Codex or Antigravity, you already use a harness. The model behind them is only part of what you are working with: around it sit tools, rules, memory, test runners and the loop that ties them together. Harness engineering is the practice of designing that surrounding layer on purpose instead of leaving it to defaults. This article draws on Birgitta Böckeler's piece on harness engineering for coding agent users (martinfowler.com), Vivek Trivedy's anatomy of an agent harness on the LangChain blog, and our own experience of what makes coding agents useful.
Agent = Model + Harness
The equation is the shortest definition there is. The model is the brain: capable, but non-deterministic, and with no direct contact with the outside world. It cannot open your repository, run your tests or remember what happened yesterday on its own. The harness is everything else in the agent — every piece that lets the brain act, observe and correct itself. LangChain puts it bluntly: "If you're not the model, you're the harness."
Even a plain chat product is a harness. As LangChain notes, chat itself is a model wrapped in a while loop — the simplest harness there is. Everything a coding agent adds on top of that loop is harness, too.
What's inside a harness
| Component | What it gives the model | Example |
|---|---|---|
| System prompts and rules | Clear instructions and coding standards from the first token | AGENTS.md-style files injected into context at start |
| Tools and MCP servers | Ways to act, and to reach knowledge past the training cutoff | Bash, code execution, web search, MCP tools such as Context7 |
| Skills | Task know-how loaded only when it is needed | A skill for code review or for bootstrapping a service |
| Memory systems | Durable state across sessions | Memory files, a plan file, git history |
| Sandbox, filesystem, browser | A safe place to work and a way to see results | Isolated execution, allow-listed commands, network isolation, screenshots |
| Orchestration and subagents | A way to split work and route it | Subagent spawning, handoffs, model routing |
| Hooks and middleware | Deterministic steps the model cannot skip | Compaction, continuation, lint checks |
Why a model needs a harness
According to LangChain, a model on its own cannot:
- keep durable state across interactions,
- execute code,
- access real-time knowledge,
- set up environments or install packages.
Each gap is closed by a harness primitive. LangChain calls the filesystem the most foundational one: a workspace, a place to offload context, and a collaboration surface between agents and people. Git adds versioning, rollback and branching on top. Bash and code execution act as the general-purpose tool, driven by a ReAct loop: reason, act with a tool call, observe the result, repeat.
Our view at ByteVancer is that a good harness does two things: it makes the model's output more accurate, and it gives the model a feedback loop to correct itself. Böckeler frames the outer harness the same way, with two goals — raise the probability the agent gets it right the first time, and self-correct as many issues as possible before a human reviews the work. The payoff she names is less review toil and fewer wasted tokens.
The shift: from a one-way prompt to a two-way loop
- 01
Human prompt
You describe what you want.
- 02
AI model
Generates an answer in one pass.
- 03
Code generated
Every mistake lands on your desk.
- 01
Human prompt
You describe what you want.
- 02
Harness (feedforward)
Rules, skills and standards shape the request before the model acts.
- 03
AI model ⇄ harness tools
The model acts; tests, linters, logs and the browser answer back.
- 04
Code generated
Checked by the harness before you see it.
That two-way arrow is the whole story. In the old flow the model hears nothing back, so every error reaches you. In the new one, the model hears from the type checker, the test suite and the linter first — and fixes what they report before you review.
Feedforward guides and feedback sensors
Böckeler splits harness controls into two kinds. Guides are feedforward controls: they steer the agent before it acts. Sensors are feedback controls: they observe what the agent did and help it self-correct. You need both. With feedback only, the agent keeps repeating the same mistakes; with feedforward only, your rules are encoded but the agent never learns whether they worked.
Harness
Coding agent
Feedforward (guides)
- Skills
- PRDs
- Rules
- MCP servers
- Principles
- Coding standards
Feedback (sensors)
- Review agents
- Logs
- Browser access
- Unit tests
- Integration tests
- ESLint config
Harness
Feedforward (guides)
- Skills
- PRDs
- Rules
- MCP servers
- Principles
- Coding standards
Feedback (sensors)
- Review agents
- Logs
- Browser access
- Unit tests
- Integration tests
- ESLint config
Coding agent
Feedforward →
Feedback →
Read the diagram top to bottom. The prompt enters the harness, not the model. Guides shape the first attempt; sensors check it and send the agent back to fix what failed. The output you see has already been through that loop.
Computational vs inferential controls
Böckeler adds a second axis. Computational controls are deterministic and fast and run on a CPU: tests, linters, type checkers, structural analysis. Inferential controls use a model: semantic analysis, AI code review, LLM-as-judge. They catch things rules cannot, but they are slower, cost more and are non-deterministic. Her examples:
| Control | Direction | Kind | Example |
|---|---|---|---|
| Coding conventions | Feedforward | Inferential | AGENTS.md, skills |
| Bootstrap instructions | Feedforward | Both | A skill plus a bootstrap script |
| Code mods | Feedforward | Computational | OpenRewrite recipes |
| Structural tests | Feedback | Computational | A pre-commit or agent hook running ArchUnit on module boundaries |
| Review instructions | Feedback | Inferential | Skills |
The steering loop
A harness is never finished. Böckeler's advice is to improve the feedforward or feedback controls whenever an issue recurs — and the agents themselves can help, by writing structural tests, drafting rules and scaffolding linters.
- 01
Issue recurs
The same mistake shows up in review twice.
- 02
Improve a guide or sensor
Add a rule, a skill, a lint check or a structural test.
- 03
Agent retries
The next run is shaped and checked by the new control.
- 04
Fewer repeats
Human review moves on to problems a control can't catch.
Keep quality left
Not every check belongs in the inner loop. Böckeler recommends running the fast checks first and the expensive ones later, with continuous and runtime sensors behind them:
- 01
Before commit
Linters, fast tests, a basic review agent.
- 02
Post-integration
Mutation testing, broader review.
- 03
Continuous drift
Dead code, coverage quality, dependency scanners.
- 04
Runtime
Degrading SLOs, log anomalies.
Böckeler also points to teams already working this way: an OpenAI team that enforces a layered architecture with custom linters and structural tests and runs recurring "garbage collection" against drift, and Stripe's "minions", where pre-push hooks run the relevant linters to shift feedback left.
What a harness regulates
| Harness | What Böckeler describes |
|---|---|
| Maintainability | The easiest to build, because existing tooling already covers much of it |
| Architecture fitness | Fitness functions, performance tests, logging standards |
| Behaviour | The hardest: a spec as feedforward; AI-generated tests as feedback aren't good enough yet; the approved-fixtures pattern helps |
Harnessability and ambient affordances
Some codebases are easier to harness than others. A typed language gives you a type-check sensor for free; clear module boundaries let you write architecture rules. Böckeler borrows Ned Letcher's term "ambient affordances" for these properties. The uncomfortable corollary: in legacy code, the harness is most needed exactly where it is hardest to build.
She also suggests harness templates per service topology, and cites Ashby's Law of Requisite Variety — a regulator needs as much variety as the system it regulates. The human role does not disappear: the harness externalises developer experience, and the aim is to direct human input to where it matters most, not to eliminate it. In her framing, a user harness is a specific form of context engineering — the practice that makes guides and sensors available to the model.
Harnesses for long-running agents
Long tasks add a problem LangChain calls context rot: models degrade as their context window fills. The harness primitives LangChain describes for long-horizon work:
- Filesystem and git across sessions — progress survives when the context does not.
- The Ralph Loop — a hook intercepts the agent's attempt to exit and re-injects the prompt in a clean context.
- Planning — a plan file the agent writes and follows.
- Self-verification — hooks run the test suite and loop errors back to the model.
- Compaction — summarising older context to free space.
- Tool-output offloading — keep the head and tail of a long output in context and write the full output to the filesystem.
- Skills with progressive disclosure — load instructions only when the task needs them.
Evidence that the harness matters
LangChain reports that its coding agent moved from the Top 30 to the Top 5 on Terminal Bench 2.0 by changing only the harness. Same model, different surroundings, a very different result. That is the strongest argument for treating the harness as engineering rather than configuration.
- Before
- Top 30LangChain's coding agent with its original harness.
- After
- Top 5The same model; only the harness changed.
Leaderboard position, where a lower rank is better. Figures as reported by LangChain (Vivek Trivedy, The Anatomy of an Agent Harness).
A starter harness for your team
This is our own checklist, built from the controls above. Each item is small; together they cover both directions of the loop.
- Write your conventions down in an AGENTS.md or CLAUDE.md file: coding standards, architecture rules and the commands to build and test.
- Package repeatable know-how as skills, so it loads only when a task needs it.
- Run lint, type checks and fast tests as hooks, so the agent sees failures before you do.
- Rewrite custom lint messages to say how to fix the problem, not just what is wrong.
- Add a review agent with written review instructions.
- Give the agent browser and log access so it can verify its own work.
- Keep memory and plans in files, and work through a git workflow so every change can be rolled back.
- Close the steering loop: every repeated mistake becomes a new rule or a new sensor.
Where harness engineering is going
LangChain expects some harness functions to be absorbed into the models themselves over time, while harness engineering likely remains useful. We agree: models will get better at the inner loop, but your conventions, your architecture and your definition of done are specific to your team, and only a harness can carry them. The same goes when you swap the model itself, say for an open model from the Hugging Face Hub: the harness is the part that carries over. Our guide to what Hugging Face is used for covers the Hub, Spaces and Inference Providers.
One more distinction worth keeping: harness engineering governs one agent; graph engineering wires many. When several agents share a codebase, each with its own mandate, read our follow-up on graph engineering for multi-agent systems.
