Dash0 acquires Polar Signals

Last updated: August 25, 2026

What Is an Agent Harness?

Hand a raw language model a prompt like "fix the failing test in this repo" and it will happily describe how it would fix the test. It won't open the file. It won't run the test. It won't check whether its own patch actually worked. Something else has to do that: call the tool, read the result, decide what to try next, and know when to stop. That something is the agent harness, and it's quietly become one of the more consequential pieces of software in the current AI stack.

The term is still settling. Anthropic uses it for Claude Code. LangChain calls the practice of tuning one "harness engineering" and applies it to Deep Agents. You'll also see "scaffolding" and "agent framework" used for roughly the same idea. This piece works through what a harness actually does, the loop nearly all of them run, why swapping one out can matter more than swapping the model underneath it, and why it's become something you need to instrument, not just build.

What is an agent harness?

An agent harness is the software layer wrapped around a language model that turns it from something that answers questions into something that does work: executing tools, managing what stays in context, persisting state across steps, and enforcing what the model is and isn't allowed to touch. The model supplies the reasoning. The harness supplies everything required to act on it.

The UK's AI Security Institute put a name to the split back in 2023 with a compact formula: Agent = Model + Harness. It's not an industry standard so much as a useful way to separate two things people conflate constantly. Anthropic's own engineering guidance describes a harness as "the loop, tools, context management, and guardrails that turn raw intelligence into a working agent." Same idea, and it's the definition I'll use throughout.

A useful gut check: if you're wondering whether something is "the model" or "the harness," ask whether it would still exist if you swapped Claude for GPT or Gemini underneath. A retry policy, a sandbox, a rule about which files an agent can write to: that's harness. The next-token prediction that decided which tool to call: that's the model.

Agent = model + harness, and the harness carries more weight than you'd think

The formula matters because it implies something people don't act on often enough: two teams running the identical model can get very different results, purely because one of them invested in the scaffolding around it and the other didn't. Dash0's own glossary of agentic engineering terms puts it bluntly: "capability comes from the harness, not the model."

There's a concrete data point behind that claim. LangChain documented taking its deepagents-cli coding agent from 52.8% to 66.5% on Terminal-Bench 2.0, a 13.7-point jump, while keeping the model fixed at GPT-5.2-Codex the entire time. Every gain came from harness work: a rewritten system prompt, middleware that enforces verification and detects an agent looping on the same edit, and richer context about the environment it's working in. That's a harness upgrade producing what looks, from the outside, like a model upgrade.

It also explains why Anthropic ships more than one harness for the same model family. Claude Code is a specific, opinionated harness tuned for coding work. Claude Managed Agents is what Anthropic calls a "meta-harness," deliberately unopinionated, exposing general interfaces so teams can build task-specific harnesses of their own on top. Same model family, two very different bets on what the scaffolding should look like.

The loop every harness runs

Strip away the branding and most harnesses run a version of the same cycle, often called the ReAct pattern (short for "reason and act"):

The model reads whatever's currently in context and decides on one next action. The harness carries that action out (running a shell command, calling an API, editing a file inside a sandbox) because the model itself has no hands. The harness then captures whatever came back and feeds it into the model's context as new information. The model reads that, decides on the next action, and the cycle repeats until the harness recognizes a stopping condition: the task looks done, a step or cost budget is exhausted, or a guardrail requires a human to weigh in.

None of that loop lives in the model's weights. A harness is what decides how many retries a failed tool call gets, how a five-hour session with a shrinking context window gets compacted without losing the plot, and what happens when the model asks for something it isn't allowed to do.

What the harness is actually responsible for

A few responsibilities show up in nearly every harness, coding-focused or not.

Tool execution and retries. The model requests an action; the harness is what actually runs it, usually inside some kind of sandbox, and decides how to handle a failed shell command, a rate-limited API, or a malformed tool call. Anthropic's Claude Code write-up notes that some of its most capable behavior traces back to just two tools: bash and a text editor. Everything more elaborate, like Agent Skills and programmatic tool calling, is built on top of that same execution layer.

Context management. Real tasks blow past a single context window. Anthropic's guidance on long-running agents describes a two-agent pattern to cope with it: an initializer agent that writes a feature list, a setup script, and an initial commit once, and a coding agent that picks up in later sessions by reading a progress file and working through one feature at a time rather than trying to one-shot the whole thing. That structure exists purely to survive a context window resetting mid-task.

State and memory across sessions. Git commits with real messages, a progress log, a feature checklist marked passing or failing: all harness-level bookkeeping, not something the model tracks on its own between sessions.

