# Introduction

The system around your model.

HarnessX is a Python SDK for building agents that reason, call tools, and carry work across turns. You supply the model, tools, and policies. The harness runs the loop and exposes what happens along the way.

<div class="intro-illustration harness-map">
<span class="diagram-label">THE WORKING PARTS</span>
<div class="map-row map-supply"><span class="map-row-label">You supply</span><a href="../agents/">Request<small>a message, or a resumed session</small></a><a href="../providers/">Model &amp; provider<small>one AgentConfig</small></a><a href="../tools/">Tools<small>typed functions</small></a><a href="../permissions/">Policies<small>permissions &amp; budgets</small></a></div>
<svg class="hx-track" viewBox="0 0 740 432" role="img" aria-label="The agent loop as a track: context feeds the model, the model calls tools and returns, guardrails, approvals and middleware act on the road, and execution state, recovery, the flight recorder, tracing and decisions sit beneath it.">
<defs><marker id="hx-arrow" viewBox="0 0 10 10" refX="7" refY="5" markerWidth="13" markerHeight="13" markerUnits="userSpaceOnUse" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z"/></marker></defs>
<g class="hx-slab"><rect x="20" y="340" width="700" height="86" rx="10" class="hx-slab-depth"/><rect x="20" y="334" width="700" height="86" rx="10" class="hx-slab-top"/><text x="36" y="356" class="lab">BENEATH THE LOOP</text>
<a href="../durable-agent-runs/" class="hx-chip"><rect x="36" y="366" width="160" height="44" rx="6"/><text x="46" y="384" class="t2">Execution state</text><text x="46" y="399" class="s">SQLite · Postgres · Temporal</text></a>
<a href="../recovery/" class="hx-chip"><rect x="202" y="366" width="100" height="44" rx="6"/><text x="212" y="384" class="t2">Recovery</text><text x="212" y="399" class="s">resume · replay</text></a>
<a href="../flight-recorder/" class="hx-chip"><rect x="308" y="366" width="160" height="44" rx="6"/><text x="318" y="384" class="t2">Flight recorder</text><text x="318" y="399" class="s">export · verify · play back</text></a>
<a href="../evaluations/" class="hx-chip"><rect x="474" y="366" width="104" height="44" rx="6"/><text x="484" y="384" class="t2">Tracing &amp; evals</text><text x="484" y="399" class="s">LangSmith</text></a>
<a href="../decisions/" class="hx-chip"><rect x="584" y="366" width="135" height="44" rx="6"/><text x="594" y="384" class="t2">Decisions</text><text x="594" y="399" class="s">Choice · Score · Noul</text></a></g>
<path id="hx-loop" class="hx-road-ghost" d="M110 150V115A44 44 0 0 1 154 71H586A44 44 0 0 1 630 115V256A44 44 0 0 1 586 300H154A44 44 0 0 1 110 256Z"/>
<path class="hx-road" marker-end="url(#hx-arrow)" d="M110 150V115A44 44 0 0 1 154 71H292"/>
<path class="hx-road" marker-end="url(#hx-arrow)" d="M440 71H586A44 44 0 0 1 630 115V142"/>
<path class="hx-road" marker-end="url(#hx-arrow)" d="M630 212V256A44 44 0 0 1 586 300H154A44 44 0 0 1 110 256V220"/>
<path class="hx-ramp" marker-end="url(#hx-arrow)" d="M436 42C466 12 520 31 552 31"/>
<text x="492" y="14" class="mono">end_turn</text>
<path class="hx-entry" marker-end="url(#hx-arrow)" d="M70 252V222"/><text x="62" y="234" class="s" text-anchor="end">request</text><text x="62" y="247" class="s" text-anchor="end">enters</text>
<g class="hx-pin"><circle cx="205" cy="71" r="5"/><text x="205" y="50" class="s" text-anchor="middle">guardrails</text><text x="205" y="63" class="s" text-anchor="middle">request middleware</text></g>
<g class="hx-pin"><circle cx="530" cy="71" r="5"/><text x="530" y="92" class="s" text-anchor="middle">permissions · approvals</text><text x="530" y="105" class="s" text-anchor="middle">call middleware</text></g>
<g class="hx-pin"><circle cx="370" cy="300" r="5"/><text x="370" y="321" class="s" text-anchor="middle">hooks observe every event · result middleware · next iteration ↺</text></g>
<g class="hx-inner"><text x="370" y="150" class="lab" text-anchor="middle">AROUND EVERY STEP</text><text x="238" y="170" class="s"><tspan class="k">Middleware</tspan> reshapes requests and results</text><text x="238" y="185" class="s"><tspan class="k">Hooks</tspan> watch every event</text><text x="238" y="200" class="s"><tspan class="k">Guardrails</tspan> cap iterations, cost and context</text><text x="238" y="215" class="s"><tspan class="k">Approvals</tspan> pause a tool until a person decides</text><text x="238" y="230" class="s"><tspan class="k">Extensions</tspan> bundle these with saved state</text></g>
<a href="../memory/" class="hx-station"><rect x="35" y="150" width="150" height="62" rx="8"/><text x="47" y="172" class="t">Context</text><text x="47" y="188" class="s">history · notes · facts</text><text x="47" y="202" class="s">trimming · spilling</text></a>
<a href="../providers/" class="hx-station hx-model"><rect x="300" y="42" width="140" height="58" rx="8"/><text x="370" y="66" class="t" text-anchor="middle">Model</text><text x="370" y="84" class="s" text-anchor="middle">prompt cache · retry</text></a>
<a href="../tools/" class="hx-station"><rect x="555" y="150" width="150" height="62" rx="8"/><text x="567" y="172" class="t">Tools</text><text x="567" y="188" class="s">functions · MCP · skills</text><text x="567" y="202" class="s">subagents · sandbox</text></a>
<a href="../streaming/" class="hx-station hx-result"><rect x="560" y="6" width="160" height="50" rx="8"/><text x="574" y="27" class="t">Result</text><text x="574" y="44" class="s">RunResult · events · usage</text></a>
</svg>
<div class="hx-fallback">
<div class="map-loop">
<div class="map-node"><a href="../memory/">Context</a><small>conversation history</small><small>notes · long-term facts</small><small>trimming · spilling</small></div>
<b aria-hidden="true">→</b>
<div class="map-node map-model"><a href="../providers/">Model</a><small><a href="../prompt-caching/">prompt cache</a> · retry</small></div>
<b aria-hidden="true">⇄</b>
<div class="map-node"><a href="../tools/">Tools</a><small>functions · <a href="../mcp/">MCP</a> · <a href="../skills/">skills</a> · <a href="../knowledge/">knowledge</a></small><small><a href="../multi-agent/">subagents</a> · <a href="../sandbox/">sandbox</a></small><small>schemas · timeouts · dedupe</small></div>
<b aria-hidden="true">→</b>
<div class="map-node"><a href="../streaming/">Result</a><small>RunResult · output</small><small>error · typed events</small><small>usage · cache reads</small></div>
</div>
<p class="map-loop-note">Repeats until the model stops, a tool needs approval, or a guardrail is reached.</p>
<div class="map-row map-around"><span class="map-row-label">Around every step</span><a href="../hooks/">Middleware<small>transform requests &amp; results</small></a><a href="../hooks/">Hooks<small>observe every event</small></a><a href="../extensions/">Extensions<small>packaged features &amp; state</small></a><a href="../permissions/">Guardrails<small>iterations · cost · context</small></a><a href="../recovery/">Approvals<small>pause, decide, continue</small></a></div>
<div class="map-row map-beneath"><span class="map-row-label">Beneath the loop</span><a href="../durable-agent-runs/">Execution state<small>SQLite · PostgreSQL · Temporal</small></a><a href="../recovery/">Recovery<small>resume · replay policies</small></a><a href="../flight-recorder/">Flight recorder<small>export · verify · play back</small></a><a href="../evaluations/">Tracing &amp; evals<small>LangSmith</small></a><a href="../decisions/">Decisions<small>Choice · Score · Noul</small></a></div>
</div>
</div>

