Skip to content
advanced

What Is an Agent Harness? The Software Layer Around an LLM

Two teams ship the same model, the same prompt, the same tool list. One agent finishes a multi-step task. The other stalls, loops, and quietly corrupts its…

Published 2026-09-11Updated 2026-09-1210 min read
Close-up of dual computer monitors with green coding interfaces in a dark room, highlighting cyber security themes.
Close-up of dual computer monitors with green coding interfaces in a dark room, highlighting cyber security themes. Photo by Tima Miroshnichenko on Pexels.

Two teams ship the same model, the same prompt, the same tool list. One agent finishes a multi-step task. The other stalls, loops, and quietly corrupts its own state. The model is not the variable. The harness is.

For chat and single-tool calls, "the agent is the model plus a while loop" holds up fine. That loop tracks messages, appends the user turn, calls the model, and stops when the model stops asking for tools. It breaks the moment a task needs durable state, enforced policy, deterministic verification, or recovery from partial failure. The model proposes judgment: decomposition, action selection, interpretation of feedback, and when to stop. The harness enforces what actually happens. Everything that must be true for judgment to become work lives in that layer.

The Boundary: Model, Harness, Framework, Application

A three-column comparison shows the model proposing actions and interpreting results, the harness assembling context, enforcing policy, executing tools, persisting state, and validating outcomes, and the application presenting progress and collecting human input. Arrows run from model proposal through harness control to application interaction and back through recorded results.
The harness is the execution boundary between model judgment and application experience: it turns proposals into controlled, observable work.

The working definition I use: the harness is every piece of code, configuration, and execution logic that is not the model. If you are not the model, you are the harness. A raw model is not an agent; it becomes one when a runtime gives it state, tool execution, feedback loops, and enforceable constraints.

That definition is deliberately broad, so it needs three boundaries.

Harness vs. framework. A framework supplies building blocks you assemble: message types, tool abstractions, graph nodes, provider clients. A harness is the assembled, opinionated runtime that already drives model and tool calls, manages context, applies approvals, and keeps a multi-step task progressing. You can build a harness on a framework, or hand-roll one directly on a provider SDK. The distinction is assembly and opinion, not dependency count.

Harness vs. application. The application owns UX: streaming, progress display, human input collection, the approval dialog itself. The harness owns execution semantics underneath it. When a tool call needs a human decision, the harness decides what runs and the application collects the decision.

Agent vs. harness. The word "agent" gets used for both the whole working system and the model doing the reasoning. In this article, "agent" means the whole system and "model" means the reasoning component. The harness is the layer between them.

The invariant worth defending: the model proposes the next action and interprets results; the harness validates, limits, records, and can override the transition. Behavior you cannot express as a harness mechanism will not reliably happen.

Knowledge check

Check your understanding

Answer this question before you continue.

A team tells the model, “Never delete files,” but has no code-level restriction. According to the article’s boundary invariant, what is the most accurate assessment?
Misconception Check

Focus: Distinguish the model's advisory role from the harness's enforcement role in an agent system.

What the Model Cannot Do on Its Own

Rather than memorize a component taxonomy, derive it. Start from the model's structural gaps and work backward to the harness feature that closes each one.

The model has no memory between calls. It has no ability to execute the code it writes. It keeps no record of what it tried five steps ago. It has no mechanism to check whether it succeeded. Each gap maps to a harness responsibility.

Without weight updates, the only way to add knowledge is context injection. That single fact makes context assembly, compaction, and retrieval harness concerns, not model concerns. Knowledge cutoffs mean current facts — library versions, API changes, live system state — must arrive through search or tool calls that the harness provides and routes.

The derivation rule: work backwards from the desired agent behavior to the harness feature that makes it possible. If you want the agent to remember a project convention across sessions, you need a memory file that gets injected at start and reloaded when the agent edits it. If you want it to stop after three failed attempts, you need an iteration limit in the loop. Teams that skip this step add tools and prompts reactively, then cannot explain why the agent behaves differently across runs.

Knowledge check

Check your understanding

Answer this question before you continue.

An agent must remember a project convention across separate sessions. Which harness design follows the article’s derivation rule?
Comparison Reasoning

Focus: Map a model capability gap to the harness mechanism required to support the desired behavior.

The Core Components of a Harness

Here is the component model, mapped to the gap it closes and the symptom you see when it is missing.

