The Agent Loop

Part of the free Generative AI course on LogicWiz, module: The Agent Awakens.

Episode 12: The Agent Loop

"Intelligence isn't answering in one breath. It's knowing when to stop, look something up, and think again."


The Question That Needs a Loop

A reader asks Nova:

"I'm flying to Paris today — should I pack an umbrella?"

Watch what a single LLM call does here. Nova has no live weather data, so she either shrugs or guesses.

But notice how you'd answer that question. You wouldn't reply from memory — you'd open a weather app, glance at the Paris forecast, and then say yes or no. The honest answer needs the same little dance:

  1. Think: "To answer this, I need today's Paris forecast."
  2. Act: call a weather tool with city="Paris".
  3. Observe: the tool returns "Paris, 14°C, rain expected".
  4. Think again: "Rain — so yes, umbrella."
  5. Answer: "Yes, pack an umbrella — it's due to rain in Paris today."

No single call can do that. The model has to pause mid-thought, reach for a tool, look at what came back, and only then finish. That back-and-forth is the agent loop — and it's what turns Nova from a talker into a doer.


Two Ways to Orchestrate

Before we build the loop, a fork in the road. Who decides the steps — you, or the model?

{{visual:workflow-vs-autonomous}}

Agentic Workflowyou wire the steps. The developer codes a fixed pipeline: "first classify, then route to model A or B, then summarise." Think of a factory assembly line: every item rolls through the same stations in the same order. Predictable, fast, easy to debug — but rigid. If a request doesn't fit the line you built, it can't detour.

Autonomous Agent — the model decides the steps, live. You hand it a goal and a set of tools, and the LLM works out which tools to call, in what order, adjusting as it sees results. Think of a taxi driver: you give the destination, they pick the route and reroute around traffic. Flexible and general-purpose — but slower and less predictable, since the same question might take a different path each run.

Autonomous Agent Agentic Workflow
Who orchestrates The LLM, at run time The developer, in code
Flexibility High — adapts on the fly Low — fixed path
Predictability Lower Higher
LLM calls Many (unknown ahead of time) Fixed and known
Speed Slower (more round-trips) Faster
Best for Open-ended tasks Well-defined tasks

💡 Tip: Most production systems are hybrids — a high-level workflow lays down the assembly line, and inside a single messy station, an autonomous agent improvises. You don't have to pick a side.


The Agent Loop: Think → Act → Observe

At the heart of every autonomous agent is one small, relentless cycle:

Loop ( Think + Act + Observe )

The industry name for it is ReActReasoning + Acting. It's exactly how a detective works: notice a clue, reason about it, chase down a lead, see what turns up, repeat — until the case is solved.

{{visual:react-loop}}

  • Think — the LLM reasons about the goal and the state so far, and decides the next move.
  • Act — it calls a tool, passing arguments it extracted from the task.
  • Observe — the tool runs; its result comes back and updates what the agent knows.

Then it loops. Each pass, the agent asks itself: do I have enough to answer now, or do I need another tool? When the answer is "enough," it exits the loop and replies.

The looping is what makes agents robust. When a tool errors, the Observe step catches it — and the agent can rethink, fix the arguments, or try a different tool, exactly like a GPS quietly recalculating when you miss a turn instead of stubbornly repeating the wrong directions. That self-correction is the whole point of looping instead of guessing once.


Tool Calling: How Nova Asks for a Tool

So the LLM "calls a tool." But it can't actually run your Python — it only produces text. So how does the Act step really work?

Here's the key: the model is the manager, not the machinist. It never touches the machinery itself — it writes a work order ("run get_weather with city="Paris"") and hands it to an assistant (your code), who does the actual work and reports the result back. In technical terms, the model emits a structured tool call: the name of the function it wants and the arguments it extracted from the request. Your code runs the function and returns the result. The round trip looks like this:

sequenceDiagram
  participant U as User
  participant A as Your code
  participant L as LLM
  U->>A: "Umbrella in Paris?"
  A->>L: messages + tool schemas
  L-->>A: tool_call: get_weather(city="Paris")
  A->>A: run get_weather("Paris") → "14°C, rain"
  A->>L: messages + tool result
  L-->>A: "Yes, pack an umbrella."
  A-->>U: final answer

Three pieces make this work:

1. The tool schema. You describe each tool to the model as JSON — its name, a description (the model reads this to decide when to use it), and its parameters:

get_weather_tool = {
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a city. Use when the user asks about weather.",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string", "description": "The city name, e.g. 'Paris'"}},
            "required": ["city"],
        },
    },
}

💡 Tip: The description is doing real work — it's the label on the drawer. The model picks a tool almost entirely from its description, so write it like good documentation: say clearly what it does and when to use it. A vague label, and the model reaches into the wrong drawer.

2. Detecting the call. You pass tools=[...] and tool_choice="auto". If the model wants a tool, the reply carries message.tool_calls instead of a final answer. Each call gives you tc.function.name and tc.function.arguments (a JSON string you parse).

3. Returning the result. You append the model's tool-call turn, then a tool message carrying the result and the matching tool_call_id — the receipt that tells the model which work order this answers. Then you call it again. It loops until the reply has no more tool_calls — that's your final answer.

Here's one full round trip, live:

{{visual:tool-calling-walkthrough}}

{{cell:l12-tool-calling}}

💡 A standard for all this: MCP. Hand-writing a schema for every tool works, but every team ends up reinventing it. MCP (Model Context Protocol) is an open standard — introduced by Anthropic — that lets a server expose its tools and data through one uniform interface. Instead of hardcoding each tool, an agent can ask an MCP server what tools it offers and use them on the fly — so when a backend changes, the agent adapts without you rewriting integration code. Many agent frameworks now speak MCP; we'll lean on them from Chapter V onward.

📌 Summary: Complex tasks need a loop, not a single call. Agentic workflows hardcode the steps; autonomous agents let the LLM choose them. The loop is Think → Act → Observe (ReAct). Tools are invoked by tool calls: the model emits a function name + arguments, your code runs it and returns the result with its tool_call_id, and the loop repeats until the model gives a final answer.


What Nova Learns Next

Nova can reason and act in a loop now — she's a real agent. But she's a very modern kind of agent, with an LLM brain. Agents have a longer history, and understanding the whole family makes you a sharper designer.

Next episode we rewind to first principles and meet the agent family: the twitchy reflex agent that just reacts, the model-based agent that remembers, the goal-based agent that plans, and the utility-based agent that weighs its options. You'll build each one — starting with a little robot vacuum that can't stop bumping into walls.