Skip to content
Everything Agents

Lesson 3 of 14 · 6 min

Anatomy of one harness turn

Observe → think → act → commit. The deterministic stages around the model are where almost all harness design happens.

A harness turn is the unit of execution. You can think of it as one revolution of a wheel: read state, ask the model, do the thing, record what happened, repeat.

One harness turn: four phasesA turn cycles through four phases. Observe reads state and composes the prompt. Think is the model phase, where it picks a tool or a reply. Act dispatches the tool and captures the result. Commit writes state, logs, and trajectory before the loop returns to observe.observeread state, compose promptthinkmodel picks tool or replyactdispatch tool, capture resultcommitwrite state, log, evaluatedeterministic shell · soft model core · deterministic shell

The picture matters because it says where the engineering happens. Three of the four phases are deterministic: code that you write, or that the harness vendor wrote on your behalf. Only think is the LLM. Almost every interesting harness design choice is a choice about what runs in the deterministic stages.

Step it through

Below is one real Claude Code turn (fix the failing test in auth_service_test.py), broken into six frames. Click through them and watch which components are active at each phase.

Step through one turn

One real Claude Code turn, frame by frame. Watch which components are active at each phase.

frame 1 / 6
ETCSLVactive components
observe

Read state, compose prompt

The harness loads the user message, recent history, the contents of CLAUDE.md, and any relevant tool results from prior turns. The context manager (C) decides what fits.

user: fix the failing test in auth_service_test.py
assistant_history: [3 prior tool results, 2 messages]
CLAUDE.md: [loaded]

A few things worth noticing in that sequence.

The model only acts once per turn, in the think phase. It picks a tool. Everything else is the harness around the call.

Validation happens before dispatch, not after. The tool registry checks that Read was called with a valid file_path before the implementation runs. A typo in the model's call gets rejected; the implementation never sees a bad input.

Hooks run twice, once before the tool and once after. The pre-call hook can refuse the call (permission denied, quota exceeded). The post-call hook is for audit and metrics.

The trajectory entry is structured. It's not a log line. It's a typed record with tool, args, result, latency, ok: something downstream tooling can read directly. This is the V component doing real work.

Why the deterministic shell matters

Here is the version of this picture you'll see again and again: deterministic shell · soft model core · deterministic shell.

The shell is where you put guarantees. "This tool is allowed only when verified is true." "This argument must match this regex." "This output must be parseable as JSON." None of those are reliable when expressed as a sentence in a prompt; all of them are trivially reliable when expressed as code in the harness.

The soft core is where you put judgment. Should the agent run the tests now or write more code first? Which file is most likely to contain the bug? Those are model-shaped questions and the model should answer them.

The execution loop as a state machine

If you formalize the loop, it's a labeled transition system:

Q = { idle, observing, invoking-model, dispatching-tool,
      awaiting-tool-result, committing-state, terminated }
Σ = model tokens, tool invocations, tool results,
    human approvals, errors
δ : Q × Σ → Q

Three properties only become expressible once you write it down this way (source: 2604.agent-harnesses-survey.pdf §2.2):

  • Safety: the system never enters a state from which termination is unreachable. No runaway loops.
  • Liveness: from every reachable non-terminal state, a terminal state is reachable. The loop can always finish.
  • Determinism: the transition function is a function, not a relation. Environment non-determinism is isolated at tool boundaries.

Most agent loops in the wild violate at least one of these. ReAct's δ is undefined on error inputs (there's no "what does the loop do if a tool throws an exception" arc), so its safety property is violated. AutoGPT does have an explicit error recovery arc; it qualifies.

This isn't pedantry. Execution runaway, the failure mode for E, is exactly what you get when safety is violated. Knowing the property has a name helps you find the bug.

What's coming

Lesson 4 zooms into the C stage of a turn: how context gets managed when the conversation outgrows the window. Lesson 5 zooms into T: what makes the tool registry trustworthy. From there you'll have the vocabulary to read any harness paper.

Quick check

In the four-phase turn loop, which phase is the only one driven by the LLM?