# 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="../sessions/#what-persists" 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="../sessions/#what-persists">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())
~~~

<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 BM25F retrieval over OKF knowledge bundles | [Tools](../tools/), [MCP](../mcp/), [Skills](../skills/), [Knowledge](../knowledge/) |
| Context | Conversation history, notes, structured facts, and result spilling | [Sessions & snapshots](../sessions/#what-persists) |
| 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

**Agent** and **AgentRuntime** are two entry points into one execution engine, with the same tool and permission semantics. Use `Agent` for an in-process conversation or request. Use `AgentRuntime` when work must pause for an approval or survive a process failure. See [Durable agent runs](../durable-agent-runs/).