Permissions and guardrails. What the agent can read, write, or execute without asking, and where a human has to approve first. LangChain's Deep Agents, for one, ships this as middleware bolted onto the loop rather than something the model decides for itself: human-in-the-loop approval gates and PII detection, both configurable independent of which model is running underneath.

Orchestration. Spawning subagents, routing a task to a different model mid-run, deciding when to parallelize a batch of independent steps instead of running them one after another. None of that coordination happens inside the model itself; it's the harness deciding to fan work out and stitching the results back together.

Agent harness, framework, or scaffolding: does the label matter?

Not enough to lose sleep over, but it's worth having a working distinction since the vocabulary genuinely isn't settled. "Scaffolding" and "harness" are used interchangeably almost everywhere. "Framework" tends to mean something a level up: a library like LangGraph that gives you the pieces to build a harness, rather than a running system wired to a specific model, task, and set of tools. LangChain's own Deep Agents, for instance, is described as a harness built on LangGraph as its runtime.

The distinction that's actually useful in practice is autonomy. Independent comparisons of coding agents note that Claude Code runs a tight, largely autonomous loop with strong safety defaults, while Cursor's harness stays closer to the developer, more interactive and less willing to act without a human watching each step. Same broad category, different points on the autonomy dial, and that dial is a harness decision, not a model one.

Why observability has to watch the harness, not just the model

A single LLM call is a request and a response. An agent run is a trajectory: a sequence of model calls, tool calls, and decisions that only makes sense read together. That shift changes what you need to instrument. Dash0's guide to LLM observability lays out the agent-specific signals worth tracking beyond a single call: steps to completion, tool calls per task, retries, duplicate tool calls, loop rate, and cost per successful task, not just cost per call.

It also changes where the bugs live. In production, the model usually picks a reasonable tool and calls it correctly. The failure shows up downstream: an expired auth token, a rate limit, a malformed argument the API rejects. A trace that only says "tool called, tool errored" doesn't tell you which. That's a harness-layer failure, and it's invisible if your telemetry only watches the model call.

OpenTelemetry (OTel), the vendor-neutral standard most observability tooling now speaks, has GenAI semantic conventions built with exactly this shape in mind. An invoke_agent span wraps the whole run, chat spans cover each model call underneath it, and execute_tool spans cover each tool invocation, all nested in one trace via gen_ai.operation.name. Dash0's own Claude Code integration tags every span it emits with gen_ai.harness.name, so telemetry from Claude Code and Cursor sessions can be compared side by side by harness, not lumped together as an undifferentiated pile of "AI usage." Worth flagging: as of mid-2026 the GenAI conventions, including the agent- and harness-specific attributes, are still marked Development status in the spec. The core shape is stable enough to build dashboards on; expect some attribute names to keep moving underneath you for another few releases.

Instrumenting the harness you're already running

If you've adopted Claude Code or Cursor as a coding harness, that OTel data is often just a few environment variables away rather than a custom integration. Claude Code, for example, can export spans on its own:

bash
12345
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.<region>.aws.dash0.com"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <your-dash0-auth-token>"

That's the harness telling you what it's doing: which tools it called, how many tokens each model call burned, where it retried, where it failed. It's the same telemetry discipline you'd apply to any distributed system, pointed at a loop instead of a request handler.

Dash0 is built OTel-native for exactly this reason. GenAI spans land in the same pipeline as your infrastructure metrics, logs, and traces, so a coding harness's tool calls, an agent's decision path, and the production service it just modified show up in one place instead of three disconnected dashboards. AI Coding Insights uses that data to group Claude Code and Cursor sessions by model rather than vendor, tying agent activity back to cost, adoption, and cycle time from first prompt to merged pull request. The same data model underpins Agent0, Dash0's own production agent, which runs its investigations through a harness of its own, with a human approving actions until enough trust is built to hand more of it over.

Final thoughts

An agent harness is the scaffolding, not the intelligence: the loop that keeps calling the model, the tools it's allowed to execute, the context it manages, and the guardrails that keep it inside bounds. The Deep Agents benchmark result is the clearest evidence yet that this scaffolding isn't a minor implementation detail. It can matter as much as which model you picked. The vocabulary is still shaking out, but the shape underneath it (reason, act, observe, repeat) is consistent enough to reason about regardless of what a given vendor calls it.

If you're evaluating or building one, the practical takeaway is to treat it like any other piece of production infrastructure: instrument it. A harness that runs unobserved is a system making autonomous decisions you can't audit after the fact. For more on what to capture once you get there, see what LLM observability actually requires, the broader AI observability picture across predictive and agentic systems, and Dash0's terminology guide for how harness engineering fits alongside the rest of the agentic stack. Try Dash0 on your own harness telemetry at dash0.com. No credit card required.