All posts
Fundamentals

How an AI agent actually runs: the agent loop

The previous piece covered what an AI agent is made of. This one covers how it runs, because the mechanism is simpler and stranger than most explanations suggest.

The definition worth memorising

An LLM agent is a program that hands part of its control flow to a language model, letting the model decide what actions to take and when to stop, based on its current context and goals.

Control flow means the sequence of "what to do next." In traditional software that sequence is written down. The if statements, the for loops, the order of function calls: a developer decided all of it in advance. In an agent, part of that decision-making authority is handed to the model at runtime.

Authority over what happens next is the whole distinction. Intelligence and scale sit to one side of it.

Take an agent asked whether routing routine support tickets to a model would pay for itself. It opens last quarter's ticket export, counts the routine categories, looks up what the model costs today, works out the staff-hours involved, and writes up the comparison. The interesting question concerns who decided each step: which file to open first, whether the categories it found were enough, what to look up next, and when to stop gathering and start answering. None of that was hardcoded. The model decided each one on the fly, from the context it had at that moment.

Three elements make autonomy possible

For autonomous control flow to work in practice, three things come together.

The LLM is the brain. It understands the current situation and decides what to do next. Underneath, it is a model trained to predict the next token from all preceding tokens. Trained at scale on that one simple principle, it develops a working grasp of language structure, context and meaning, and generalises it to examples it has never seen. Newer reasoning models go further: instead of answering immediately, they first generate thinking tokens, which makes unfamiliar multi-step problems more tractable.

Tools extend the action space. Web search, code execution, database access. Tools are how the agent reaches anything outside its own context.

The loop unfolds the decisions over time. It runs the cycle repeatedly until the goal is met.

To put it in one line: the LLM makes autonomous decisions possible, tools expand what those decisions can touch, and the loop lets them accumulate.

Why there has to be a loop

You cannot know in advance which tools a task will need, or how many steps it will take. A question might need one search. A research task might need dozens of sources. The loop exists precisely because that count is unknowable up front.

The agent loop: check context, execute a tool, feed the result back, decide whether to continueThe agent loop: check context, execute a tool, feed the result back, decide whether to continue

The cycle runs like this:

  1. The model evaluates the current context and decides whether a tool is needed. If information is missing, it picks the tool based on what is missing.
  2. The selected tool executes.
  3. The result is added back into the model's context, enriching what it knows.
  4. The model decides whether to continue or stop. If it has enough to answer, it produces the final response. Otherwise it returns to step one.

The session workflow around that cycle is equally plain. The agent sends the model a message. If what comes back is a final response, the loop terminates and the response goes to the caller, which might be a person, another system, or a higher-level agent. If what comes back is an instruction to perform an action, usually a tool call, the agent performs it and sends the result back, continuing the loop.

The three phases, and two surprises

The loop is conventionally described in three phases: sensing, thinking, acting. Two of them work differently from how the names suggest.

Sensing. The agent perceives its environment by collecting data, observing state and changes, calling APIs, reading physical sensors, or querying a datastore. The part people miss: the trigger for sensing is always a tool call message from the model. Users or frameworks invoke an agent with a system prompt, an initial message and a set of tools, but that information goes to the model first, and the model decides whether to sense.

Thinking. Here is the first surprise. All the thinking happens inside the model: planning, reasoning, analysing earlier tool results, choosing tools, writing the final answer. The agent loop works as a conduit for exchanging messages, and thinking happens every time the loop sends a message to the model.

Hybrid systems complicate that picture. Some intercept intermediate results, process them in their own code, and decide what to do next without delegating everything to the model. But that thinking happens above the agent framework. The framework running the loop is still just a conduit; it may expose a hook where each tool result is handed up to the surrounding system, and code with domain knowledge can then shape the next interaction, modify the context directly, or terminate the loop even though the model has not produced a final response.

Acting. Here is the second surprise. Acting and sensing are indistinguishable from the loop's point of view. Both are the same shape: the loop sends a message, the model responds with a tool call, the framework executes it and returns the result. Acting is simply a tool call that changes something outside: an API write, a database update, a robot arm moving. The loop is oblivious to which is which.

The result of an action is usually a success or error message. For a long-running action it might be an identifier the model can query later for progress. Either way, the model decides how to continue. On success it may finish and terminate the loop. On failure it may retry or attempt recovery.

The whole thing in one sentence

An agent is a loop that keeps asking a model "what next?", executes whatever the model asks for, feeds the result back, and stops when the model says it is done.

while True:
    reply = model(context)              # the model decides what happens next
    if reply.is_final:
        return reply                    # it says it is done, the loop ends
    result = run_tool(reply.tool_call)  # otherwise: execute what it asked for
    context.append(result)              # and feed the outcome back in

Everything else, the frameworks, the abstractions, the orchestration layers, is arrangement around that.