> ## Documentation Index
> Fetch the complete documentation index at: https://codexceed.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# avatar.runner

AgentRunner — the bounded loop that terminates on verification (§5).

The runner owns *all* `TaskState` mutation (§8); tools and the verifier are
pure-ish workers. Phase 1 covers the read-only path: tier-0 tools, no permission
gate (every tool is tier 0), and the minimal `investigate` verifier. The loop is
deliberately a near-verbatim transcription of the §5 pseudocode.

## Classes

### `AgentRunner`

The bounded loop that owns all state mutation and ends on verification (§5, §8).

Collaborators are injected explicitly so a run is self-contained and replayable;
the runner orchestrates them but mutates `TaskState` itself.

Args:
model\_client: Proposes each turn's `ModelDecision`.
registry: The active `ToolRegistry`.
deps: Run-scoped `RunDeps` (workspace, etc.).
context\_builder: Assembles the per-iteration context packet (§9).
verifier: Disposes of "done" on external evidence (§12).
emitter: Observation-only event emitter (§13).
config: Budgets and harness settings.
policy: The before-tool-call control gate (§11); defaults to the standard tier policy.
planner: Resolves the per-session verification plan (ADR-0007); defaults to a
`VerificationPlanner(config)`.
event\_sink: Optional typed-event sink (a `Session`); absent on the batch/sync path.
approval\_controller: Optional awaited gate for tier-3 `ask` calls (a `Session`).
conversational: Terminal-boundary authority (§23.5, ADR-0046). The verifier steers
(repair loop) in both strict and conversational modes; this flag only changes the
disposition at repair exhaustion — `False` (default, `--auto`) pronounces `failed`;
`True` (interactive) defers to the human, blocking with an `open_question`. It never
makes a failed verdict advisory.
advisory: External-grading authority (ADR-0040 option A). `True` runs the verifier as
advisory — it reports but does not steer or gate, and a failed verdict is delivered
as `success` for a held-out grader (the eval probe) to judge. Off by default; set
only by external-grading callers (the eval harness), never the REPL. Takes precedence
over `conversational`.

```python theme={null}
AgentRunner(*, model_client: ModelClient, registry: ToolRegistry, deps: RunDeps, context_builder: ContextBuilder, verifier: Verifier, emitter: Emitter, config: HarnessConfig, policy: PermissionPolicy | None = None, planner: VerificationPlanner | None = None, event_sink: EventSink | None = None, approval_controller: ApprovalController | None = None, conversational: bool = False, advisory: bool = False) -> None
```

#### `AgentRunner.arun(self, state: TaskState) -> TaskState`

Drive the loop to a terminal outcome asynchronously — the real loop (§5).

A near-verbatim async transcription of the §5 pseudocode: blocking model/tool/
verifier bodies are offloaded with `asyncio.to_thread` so the event loop stays
responsive (spinners, keystrokes, ESC), and typed lifecycle events are published
to the sink as the run progresses. With no sink/controller wired it matches `run()`.

Args:
state: The task state to drive; mutated in place.

Returns:
The final `TaskState` with a terminal `outcome`.

Raises:
TransportError: When a model call fails at the transport layer (timeout / NUL body)
past the client's retries — a system failure surfaced to the caller, never fed
back to the model or masked as a soft `incomplete` (§16, ADR-0028 R4).
asyncio.CancelledError: When the run task itself is cancelled (the signal /
`_run_task.cancel()` path, ADR-0030) — re-raised after aborting the in-flight
model call so the loop unwinds without orphaning the request.

#### `AgentRunner.run(self, state: TaskState) -> TaskState`

Drive the loop to a terminal outcome synchronously (§5).

The thin sync wrapper over the async core: `arun()` *is* the loop, `run()`
wraps it via `asyncio.run()` for batch/library callers. Behavior is identical
to the async path with no sink/controller wired.

Args:
state: The task state to drive; mutated in place.

Returns:
The final `TaskState` with a terminal `outcome`.
