Skip to content
essayarchitecturetechnical foundersagent builders

The Loop: How Coding Agents Actually Execute

By James Han

·

Apr 2, 2026

·

3 min read

production reliabilityverification loopsagent architectureLinearClay

The first agent I built could plan beautifully. It would read files, propose edits, even describe what tests to run. Then it would announce "Done!" and move on — leaving behind code that didn't compile.

The model thought it was done. The code disagreed.

The runtime controls the loop, not the model

The pattern that fixed this is deceptively simple: the model proposes actions, but the runtime decides when to stop. It's a state machine with three phases — context, action, verify — and the agent cycles through them until exit criteria are met.

while not done and iteration < MAX:
  prompt = assemble_context(session)
  response = model.generate(prompt, schema)

  if response.type == "plan":
    session.plan = response.plan

  if response.type == "tool_calls":
    for call in response.calls:
      result = gateway.execute(call)  // pattern 01
      session.observations.append(result)

  if response.type == "final":
    verification = run_tests(session)
    if verification.passed:
      done = true
    else:
      session.observations.append(verification.failures)
      // loop continues — model sees what failed

The critical detail: when the model says "final," the runtime doesn't trust it. It runs verification — tests, linting, diff review — and only marks the session complete if verification passes. If it fails, the failure observations go back into the prompt and the loop continues.

Flat beats fancy

I experimented with tree-based execution — branching plans, backtracking, parallel exploration paths. They were harder to debug, harder to trace, and didn't produce better results.

A flat, single-threaded loop with observations is more reliable. Each iteration: assemble context, ask the model, execute actions, verify. The model sees everything that happened before. Simple state, simple debugging.

The verify phase is non-negotiable

Skipping verification to save tokens is the most expensive optimization I've made. Without it, the model completes work based on its own assessment. Its assessment is often wrong — especially for code changes where a small edit can break a distant test.

The verification phase catches errors that compound. An unverified edit in iteration 2 creates confusion in iteration 5, which leads to a rollback in iteration 8. Verification in iteration 2 would have cost 200 tokens. The cascade cost 4,000.

The anti-pattern: model-controlled termination

When the model decides it's done, it optimizes for confidence, not correctness. It generates a plausible summary, marks the task complete, and moves on. The code might be broken. Tests might be failing. But the model said "Done!" so the session ended.

Runtime-controlled termination means the model can't lie its way out. Tests pass or they don't. The diff is scoped or it isn't. Exit criteria are checked by code, not by vibes.

The takeaway

The agent loop is the heartbeat of your system. Keep it flat. Keep it simple. And never let the model decide when it's done — that's the runtime's job.

Next: Why Your Agent Needs a Policy Engine


I write about this when I have something worth saying.