ComponentModel gap it closesSymptom when absent
Capabilities: tools, skills, MCP integrations, and their descriptionsNo ability to act on the worldAgent describes actions instead of taking them
Bundled infrastructure: filesystem, sandbox, shell, browserNo execution environmentAgent cannot inspect or modify real artifacts
Orchestration: driving loop, iteration limits, subagent spawning, handoffs, model routingNo control flow across stepsInfinite loops, or one context window doing everything
State and persistence: session instructions, per-call history, todo state, memory filesNo memory between callsAgent repeats work, forgets decisions
Context management: compaction, token budgets, progressive disclosureFixed context windowSessions degrade or hard-fail near the limit
Deterministic middleware: hooks for compaction, continuation, lint, formattingNo guaranteed side effectsCorrectness depends on the model choosing to comply

Two of these deserve emphasis.

Tool descriptions are harness surface. They shape action selection as much as the tool implementation does. A tool with a vague description is a harness bug, not a model bug.

Deterministic middleware runs outside the model. Compaction, continuation, lint checks, and formatting should not depend on the model deciding to do them. If a step must happen every iteration, put it in a hook.

Parallel subtasks need isolated context. That is an orchestration constraint, not a prompting trick. If two subagents share a context window, they will contaminate each other's working state.

Knowledge check

Check your understanding

Answer this question before you continue.

An agent repeatedly avoids a tool even though the implementation works and the tool is available. Its description is vague about when and why to use it. What should the team diagnose first?
Scenario Interpretation

Focus: Recognize tool descriptions as part of the harness surface that influences action selection.

One Run, End to End

The component table tells you what exists. A trace tells you how it moves. Here is a framework-neutral walkthrough of a single task: "fix the failing test in auth/session.py."

state = { goal, history: [], artifacts: {}, attempts: 0 }

loop:
  proposal = model(context=assemble(state))
  # proposal: { action: "run_tests", args: { path: "auth/session.py" } }

  decision = policy(proposal)          # allow | require_approval | deny
  if decision == deny: halt(reason)
  if decision == require_approval: await human; record(decision)

  result = execute(proposal)           # sandboxed, bounded, timed
  persist(result)                      # append to history + artifacts
  signal = validate(result)            # tests, linter, type checker

  if signal == pass: halt(success)
  if signal == validation_failure and attempts < 3:
      attempts += 1; continue          # bounded repair
  if signal == policy_violation: halt(reason)
  if signal == timeout and idempotent(proposal): retry
  if signal == stale_state: refresh(); continue
  halt(reason)

Three things are load-bearing here. First, the model proposes; the harness disposes. Second, every side effect is persisted and associated with the action that caused it — the invariant is that no side effect is considered complete until its result is recorded and linked to its cause. Third, the loop terminates on a named condition, not on the model's mood.

Knowledge check

Check your understanding

Answer this question before you continue.

In the article’s run trace, tests fail after an action and the attempt count is still below three. What does the harness do next?
Output Prediction

Focus: Predict the harness branch for a validation failure in a bounded execution loop.

signal == validation_failure and attempts < 3

Execution, Authorization, and the Permission Boundary

Shell and filesystem access is where a harness stops being a wrapper and becomes an operating concern. Model the capability explicitly rather than granting ambient access.

Approval flows come in three shapes: standing approvals for a class of commands, auto-approval rules for known-safe patterns, and per-call approval for everything else. The harness decides what runs; the application collects the human decision.

For local shell execution, run the logic in an isolated environment and keep explicit approval in place before commands are allowed to run. This is the recommendation from teams shipping these patterns in production, and it is the right default.

Permission tiers should be harness-level policy: what the agent can read, write, execute, and reach over the network. Least privilege is a code constraint, not a prompt request.

Prompt-level guardrails are advisory. If a constraint must hold, it belongs in code that can refuse the action. A model that is told not to delete files will eventually delete a file.

Feedback Loops and Verification

The harness acts as a control layer. It observes the effects of agent actions and regulates subsequent state transitions rather than merely forwarding error text to the model.

Deterministic sensors do the observing: linters, parsers, compilers, type checkers, unit and integration tests, static analyzers, runtime monitors, CI pipelines. These turn a trajectory into inspectable signals — pass/fail outcomes, diagnostics, failing traces, coverage gaps, policy violations.

The harness then chooses among real branches. The signal type determines the response, and each response persists different evidence:

