Harness Engineering

A working demo and a reliable product are separated by a real gap — the model hallucinates tools, picks the wrong one, or cannot recover from an error. Treat the LLM as the Model and everything built around it as the Harness — context and tools, plus three outer layers of constrain, verify, and correct.

By now you understand how an Agent works at its core — an LLM runs the ReAct loop, guided by context, using tools to complete a task. The basic mechanism works, but it is fragile: the model may hallucinate tools or parameters that do not exist, pick the wrong tool, or fail to recover from an error. Between a working demo and a reliable product lies a substantial gap, and those fragilities are exactly what Harness Engineering exists to fix.

The core formula Agent = LLM + Context + Tools describes the Agent’s internal composition. Harness Engineering adds an implementation-level view of the same system: treat the LLM as one core component (the Model), and call all the supporting code built around it the Harness. The two views are not rivals — they describe the same system at different levels of abstraction. We switch to the more general word “Model” because the principles apply to any model that can reason and call tools. The core of the Harness is the original formula’s “Context + Tools,” plus three layers of safeguards — Constrain (what the Agent may and may not do), Verify (whether it did the thing correctly), and Correct (how to recover when it did not). Expanded as an equation:

Agent = LLM + [Context + Tools + Constrain + Verify + Correct] = Model + Harness

A minimal working Agent runs on LLM, context, and tools alone; to keep running reliably in production it needs the three outer layers too. Take a refund for an order placed 3 days ago. Without a Harness: the model does not see the refund policy (no context), does not know which API to call (no tools), fabricates a refund result (no verification), and the user discovers the refund never happened (no correction). With a Harness: the system prompt states the 7-day policy (context), the Agent calls query_order and process_refund (tools), the framework checks the refund does not exceed the order total (constrain), confirms against the database that it went through (verify), and retries automatically on API timeout (correct). Same model, dramatically different result.

The Five Functions of the Harness

All infrastructure outside the model belongs to the Harness. Its core is Context and Tools, around which three engineering safeguards are built:

FunctionOne-sentence responsibilityRelationship to context / tools
ContextProvide the model with information to perceiveCore capability
ToolsProvide the model with interfaces to actCore capability
ConstrainSet behavioral boundaries — what can and cannot be doneSafety boundary around context and tools
VerifyAutomatically judge the correctness of a resultChecking mechanism around tool results
CorrectAutomatically recover or roll back on a problemRecovery mechanism around tool failures

Context and tools let the Agent “do things”; constrain, verify, and correct keep it from “doing the wrong thing.” The importance of the two groups is asymmetric along the product maturity curve: early frameworks focused on context and tools, while production systems have shifted their center of gravity to constrain, verify, and correct. In Claude Code the vast majority of Harness code is constrain / verify / correct, not context and tools — the tools are a small part; the safeguards around them are the real core. The industry is shifting from “doing things” to “doing things reliably,” which is why Harness Engineering has become the core competitive advantage of Agent systems.

From Prompt Engineering to Loop Engineering

Looking back at AI application engineering, a clear arc emerges, and the layers nest:

  • Software Engineering is the foundation — traditional system design, architecture, testing, deployment.
  • Prompt Engineering was the first wave — improving output by refining the natural-language instructions fed to the model.
  • Context Engineering was the second — optimizing the prompt alone is not enough; the whole working context (system instructions, tool definitions, conversation history, external knowledge) has to be managed systematically.
  • Harness Engineering is the third — it widens the view from “what the model sees” to “what kind of system the model runs in”: constraints, verification, feedback loops, error recovery.
  • Loop Engineering widens it again from a single run to sustained autonomous operation across runs — who finds the next thing to do, when to verify, and when the task is truly done.

These are not replacements but nested layers: prompt ⊂ context ⊂ Harness ⊂ Loop. Each widens the engineer’s scope beyond the last. As models converge in capability and stop being the decisive differentiator, competitive advantage shifts to the engineering outside the model.

Core Principles for Building Effective Agents

Based on Anthropic’s experience, successful Agent systems follow three core principles.

  • Keep it simple. Start with the simplest solution and add complexity only when truly necessary. Direct API calls beat complex frameworks; clear code beats clever abstraction — every extra layer is a new blind spot during debugging.
  • Keep it transparent. Show the Agent’s planning steps, execution logs, and decision trajectory. This is not just a debugging convenience but a precondition for user trust — an error inside a black box cannot be located or fixed from outside.
  • Design the tool interface well (ACI, Agent-Computer Interface). ACI means designing from the Agent’s perspective (easy for the Agent to understand and use), not the programmer’s. Names and parameters should be intuitive, and wherever misuse is likely the design should make the mistake impossible — like a SIM card’s notched corner that only fits one way. Manufacturing calls this Poka-yoke. A poorly designed tool makes even the strongest model fail repeatedly, because the interface is the only channel between model and tool.

How to Choose a Model

The model is the Agent’s foundation of intelligence, and choosing the right one often matters more than tuning prompts. Releases move too fast for specific version recommendations, so here are directions instead:

  • The three major closed-source vendors. OpenAI (GPT / o series), Anthropic (Claude), and Google (Gemini) are the most common. Each has strengths — Claude on complex reasoning, coding, and tool use; Gemini on very long context and multimodality; GPT / o on balanced all-round ability. Do not judge by leaderboards alone; evaluate on your own task.
  • Domestic and open models. When deploying in China or cost is sensitive, Doubao (low latency), Kimi (strong agentic ability), and Qwen / DeepSeek (open, self-hostable, fine-tunable) are pragmatic choices. Tool-calling ability varies widely — always test in your concrete scenario.
  • Most Agents need a reasoning model. Agents require multi-step reasoning and tool selection; models without reasoning tend to do poorly except on the simplest single-step tasks.
  • Watch output speed and multimodality. Each turn waits for the model to finish before the next step runs, so output speed drives end-to-end latency; if you need to understand images, audio, or video, multimodality is a hard requirement.

Engineering Practice

In Zapvol’s runtime, the core of the Harness shows up as three parts with non-overlapping responsibilities — divided by state ownership and trust boundary rather than by the formula’s structure, so the three do not line up with the three components: the agent loop is not the LLM, the message record is not the context.

Runtime partHolds durable stateTrustedCode
Agent loopNoYesrunAgentLoop()
SandboxNo, destroyed with the runNoISandbox port + createSandbox() factory
Message recordYes, the run’s full historyYesTaskRepository.getMessages()

The sandbox is the only untrusted part and the message record the only durable one — and these two facts deliver the Harness’s constrain and correct: constrain — credentials never enter the sandbox (it is untrusted, so credentials are isolated behind the KeyEncryption port); correct — crashes are recoverable (the loop holds no state that needs persisting, so a restart replays the message record to return to where it left off). This also answers a common confusion: the loop accumulates context across turns but does not own it — the message record is the sole source of context, and what the model sees each turn is projected from that append-only history.

The sandbox is constructed through the single createSandbox() factory dispatching on SANDBOX_TYPE — the only construction path, so switching provider is a one-line env change with zero code edits, and “given a task id, reconnect to its sandbox” lives in one place. Only NodeSandbox is actually implemented today; Daytona / E2B have their config types and env wired in but their adapters are still placeholders, so the factory throws a clear error for them until they are ported.

Was this page helpful?