Tier II — The Agent

The bar: you can ship a working loop that finishes real tasks and never runs away.

L2 — The Loop

COREYour first real agent — because you closed the loop.

The exact moment you feed a tool result back and let the model decide again — call another tool, or stop — you have an agent. Everything before was a pipeline; this is the first thing that pursues a goal. And with the loop comes the single hardest problem in agent engineering, which recurs at every rung above this one: termination. Not "how do I call a tool" — that was L1 and it's easy — but how does it know it's done, and how do I stop it when it doesn't.

              STOP · EMIT
                  ↑  if done / confident / max steps
OBSERVE  →  DECIDE  →  ACT
   ↑                    │
   └────────────────────┘
    observe result → decide again

The agent loop. The cycle is the verbs; the gold branch is termination — the gate every rung above L2 inherits.

Topology Shape When
SINGLE-PASS call → answer One tool, one hop, no iteration. This is L1 — the baseline before the loop.
ReAct think ⇄ act ⇄ observe ↻ Interleave reasoning and acting each turn until done. The default agent loop.
PLAN-EXECUTE plan → [ s1 · s2 · s3 ] Commit a plan up front, then run the steps. Best when the path is knowable.
REFLEXION act → critique → retry Self-evaluate the attempt, revise, try again. Costly; use when quality justifies it.

What you're actually learning

The agent loop itself: observe → decide → act → observe result → decide again → … → terminate. The minimal cycle that defines agency. Then loop topologies, and choosing between them is the design work — not a detail: single-pass tool use; ReAct (interleaved reasoning and acting); plan-then-execute (plan up front, then run the steps); and reflexion / self-critique (act, evaluate your own output, revise).

Termination conditions, in depth, and real agents use several at once: a max-step ceiling (the safety net), an explicit done-signal (the model declares completion, often via a "finish" tool), a goal-satisfaction check (external verification the objective is met), and a confidence threshold (completed at L4). Alongside them, the failure taxonomy: runaway loops (never stops), oscillation (A→B→A→B), premature termination (declares done too early), and thrash (busy but not progressing) — each with a different fix.

Finally, progress guarantees — ensuring each iteration moves toward the goal via step budgets, state deltas, and no-progress detection — and loop-carried state: what the cycle carries forward, and why naive accumulation blows the context budget (which L3 solves).

Concepts to master

  • The cycle — observe / decide / act / terminate.
  • TopologiesReAct vs. plan-execute vs. reflexion; tradeoffs and fit.
  • Multiple stop conditions — ceiling + done-signal + goal check together.
  • The finish-tool pattern — an explicit, model-emitted done-signal.
  • Failure detection — oscillation, thrash, no-progress.
  • Progress guarantees — step budgets and state deltas.
  • Loop-carried state — and its context cost.
  • Human-in-the-loop — a person as a stop, branch, or approval gate.
  • Budget-aware loops — token and cost ceilings as hard stops.
  • Deterministic replay — re-running a trace to reproduce a decision.

What you build

A multi-step agent that chains 2–4 tool calls to complete a real task — look something up, transform it, verify the result — and stops itself correctly. Implement it once as ReAct and once as plan-execute so you feel the difference, with a hard step ceiling and an explicit done-signal on both.

Clear it when

  • ☐ It finishes genuine multi-step tasks and never runs away — you can point to the exact condition that stops it.
  • ☐ You can trigger, detect, and recover from oscillation.
  • ☐ You can explain why you chose your topology over the alternatives.
  • ☐ Given a task it can't complete, it terminates cleanly instead of looping forever.

Where people get stuck

  • No stopping theory at all — the #1 reason first agents fail.
  • One stop condition where several are needed — e.g. only a ceiling, so it "succeeds" by hitting the cap.
  • Unbounded state accumulation that overflows the window mid-run.
  • Reflexive topology choice — ReAct for tasks that want a plan, or vice versa.

Connects

This is the behavioral core of the harness — loop engineering, the verbs. L3 builds the nouns around it. Termination introduced here goes fractal at L6; the confidence-threshold stop condition is completed at L4 by the token-level work.

L3 — The Harness

COREYour loop survives contact with reality.

An L2 loop works in a demo and dies in production, because production is tool timeouts, malformed output, rate limits, and context windows that overflow on turn nine. The harness is everything you build around the loop so it degrades gracefully instead of crashing — or worse, failing silently. If L2 is the verbs, L3 is the nouns: the static machinery the loop cycles through.

System | Tool defs | History | Retrieved | State | headroom → truncate / compact

The context budget. Every turn competes for one fixed window. When it fills, you truncate by recency or relevance, or compact old turns — the highest-leverage harness skill.

What you're actually learning

Context assembly and truncation is the highest-leverage harness skill. Each turn you decide what enters the window — system prompt, tool definitions, relevant history, retrieved context, current state — and what gets dropped when you exceed budget: truncation by recency or relevance, and summarization / compaction of old turns. "Just send everything" fails, and this is where most quality-under-load problems actually live.

Tool dispatch hardening: timeouts, retries with backoff, idempotency, concurrency limits, failures returned as results not exceptions. Error recovery: distinguishing recoverable errors (retry, reformulate) from terminal ones (stop, escalate), and wrapping the loop so a single bad turn doesn't kill the run. State and memory: short-term working transcript versus persistent cross-session memory — and recognizing that memory is a context-management problem in disguise.

Streaming for UX and the engineering it forces — partial parsing, tool calls mid-stream, cancellation. And output parsing under load: the structured-output enforcement from L0 applied at every turn, with repair, because at scale the model will occasionally return something malformed.

Concepts to master

  • Context budgetingtruncation & compaction strategies.
  • Rolling memory — summarization to fit long runs.
  • Dispatch hardening — timeouts, backoff, idempotency, concurrency limits.
  • Error classification — recoverable vs. terminal.
  • State tiers — short-term vs. persistent; memory as context management.
  • Streaming — partial parsing and cancellation.
  • Per-turn enforcement — structured output + repair at every step.
  • Prompt/response caching — avoid recomputing stable context.
  • Rate-limit & quota handling — backpressure without dropping work.
  • Idempotency keys — safe retries for side-effecting tools.
  • Observability hooks — tracing baked into the loop, not bolted on.

What you build

Take your L2 agent to production shape by injecting faults deliberately: a tool that throws, a tool that hangs (add timeouts), a model that returns garbage (add repair), a run long enough to overflow the window (add truncation/compaction). Add streaming and persistent state. It must handle every fault without crashing and without silently doing the wrong thing.

Clear it when

  • ☐ Kill a tool, feed it junk, overflow the window — it recovers or fails cleanly and loudly, never silently.
  • ☐ Context stays under budget across a long run via a strategy you designed on purpose.
  • ☐ It streams and can be cancelled mid-turn without corrupting state.
  • ☐ You can trace any run and see exactly what was in the window at each turn.

Where people get stuck

  • A loop that only works on the happy path.
  • "Send the whole history every turn" until it overflows — no truncation strategy.
  • Silent failures — swallowing errors so it looks like it worked but didn't.
  • Memory as storage rather than as a context-budget decision.

Connects

This completes the harness — the orchestration layer. The context-assembly skill here is exactly what makes subagents worth building at L6 (they exist largely to keep the parent's context clean). L5 is what lets you prove the harness is robust rather than assume it.