← All posts

What an agent loop is (and isn't): state, action, stop

What an agent loop is and isn't: its three components—state, action, and stopping condition—and why 'build me an app' is input for a chat, not an agent.

Agent loop illustration: a goal enters a cycle of decide, act, and observe that repeats until a stopping condition

An agent loop is the cycle in which a language model decides an action, that action runs, and the result feeds back in as context for the next decision, until a stopping condition is met. That repetition—decide, act, observe, repeat—is what separates an agent from a chat. A chat answers each message once; an agent runs that cycle on its own, many times, until the task is done. This is the first post in a series on how AI agents work under the hood, and it starts with the piece that gives the whole thing its name: the loop.

TL;DR
  • An agent loop has three pieces: a state (what the agent knows so far), an action (what it does each turn), and a stopping condition (when it decides it's done).
  • The difference from a chat isn't the model, it's who runs the cycle: in a chat you run it (read, run, ask again); in an agent the program does.
  • "Build me an app" is a prompt for a chat and a goal for an agent. Same sentence, two different architectures.

In this article:

What an agent loop is

A language model, on its own, does one thing: it takes text and produces text. One input, one inference, one output. It doesn’t run anything, doesn’t remember what came before, doesn’t check whether it got it right. Each call is independent and ends the moment the model stops writing.

An agent wraps that inference in a cycle. The model’s output is no longer the final answer but a decision: “run this command,” “read this file,” “search for this.” The program executes that decision, captures the result, and hands it back to the model as new context. Then the model decides again, with more information than before. That turn repeats until the task is done.

The new piece isn’t the model, it’s the cycle around it. The same model that would answer once in a chat gets called ten or fifty times inside a loop, accumulating context at each step. That’s why an agent can solve multi-step tasks a chat can only describe: not because the model is more capable, but because its output feeds back instead of ending.

The three components: state, action, and stopping condition

Every agent loop, however simple or complex, comes down to three pieces. If you understand these three, you understand the whole pattern.

State. It’s everything the agent knows at this point: the goal, the history of actions it has already taken, and the results it got. The state grows on every turn, because each action and its result get added to the context. The first entry in the state is the goal; the last is what it just observed.

Action. It’s what the agent does on each iteration. Almost always it’s calling a tool: running a command, reading or writing a file, doing a search, calling an API. One detail that matters and that the series will keep repeating: the model doesn’t execute anything. The model chooses the action; the program runs it. That separation is what makes the loop safe and debuggable.

Stopping condition. It’s the rule that cuts the cycle off. It can be the model emitting a “done” action, a verifiable goal being met (the tests pass, the file exists), or an iteration cap as a safety net. Without a clear stopping condition, an agent either doesn’t finish or doesn’t know it already has.

The fastest way to pin down these roles is to see who handles each one:

ComponentWhat it isWho handles it
StateThe goal plus the history of actions and resultsThe program accumulates it
ActionThe decision of what to do this turnThe model chooses it, the program runs it
Stopping conditionThe rule that decides when to cut offThe program checks it

The split in that last column is the center of the pattern: the model provides the judgment (what to do now), and the program provides the execution and the control (doing it and deciding when to stop). Confusing those two roles is the cause of most agents that misbehave.

Chat or agent: why “build me an app” changes meaning

The clearest way to see the difference is to take a single sentence—“build me an app”—and drop it into both systems.

In a chat, “build me an app” is a prompt. The model produces a block of code and its job ends there. If the code doesn’t compile, the one running the cycle is you: you read the error, paste it back, ask for a fix, run it again. The chat does one inference per message; the loop—try, observe, correct—is something you run, by hand, from the outside.

In an agent, “build me an app” is a goal. The agent writes the code, runs it itself, reads the error that comes out, fixes it, and runs again, until the tests pass or it gives up. The loop lives inside the program. You gave the goal once; the try-and-fix cycle runs on its own.

CHAT                                AGENT

"build me an app"                   "build me an app"  (goal)
      │                                   │
      ▼                                   ▼
   model                          ┌──► model ──► action ──► result ─┐
      │                           │                                 │
      ▼                           └──────────── state ◄─────────────┘
   output                                        │
      │                                 stopping condition?
   (you stop,                                    │
    run the loop                        yes ──► deliver
    by hand)

Same sentence, two architectures. And the difference isn’t the model’s intelligence or the size of the prompt: it’s where the loop runs. In a chat you run it, step by step; in an agent the code runs it. That shift—from the human to the program—is all that “agent” means.

What an agent loop is not

The title promises to say what an agent loop is not, too, because that’s where the confusion piles up. Three things get mistaken for an agent and aren’t:

  • A single chat turn, even with tools. A call with tool calling that runs a function and answers once isn’t a loop; it’s an inference with one extra step. It becomes a loop only when the tool’s result feeds back into the model and it decides another action. One turn isn’t a cycle.
  • A fixed chain of prompts. If you wrote the sequence of steps and it’s always the same—first summarize, then translate, then classify—that’s a deterministic workflow, not an agent. An automation pipeline with n8n is exactly that: the order is already decided before it runs. An agent decides the next action at runtime, not before.
  • A script with an LLM in a loop. Calling the model inside a for loop doesn’t make it an agent if the model doesn’t choose the actions or when to stop. Autonomy isn’t in the repetition, it’s in the decision being the model’s on every turn.

The question that really classifies a system isn’t “does it use an LLM?” but “who decides the next step?” If the answer is you, or a fixed diagram you drew ahead of time, it’s a workflow. If the answer is the model, turn by turn, it’s an agent.

This distinction isn’t vocabulary purism. A workflow and an agent are built, tested, and debugged in different ways. Calling a workflow an agent leads to giving it autonomy it doesn’t need; calling an agent a workflow leads to not giving it the guardrails it does.

The loop in pseudocode

With everything inessential stripped away, an agent loop is a while. This is the minimal form, with the three components marked:

# The agent loop, no frills.

state = initial_context(goal)            # the goal is the first entry in the state

while not done(state):                   # ← stopping condition
    action = model.decide(state)         # ← the model CHOOSES the action
    result = execute(action)             # ← the program RUNS it (tool, command, API)
    state  = state + action + result     # the observation feeds back into the state

return state

Four lines inside the while and that’s everything: the state goes in, the model decides, the program runs, the result returns to the state. Each iteration is a turn of the agent. The only thing that changes between a toy agent and a production one is which tools execute can call, how well the state is managed as it grows, and how robust the stopping condition is.

That stopping condition is almost never a single thing. In practice it combines the model’s decision with a hard cap, so the cycle is never infinite:

def done(state):
    if state.last_action == "finish":     # the model decided it's done
        return True
    if state.iterations >= MAX_ITER:      # safety net: never an endless loop
        return True
    return False

The first condition is autonomy: the model signals it met the goal. The second is control: no matter what, the loop stops. A well-built agent always has both. Only the first plus a model error leaves a process spinning forever; only the second and the agent cuts off halfway through tasks it hadn’t finished yet.

In production that hard cap is rarely a single iteration counter. It usually also includes a time limit, a token or cost budget, cycle detection—the model repeating the same action without progress—and, for risky actions, human approval before running. All of it is the same idea: the control lives outside the model, in the program that wraps it. It’s probably the most-neglected part of the design, and the one that costs the most when it’s missing.

One honest caveat about that while: it’s the right mental model, but not always the literal implementation. In real systems the loop often takes the shape of a state machine, a graph (as in LangGraph), or an event-driven flow, and the reasoning on each turn can follow named patterns—ReAct, plan-and-execute, reflection—that reorder the steps. Underneath all of them sits the same cycle: decide, act, observe, repeat. The while is the essence; the rest is how that essence gets organized as the task grows and the loop stops being a single piece and becomes part of a larger architecture.

The vocabulary for the rest of the series

This post pins down the terms the rest of the series will take for granted. Worth making them clear once:

  • State (or context): everything the agent knows at a given moment. The goal plus the history of actions and observations.
  • Action: the model’s decision on a turn. Usually, calling a tool.
  • Observation: the result of running an action, returned to the state.
  • Iteration (or turn): one full pass of the loop: decide, act, observe.
  • Stopping condition: the rule that ends the cycle, almost always a mix of “the model says it’s done” and “the cap was reached.”
  • Autonomy: the model deciding the action and the end, not the code around it.

With these six terms you can describe any agent, however sophisticated. The next posts in the series go into each piece separately: how tools are designed, how state is managed when the context fills up, and how stopping conditions are tuned so the agent neither cuts off too early nor keeps spinning.

Frequently asked questions

Is a chatbot with tools already an agent?

Not just by having tools. If the model calls a function, gets the result, and answers once, that’s an inference with one extra step, not a loop. It becomes an agent when the tool’s result feeds back into the model and it decides the next action, repeating the cycle until a stopping condition. The line is the feedback, not the presence of tools.

What’s the difference between an agent and a prompt workflow?

Who decides the order of the steps. In a workflow you wrote the sequence and it’s fixed: always the same steps in the same order. In an agent the next action is decided by the model at runtime, based on what it observed up to that point. A workflow is predictable and easy to debug; an agent is flexible but needs guardrails. Many real problems are better solved with a workflow, and it’s best not to turn into an agent what doesn’t need to be one.

What happens if the agent never decides to stop?

That’s why the stopping condition is almost never just “the model says it’s done.” A hard cap on iterations (or time, or cost) is added that cuts the loop off no matter what. If you rely solely on the model deciding to stop, a single misjudgment leaves the process spinning and burning tokens without progress.

Do I need a framework to build an agent loop?

No. The core is a while with three pieces: state, action, and stopping condition. You can write it by hand in any language. Frameworks add utilities—tool management, memory handling, traces—that help as the agent grows, but none is needed to understand it or to get started. Starting without a framework is often the best way to understand what each one does under the hood.

Does the model really “decide,” or does it follow rules?

It decides in the operational sense: given the current state, the model produces the next action, and that choice wasn’t written into the code ahead of time. It’s not human will or reasoning, but it’s not a fixed rules table either: it’s the difference between a program where the path is hardwired and one where the model picks the path on every turn. That runtime choice is exactly what sets an agent apart from a workflow.

Conclusion

An agent loop is nothing magical: it’s a while cycle with three components—state, action, and stopping condition—around a model that, instead of answering once, decides the next action over and over until it’s done. The test for whether something is an agent isn’t whether it uses an LLM, but who decides the next step; if the answer is the model, turn by turn, it’s an agent. With that vocabulary pinned down—state, action, observation, iteration, stopping condition, autonomy—the series can go into each piece separately. The next post drops from concept to code with the simplest agent that works: a write-test-fix loop where you write the tests and the model writes the code until they pass.

Keep reading