Skip to content

Skill · doctrine · agent-loop

The agent loop

Implement the agent loop in raw SDK calls: context → structured next step → execute → compact-append. Use when building an agent from scratch, hiding the loop inside a framework, adding termination/budgets/pause, or the user asks how an agent actually works.

GET /api/canon/skills/agent-loop?format=md

The model never executes anything. It emits structured intent. Code executes. The observation is data. Termination is a first-class intent, not an accident.

When

You need a loop you can pause, inspect, eval, and resume. Frameworks wrap this; they must not own it.

Do

  1. 01

    Implement it raw first

    No graph library. Read the prompt you send. Structured next step with intent: tool | done | ask_human.

  2. 02

    Budget the loop

    Max steps, max tokens, max USD, wall clock. 'Done' is a schema. execute() is the sandbox and the permission gate.

  3. 03

    Compact every observation

    Append the smallest string that enables the next correct action. Bulk → files with a pointer.

Don't

  • while True with no done schema.
  • Hide the loop so nobody can pause it.
  • Let the model 'just finish' without a budget.

Hard rules

  • Termination, sandbox, context builder, eval set, pause API — name all five.
  • execute() allow / ask / deny lives here, not in the prompt.
  • Pause serializes the blob; resume does not re-execute the side effect.

The loop

python
context = [event]
budget = Budget(max_steps=20, max_tokens=80_000, max_usd=2.0)

while True:
    budget.check(context)
    nxt = llm.determine_next_step(
        context,
        tools=allowed_tools(state),
        schema=NextStep,  # intent: tool | done | ask_human
    )
    if nxt.intent == "done":
        return nxt
    if nxt.intent == "ask_human":
        save_checkpoint(state, context)
        return await pause_for_human(nxt)
    result = execute(nxt)  # allow / ask / deny
    context.append(compact(result))

Refuse

  • Unbounded loopNo max-turns, token, wall-clock, or money budget. The agent rambles until the bill or the context dies.
  • Unowned promptThe policy lives in a framework black box you cannot diff, test, or revert.
  • HITL that cannot resumeThe human answers and the run is gone. Approval as a side channel, not a tool.

Load with this

Load next

Trigger tests

Should fire

  • Show me the agent loop
  • Implement a ReAct loop with a budget
  • How do we pause and resume the agent?

Should not

  • Explain backpropagation
  • Design the marketing site