Agent loops:the robot costumehides a while loop.
Your application asks a model what to do next, runs the chosen tool, feeds the result back, and decides whether another turn is allowed. Useful autonomy is a controlled feedback cycle—not an endless inner monologue.
- DISCRETEmodel calls
- STATEFULevent history
- BOUNDEDby your code
The model chooses a move. The harness decides whether that move is permitted, executed, recorded, and repeated.
There is no tiny model pacing inside your server.
A model invocation ends when it returns. Your application may then run code for milliseconds, minutes, or hours before calling a model again. The continuity lives in state and history, not in a permanently running mind.
- FRAME 01HARNESSObserve
Pack the goal, current state, relevant history, and fresh evidence.
- FRAME 02MODELDecide
Return a final answer or a structured request for the next tool.
- FRAME 03APP + TOOLAct
Validate, approve if needed, then execute one bounded operation.
- FRAME 04HARNESSInspect
Record the result, errors, and any environment changes as new state.
- FRAME 05POLICYStop or continue
Check proof of success and budgets. Exit—or make another model call.
Between frames: no magical background “thinking.” Just your runtime executing code, waiting on tools, persisting state, or pausing for a human.
The exit policy writes the ending.
Same goal. Same tools. Same first error. Change only what the harness considers a reason to stop, and watch the run recover, abandon the task, or chew through its fuse.
- T01OBSERVEOne failing auth test
- T02DECIDEPatch the stale assertion
- T02TOOLPatch conflict: line moved
- T03INSPECTRetryable; no change applied
- T04ACTRe-read, patch once, run tests
- T05VERIFY42 tests pass → exit
The loop treated the stale patch as evidence, retried safely, and exited when the environment proved the task was complete.
A model can suggest “done.” Your loop needs a testable definition of done—and a budget for the days when it never arrives.
Three jobs. Do not make the model impersonate all of them.
Reliable loops separate judgment from orchestration and execution. The model proposes. The harness governs. Tools touch the world.
Builds each model input, validates tool calls, carries state, enforces permissions and budgets, records the trace, and decides whether another turn happens.
Reads the current evidence and returns a bounded next action, perhaps a plan update, a tool request, a question for a human, or a candidate final answer.
Search, read, write, test, transact, or inspect. Their results reveal what actually happened—not what the model hoped happened.
After an action, inspect the environment again. A successful API response can still produce the wrong state; a failed tool call can contain exactly the evidence needed to recover.
Autonomy needs fuses, not vibes.
Most loop failures are ordinary software failures wearing novel clothes: missing termination, unsafe retries, stale state, weak permissions, and no useful trace.
- 01TERMINATIONWrite an exit predicate
Completion should be observable: tests pass, required fields exist, a cited answer meets a rubric, or the user confirms. “The model sounded finished” is not a predicate.
- 02BUDGETSInstall hard fuses
Cap turns, elapsed time, tokens or spend, tool calls, and repeated failures. A budget stop is a controlled outcome, not an embarrassing crash.
- 03RECOVERYClassify errors before retrying
Retry transient failures with backoff. Feed actionable failures back as observations. Stop or escalate permission errors, invalid requests, and repeated identical failures.
- 04IDEMPOTENCYMake repetition safe
Use idempotency keys, read-before-write checks, operation IDs, or deduplication. A timed-out payment call is not permission to charge twice.
- 05HUMAN GATEPause before blast radius
Ask for approval before irreversible, expensive, public, privileged, or ambiguous actions. Persist the run so approval can arrive without replaying completed work.
- 06STATEKeep a useful trace
Record decisions, tool inputs and results, retries, approvals, and stop reasons. Compact old history deliberately; do not let an ever-growing transcript become the control system.
Useful when dependencies matter: outline milestones, reserve resources, and make the intended path inspectable.
Useful when the environment is uncertain: take a small action, inspect reality, then choose again.
A plan is state, not scripture. Good loops can plan ahead and still change course when a tool returns ground truth.
Use a loop when the route is unknown—but progress is visible.
Agentic loops earn their complexity when each observation can legitimately change the next action. If the route is fixed, write the route.
- Repository work
The path depends on what search, edits, tests, and code review reveal.
- Open-ended research
The next query depends on gaps in the evidence, with a clear coverage rubric.
- Incident triage
Inspect signals, form a hypothesis, run a safe diagnostic, and update.
- Messy operations
Reconcile records or complete forms where each result changes the next step.
- The path is already known
Use normal deterministic code or a fixed workflow. A loop adds latency and new failure modes.
- Success cannot be observed
Without evidence or a rubric, the loop cannot know whether to continue, stop, or correct itself.
- Every action is irreversible
Redesign tools and approval boundaries before granting repeated autonomous access.
- One response solves it
Do not build a tiny bureaucracy around a question that needs one model call.
FIELD RULEGive the model freedom over the path, not freedom from constraints.
The glamorous bit is still a guarded while loop.
Frameworks package this differently, but the durable responsibilities remain: inspect, decide, gate, execute, record, verify, and stop.
async function runAgent(goal: Goal, budget: Budget) {
const state = await loadRunState(goal);
while (state.turns < budget.maxTurns) {
const observation = await inspectEnvironment(state);
state.record({ type: "observation", observation });
if (completionPolicy.isSatisfied(goal, observation)) {
return finish(state, "verified_complete");
}
state.turns += 1; // one turn = one new model invocation
const next = await model.decide({
goal,
state: state.compactView(),
observation,
tools: allowedTools,
});
if (next.kind === "ask_human") {
return pauseForApproval(state, next.question);
}
if (next.kind === "final") {
state.record({ type: "candidate_final", text: next.text });
await saveRunState(state);
continue; // verify against the environment on the next cycle
}
if (approvalPolicy.requiresHuman(next.toolCall)) {
return pauseForApproval(state, next.toolCall);
}
const result = await executeTool(next.toolCall, {
idempotencyKey: state.operationId(next.toolCall),
retry: retryPolicy.for(next.toolCall),
});
state.record({ type: "tool_result", result });
await saveRunState(state);
}
return finish(state, "turn_budget_exhausted");
}The environment may already satisfy the goal after a resume, duplicate delivery, human edit, or delayed tool completion.
Recovery needs durable facts. If the process restarts, the loop should continue from state—not replay side effects from memory.
Final text is a proposal to stop. When ground truth is available, let code or a grader confirm the claim.
Six ways to accidentally build a haunted carousel.
“The model keeps thinking between tool calls.”
Usually, the application is executing a tool or waiting. A later model call receives the accumulated state and continues from that evidence.
“More turns make the agent smarter.”
More turns buy opportunities to observe and correct. They also add cost, latency, and chances for errors to compound.
“Retry means run the same thing again.”
Only retry classified transient failures, and make side effects idempotent. Otherwise repetition may duplicate damage.
“A detailed plan removes the need to inspect.”
Plans are hypotheses. Tool results and environment state outrank the plan whenever reality disagrees.
“If it says it is done, the loop is done.”
Treat self-reported completion as a candidate. Prefer tests, state checks, graders, or human confirmation when available.
“Human approval means clicking yes on every turn.”
Approval is most useful at meaningful boundaries: irreversible, privileged, expensive, public, or intent-sensitive actions.
agent loop = model judgment + tool-grounded feedback + application control
↻ until verified done, paused, or safely out of budget