The Anatomy of an Agent Harness

An in-depth look at the 'Harness'—the essential infrastructure that transforms raw AI models into functional agents by providing state, tool execution, and environmental constraints.
By Vivek Trivedy
TLDR: Agent = Model + Harness. Harness engineering is how we build systems around models to turn them into work engines. The model contains the intelligence and the harness makes that intelligence useful.** **We define what a harness is and derive the core components today's and tomorrow's agents need.
Can Someone Please Define a "Harness"?
Agent = Model + Harness
If you're not the model, you're the harness.
A harness is every piece of code, configuration, and execution logic that isn't the model itself. A raw model is not an agent. But it becomes one when a harness gives it things like state, tool execution, feedback loops, and enforceable constraints.
Concretely, a harness includes things like:
- System Prompts
- Tools, Skills, MCPs + and their descriptions
- Bundled Infrastructure (filesystem, sandbox, browser)
- Orchestration Logic (subagent spawning, handoffs, model routing)
- Hooks/Middleware for deterministic execution (compaction, continuation, lint checks)
There are many messy ways to split the boundaries of an agent system between the model and the harness. But in my opinion, this is the cleanest definition because it forces us to think about designing systems around model intelligence.
The rest of this post walks through core harness components and derives why each piece exists working backwards from the core primitive of a model.
Why Do We Need Harnesses…From a Model's Perspective
**There are things we want an agent to do that a model cannot do out of the box. This is where a harness comes in.**Models (mostly) take in data like text, images, audio, video and they output text. That's it. Out of the box they cannot:
- Maintain durable state across interactions
- Execute code
- Access realtime knowledge
- Setup environments and install packages to complete work
These are all harness level features. The structure of LLMs requires some sort of machinery that wraps them to do useful work.For example, to get a product UX like "chatting", we wrap the model in a while loop to track previous messages and append new user messages. Everyone reading this has already used this kind of harness. The main idea is that we want to convert a desired agent behavior into an actual feature in the harness.
Working Backwards from Desired Agent Behavior to Harness Engineering
Harness Engineering helps humans inject useful priors to guide agent behavior. And as models have gotten more capable, harnesses have been used to surgically extend and correct models to complete previously impossible tasks.
We won’t go over an exhaustive list of every harness feature. The goal is to derive a set of features from the starting point of helping models do useful work. We’ll follow a pattern like this:
Behavior we want (or want to fix) → Harness Design to help the model achieve this.
Filesystems for Durable Storage and Context Management
We want agents to have durable storage to interface with real data, offload information that doesn't fit in context, and persist work across sessions.
Models can only directly operate on knowledge within their context window. Before filesystems, users had to copy/paste content directly to the model, that’s clunky UX and doesn't work for autonomous agents. The world was already using filesystems to do work so models were naturally trained on billions of tokens of how to use them. The natural solution became:
Harnesses ship with filesystem abstractions and tools for fs-ops.
The filesystem is arguably the most foundational harness primitive because of what it unlocks:
- Agents get a workspace to read data, code, and documentation.
- Work can be incrementally added and offloaded instead of holding everything in context. Agents can store intermediate outputs and maintain state that outlasts a single session. **The filesystem is a natural collaboration surface.**Multiple agents and humans can coordinate through shared files. Architectures like Agent Teams rely on this.
Git adds versioning to the filesystem so agents can track work, rollback errors, and branch experiments. We revisit the filesystem more below, because it turns out to be a key harness primitive for other features we need.
Bash + Code as a General Purpose Tool
We want agents to autonomously solve problems without humans needing to pre-design every tool.
The main agent execution pattern today is a ReAct loop, where a model reasons, takes an action via a tool call, observes the result, and repeats in a while loop. But harnesses can only execute the tools they have logic for. Instead of forcing users to build tools for every possible action, a better solution is to give agents a general purpose tool like bash.
Harnesses ship with a bash tool so models can solve problems autonomously by writing & executing code.
Bash + code exec is a big step towards giving models a computer and letting them figure out the rest autonomously. The model can design its own tools on the fly via code instead of being constrained to a fixed set of pre-configured tools.
Harnesses still ship with other tools, but code execution has become the default general-purpose strategy for autonomous problem solving.
Sandboxes and Tools to Execute & Verify Work
Agents need an environment with the right defaults so they can safely act, observe results, and make progress.
We've given models storage and the ability to execute code, but all of that needs to happen somewhere. Running agent-generated code locally is risky and a single local environment doesn’t scale to large agent workloads.
Sandboxes give agents safe operating environments. Instead of executing locally, the harness can connect to a sandbox to run code, inspect files, install dependencies, and complete tasks. This creates secure, isolated execution of code. For more security, harnesses can allow-list commands and enforce network isolation. Sandboxes also unlock scale because environments can be created on demand, fanned out across many tasks, and torn down when the work is done.
Good environments come with good default tooling. Harnesses are responsible for configuring tooling so agents can do useful work. This includes pre-installing language runtimes and packages, CLIs for git and testing, browsers for web interaction and verification.
Tools like browsers, logs, screenshots, and test runners give agents a way to observe and analyze their work. This helps them create self-verification loops where they can write application code, run tests, inspect logs, and fix errors.
The model doesn’t configure its own execution environment out of the box. Deciding where the agent runs, what tools are available, what it can access, and how it verifies its work are all harness-level design decisions.
Memory & Search for Continual Learning
Agents should remember what they've seen and access information that didn't exist when they were trained.
Models have no additional knowledge beyond their weights and what's in their current context. Without access to edit model weights, the only way to "add knowledge" is via context injection.
For memory, the filesystem is again a core primitive. Harnesses support memory file standards like AGENTS.md which get injected into context on agent start. As agents add and edit this file, harnesses load the updated file into context. This is a form of continual learning where agents durably store knowledge from one session and inject that knowledge into future sessions.
Knowledge cutoffs mean that models can't directly access new data like updated library versions without the user providing them directly. For up-to-date knowledge, Web Search and MCP tools like Context7 help agents access information beyond the knowledge cutoff like new library versions or current data that didn't exist when training stopped.
Web Search and tools for querying up-to-date context are useful primitives to bake into a harness.
Source: LangChain Blog
