## Start with one agent

A typed Python function can be a tool. Pass it when you construct the agent, then await a run.

~~~python
import asyncio
from harnessx import Agent

def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

async def main():
    async with Agent(tools=[multiply]) as agent:
        result = await agent.run("What is 40 * 10? Use multiply.")
        if result.error:
            raise RuntimeError(result.error["message"])
        print(result.output)

asyncio.run(main())
~~~

This example makes live calls using the default Anthropic provider. Export your API key first. Custom tools inherit the default ALLOW policy; choose explicit permissions for tools with external effects.

<div class="doc-cards"><a href="../quickstart/"><span>01 / FIRST STEPS</span><strong>Build your first agent →</strong><p>Install the SDK, add a tool, and run a complete example.</p></a><a href="../examples/"><span>02 / EXPLORE</span><strong>Learn by running →</strong><p>Try streaming, skills, approvals, and incident playback.</p></a></div>

## What the harness provides

| Layer | What it does | Learn more |
| --- | --- | --- |
| Agent loop | Sends context to a provider, validates and dispatches tools, returns results | [Agents](../agents/) |
| Capabilities | Typed functions, external MCP tools, lazy skill instructions, and OKF knowledge bundles | [Tools](../tools/), [MCP](../mcp/), [Skills](../skills/), [Knowledge](../knowledge/) |
| Context | Conversation history, notes, structured facts, and result spilling | [Memory](../memory/) |
| Decisions | Standalone Choice routing, Score rubrics, and Noul evidence assessments | [Decisions with Jev](../decisions/) |
| Control | Permissions, explicit approval, budgets, and replay policies | [Permissions](../permissions/) |
| Execution | Direct runs or durable sessions with persisted execution boundaries | [Durable agent runs](../durable-agent-runs/) (advanced) |
| Inspection | Typed streaming events, lifecycle hooks, traces, and incident archives | [Streaming](../streaming/), [Flight recorder](../flight-recorder/) |

## Choose the execution model

Use **Agent** for an in-process conversation or request. It retains history while the instance lives. Use snapshots to explicitly save and reload a conversation.

The advanced [Durable agent runs](../durable-agent-runs/) guide introduces **AgentRuntime** for work that must pause for an approval or be recovered after a process failure. Its default SQLite backend persists execution state and events. PostgreSQL and Temporal implementations exist, with service qualification still required.

These are two entry points into the shared execution engine. Ordinary and streaming runs use the same tool and permission semantics.

## Explore the city

[The city map](../../) is an interactive map of the SDK: the workshops are tools, the crossing is permissions, the archive is memory, the vault is the flight recorder, and the fenced yard is the sandbox. Select a district to learn what it represents and follow its link into these docs.

The city illustrates the architecture; it is not connected to a running agent.

## Know the boundaries

HarnessX does not promise universal rollback or exactly-once external writes. Recovery depends on the tool's replay policy and its adapter. Incident playback displays captured records without running models or tools; it is not a deterministic rerun of a live model.

See [Implementation status](../status/) for available, service-dependent, and planned capabilities.
