Skip to content

1.1 The agent loop

The whole of “an AI agent” fits in one sentence: a model that can ask to use tools, wrapped in a loop that keeps calling it until it stops asking.

That’s it. Everything else in this guide is about making that loop survive the real world. But first you have to see the loop clearly — so let’s watch one run.

The agent below has one job: figure out how many days until a deadline. It can’t look up dates on its own, so it has two tools: getToday() and getDeadline().

Step through it. Notice the rhythm — think, act, observe — and notice that the model never does anything itself. It only ever asks.

TaskHow many days until the project deadline?
TASK

The task arrives

A person hands the agent a goal in plain language. The model has not run yet — this is just the starting text.

thinkactobserve↻ repeat
Event log
taskHow many days until the project deadline?
Step 1 of 7

Read the event log top to bottom and you’ll see the same three moves repeat:

  • Think — the model reads everything so far and decides the next move. Sometimes that’s “use a tool,” sometimes it’s “I’m ready to answer.”
  • Act — when the model asks for a tool, the program around it runs that tool. The model has no hands; it only produced a request.
  • Observe — the tool’s result is handed back to the model as more text, and the loop turns again.

The loop ends the moment the model answers without asking for a tool. That single rule — “stop when it stops asking” — is the entire control flow.

If you write code, here is the loop you just watched, in about ten lines. If you don’t, read it as a recipe — every line maps to something in the demo.

async function runAgent(task: string) {
const messages = [{ role: 'user', content: task }];
while (true) {
const reply = await model(messages); // THINK
messages.push(reply);
if (!reply.toolCall) {
return reply.text; // DONE — it stopped asking
}
const result = await tools[reply.toolCall.name](reply.toolCall.args); // ACT
messages.push({ role: 'tool', content: result }); // OBSERVE
}
}

Ten lines. It works. You could demo it on stage tomorrow and it would look like magic.

Because this loop is a script with a model in the middle, and scripts break in production in ways that are invisible on stage:

  • What happens if the process crashes right after ACT sends a real email?
  • What stops a tool from doing something catastrophic?
  • What happens after 200 steps, when messages is enormous and expensive?
  • What if the task really needs five specialists, not one generalist?
  • What if a step needs a human to say “yes” first — and that human is asleep?

Each of those is a real failure mode, and each has a name and a fix. That’s Part 1.2 — the six ways it dies, and then all of Part 2, where we build the harness that turns this fragile loop into something you’d trust with real work.

© 2026 Clifford Bernard · Content CC BY 4.0 · Code MIT ·Source