SignalHarness responseEvidence to persist
Validation failureBounded repair (retry with feedback)Failing test, diff, attempt count
Policy violationHalt or escalate to approvalRule triggered, proposed action
TimeoutRetry only if the action is idempotentDuration, retry count, idempotency key
Stale stateRefresh context, replanExternal change detected, new snapshot
Partial side effectCompensate or roll backWritten artifacts, rollback result
Silent wrong objectiveHalt; requires human reviewGoal drift signal, last known-good state

Name these as explicit branches in code, not vibes in a prompt. A validation failure and a policy violation should not trigger the same recovery path.

This matters more than model choice for long-horizon work. The bottleneck of autonomy is often the reliability of the system connecting model output to long-horizon actions and persistent state, not the reasoning ability of the base model. That claim comes from vendor and independent research on long-horizon tasks, including work showing that harness design can dominate model choice for both task completion and cost. Treat it as a strong signal, not settled consensus — the research is recent and the benchmarks are still contested.

Observability, Recovery, and Durable Artifacts

Per-service-call history persistence is what makes a run reconstructable. Without it, debugging a multi-step failure becomes archaeology.

Capture model calls, tool invocations and their outputs, approval decisions, compaction events, state transitions, and the sensor results that drove each branch. Recovery patterns follow: resumable sessions, bounded retry with backoff, checkpointing durable state, and idempotency for side-effecting tools so a retry does not double-charge or double-write.

Durable artifacts — files, patches, reports, memory files — outlive the session and become the agent's continuity across runs.

Plan for this failure taxonomy:

  • Context overflow
  • Tool-call loops
  • Stale state after external change
  • Partial writes
  • Approval deadlock
  • Silent success on a wrong objective

If you cannot replay the run from persisted artifacts, you do not have observability — you have logs.

When a Harness Is Overkill

Single-turn generation, classification, extraction, and summarization need a call, not a runtime. Adding a loop adds latency, cost, and failure surface with no benefit.

Fixed, known-step workflows are better served by an explicit pipeline or state machine than by an agent that decides its own next step. Determinism you can write down should not be delegated to a model.

The threshold for a harness: the task requires multiple dependent steps, the next step depends on observed results, the work must survive process restarts, or the agent needs capabilities the model cannot have natively.

Cost and latency are harness-level levers. Iteration limits, compaction strategy, model routing, and tool granularity change the bill more than prompt wording does.

Where Reliability Is Won

The harness is where reliability is won or lost. Not the model, not the prompt. The runtime layer around the model.

Pick one failed or expensive task your system already handles. Replay its last execution and mark every transition: model proposal, policy gate, side effect, persisted state update, validator signal, recovery branch. Then find the earliest transition that is unbounded or unobservable — no iteration limit, no persisted result, no named branch, no recorded decision. That gap is your next engineering task, and it is almost always cheaper to fix than swapping models.

The adjacent concept to study next is harness engineering as a discipline — designing these components deliberately instead of accreting them one debugging session at a time.

Knowledge check

Final check

Finish the article by checking the ideas you just learned.

A tool call times out. Which recovery policy matches the article’s explicit signal branches?
Question 1 of 2Comparison Reasoning

Focus: Choose recovery behavior based on the distinct signal types defined by the harness.

A team has aggregate logs showing that an agent failed, but cannot determine which tool result caused a later recovery branch. Which missing capability is the article’s primary diagnosis?
Question 2 of 2Scenario Interpretation

Focus: Diagnose the observability requirement for reconstructing and recovering a multi-step agent run.

References

  1. The Anatomy of an Agent Harnesswww.blog.langchain.com
  2. Agent Harnesslearn.microsoft.com
  3. Toward Executable, Verifiable, and Stateful Agent Systems ◊arxiv.org
  4. Agent Harness in Agent Framework | Microsoft Agent Frameworkdevblogs.microsoft.com
  5. Nvidia just showed that the harness, not the AI model, is now the real hero - TechCrunchtechcrunch.com
8sources checked
8source domains
10searches run

Research updated Sep 11, 2026

Related sites

Build the foundations behind advanced AI systems

Use LearnLLMFast for practical LLM application foundations and LearnPyFast for the Python mechanisms that support implementation work.

LLM tutorialstutorial

LearnLLMFast

Practical LLM tutorials for builders who want to understand prompting, workflows, agents, and AI applications.

LLMAIBuilders
Visit LearnLLMFast
Python tutorialstutorial

LearnPyFast

Beginner-friendly Python tutorials, examples, and learning paths for practical programming foundations.

PythonProgrammingBeginners
Visit LearnPyFast

Keep exploring

Related AI engineering tutorials

Continue with adjacent system layers, implementation patterns, and current AI engineering ideas.