
We’ve established what an agent is (article 1) and when to use one (article 2). Now for the mechanics. Because “the model decides what to do next” sounds vague and almost mystical if you say it fast enough, but underneath, it’s a strikingly simple loop. Once you see it, agents stop being a black box and become something you can reason about, debug, and build with confidence.
This article opens up that loop. It’s the mechanism at the heart of every agent, from the toy examples you’ll build in article 8 to the large multi-agent systems in article 9. Same loop, running at different scales.
The whole loop in three words
Every agent, without exception, cycles through three phases: think, act, observe. Then it does it again. And again. Until the goal is done or a stopping condition is hit.
- Think. The language model reads what it knows so far (the goal, what’s happened, any memory) and decides what to do next. This is the reasoning step.
- Act. It carries out that decision. Usually this means calling one of the tools it has available.
- Observe. It sees the result of the action. What did the tool return? What worked, what didn’t?
Then back to thinking, with this new information added to what it knows. That’s it. That’s the whole thing. Figure 1 shows the cycle.
Figure 1: The agent loop, in its purest form. Think, using everything known so far. Act, by calling a tool or producing output. Observe, by taking the result and adding it to what’s known. Then repeat, until the goal is reached.
The elegance of this pattern is that it turns a complicated capability (autonomous multi-step problem solving) into three simple things repeated many times. Every clever agent you’ve heard of is doing exactly this loop under the hood. The differences between them come from how well they think, which tools they have, and how much they remember. But the loop shape is universal.
A tiny example that makes it concrete
Let me walk you through a very small example, so the loop stops being abstract. Suppose the agent’s goal is: “Find out what the weather is in Melbourne tomorrow, then, if it’s forecast to rain, add ‘bring umbrella’ to my reminders.”
Here’s how the loop actually runs, phase by phase.
Iteration 1
- Think: “To answer this, I need tomorrow’s Melbourne forecast. Let me use the weather tool.”
- Act: calls
weather.forecast(city="Melbourne", when="tomorrow") - Observe: the tool returns
{ "temperature_high": 18, "temperature_low": 11, "conditions": "showers", "precipitation_prob": 0.75 }
Iteration 2
- Think: “75% chance of rain is well above the threshold I’d consider likely. So I should add the reminder. Let me use the reminders tool.”
- Act: calls
reminders.add(text="bring umbrella", when="tomorrow morning") - Observe: the tool returns
{ "id": "rem_2801", "status": "created" }
Iteration 3
- Think: “Both parts of the task are done. I can tell the user.”
- Act: outputs the final message: “Tomorrow’s Melbourne forecast is 11–18°C with showers (75% chance of rain), so I’ve added a reminder to bring an umbrella.”
- No further action needed; stops here.
Notice a few things about how this ran. The agent decided, at each step, what to do based on what it had learned so far. It made two tool calls, in an order that was determined by the task itself, not by a pre-defined script. And it stopped when the goal was met, not after a fixed number of steps. That’s what makes it agentic instead of a workflow.
ReAct: reasoning and acting, made explicit
The technique that pins this loop down cleanly in real systems has a name worth knowing: ReAct, short for Reasoning and Acting. The idea, published in a lovely paper a couple of years ago, is simple: interleave the “think” step and the “act” step explicitly, so the model produces its reasoning as text and its tool calls as structured actions, alternately. The model literally writes out its reasoning before each action. It gives us a nice, inspectable trace of the agent’s thinking.
A ReAct trace for our weather example would look something like this:
Thought: I need the weather forecast for Melbourne tomorrow.
Action: weather.forecast(city="Melbourne", when="tomorrow")
Observation: {"temperature_high": 18, "conditions": "showers", "precipitation_prob": 0.75}
Thought: 75% chance of rain is high, so I should add the umbrella reminder.
Action: reminders.add(text="bring umbrella", when="tomorrow morning")
Observation: {"id": "rem_2801", "status": "created"}
Thought: The task is complete. I'll tell the user.
Action: final_answer("Tomorrow's Melbourne forecast is showers with 75% chance of rain, so I've added a reminder to bring an umbrella.")
Look at how readable that is. Every thought, every action, every observation, laid out plainly. If something went wrong, you could point at exactly which step, which is a huge debugging win. This is one of the reasons ReAct-style agents dominate in real systems: they’re inspectable. Modern implementations use structured tool-calling APIs rather than literal “Thought:/Action:/Observation:” text, but the pattern is the same.
Where the loop needs guardrails
The loop is beautiful. It’s also, left to itself, unbounded. Without safeguards, an agent could keep looping forever, or make many more calls than necessary, or spiral into confused reasoning. So every real agent has some stopping conditions built in. Figure 2 shows the key ones.
Figure 2: An agent’s loop needs bounds. Goal reached is the happy path. Maximum steps prevents runaway loops. Budget limits keep costs sane. A failure or approval checkpoint lets the agent stop and ask when something is off. Together these turn an unbounded loop into a well-controlled system.
Reading it in more detail:
- Goal reached. The natural, happy stopping condition. The agent’s most recent thought or action indicates the task is done.
- Maximum steps. A hard cap on how many iterations the loop can run. Typically small (10 to 30 steps for most tasks), because if an agent hasn’t figured it out by then, more looping usually makes it worse, not better.
- Budget limits. Since each iteration means model calls (and often tool calls too), a cost budget is a real, sensible cap. Stop before you’ve burned more than the task is worth.
- Failure or approval checkpoints. For actions with real-world consequences (send an email, spend money, delete a file), the agent stops and hands off to a human. This is the “autonomy within bounds” principle from article 1, made concrete.
Every well-designed agent has all four. Skipping any of them turns your loop into a liability.
The mental model that carries through the whole track
Here’s what I want you to take away, because it’ll carry through every article in this track. An agent is not a mysterious black box. It’s a language model, running in a loop, with tools it can call and memory to keep track of what it’s done, under stopping conditions that keep it bounded. Everything else, tool use, memory, planning, multi-agent, MCP, evaluation, security, is a specialisation or extension of this same simple picture.
When you see the same idea play out at larger scale (multiple agents coordinating, or an agent using dozens of tools), remember: it’s still just the think-act-observe loop. Only the tools, the memory, and the reasoning get more sophisticated. The shape doesn’t change.
Where we go next
Now that you can see the loop clearly, the natural next question is what the tools actually are that the agent calls in the “act” phase. Because tools are how agents actually do things in the world, and giving an agent good tools (and giving them well-described so the model can use them properly) is probably the single most important skill in this whole discipline. That’s exactly what article 4 is about.
Next in the series: Tool Use & Function Calling, how agents actually act on the world.