What Is an Agent?
From single responses to loops of reasoning and action.
Everything you've built so far follows one pattern: send a prompt, get a response, done. One shot. But ask "What's the weather in Paris and should I pack an umbrella?" and a one-shot model can only guess — it has no weather data and no way to get any. An agent is what you get when you give a model tools and permission to keep going: it can decide to act, observe the result, and act again until the job is done.
Why does this exist?
A plain LLM call is a function from text to text — it cannot look anything up, run code, or affect the world. Real tasks ("book the cheapest flight," "find and fix the failing test") require acting, observing what happened, and adapting. Agents exist because a single forward pass can't do multi-step work, but a loop of model calls wrapped around tools can.
The problem: one shot isn't enough
Compare two requests:
- "Translate this sentence to French" — pure text-in, text-out. One model call nails it.
- "Check whether our API is down, and if so, file an incident ticket" — requires doing things: an HTTP check, a decision based on the result, a ticket-creation call. No amount of clever prompting makes a single call capable of this.
You met tool calling in the Playground module: the model can emit a structured request like get_weather({"city": "Paris"}) instead of prose, and your code executes it. That's the atom. An agent is the molecule: tool calling in a loop, with the model deciding each iteration what to do next based on everything that's happened so far.
The agent loop
Strip away every framework and every buzzword, and an agent is this:
- 1. Receive a goal"Is the API down? If so, file a ticket." — an outcome, not a single instruction.
- 2. Think (plan)
- 3. Act (call a tool)
- 4. Observe
- 5. Loop or finish
This Thought → Action → Observation cycle (popularized by the ReAct pattern) repeats until the model decides it has enough to answer — or until you stop it. In code, the skeleton is humbler than the hype suggests:
messages = [{"role": "user", "content": goal}]
while True:
response = llm(messages, tools=TOOLS) # model may answer or request a tool
if response.tool_call is None:
return response.text # done: final answer
result = execute(response.tool_call) # you run the tool
messages.append(response) # the action…
messages.append(tool_result(result)) # …and the observation
That while loop is the agent. Everything else — planners, memory, multi-agent systems — is elaboration on these ten lines.
The anatomy of an agent
Four components show up in every serious agent, whatever the framework calls them:
- The model (reasoner). Decides what to do next. All "intelligence" lives here.
- Tools. Typed functions the model can invoke: search, code execution, file access, APIs. Each has a name, description, and input schema — the model chooses among them by reading those descriptions (write them well!).
- Memory. At minimum, the growing message history — the scratchpad of thoughts, actions, and observations. Longer tasks add external memory: files, databases, or RAG over past interactions.
- The loop + guardrails. The orchestration code: run the model, execute tools, feed back results — plus limits (max iterations, budgets, human approval for dangerous actions).
Workflow or agent?
If you hard-code the sequence of steps (fetch → summarize → email), that's a workflow — cheaper, more predictable, and often the right choice. It's an agent when the model decides the control flow: which tools, in what order, and when to stop. Rule of thumb: use workflows when the path is known, agents when it isn't.
What can go wrong (a preview)
Autonomy cuts both ways. Agents can loop forever ("let me search one more time…"), compound errors (one hallucinated file path cascades into five broken tool calls), and burn tokens at an impressive rate — each loop iteration re-sends the entire growing history. This is why production agents always ship with iteration caps, spending limits, and human confirmation for irreversible actions. Judging when agent autonomy is worth its cost is a core AI-engineering skill.
Build it yourself
- Take your tool-calling code from the Playground module and wrap it in the
whileloop above, with amax_iterations = 5cap. - Give it two mock tools:
get_weather(city)(return a canned string) andsearch_web(query)(return a canned snippet). - Ask: "What's the weather in Paris and should I pack an umbrella?" Print each thought, action, and observation as it happens.
- Then break it on purpose: make
get_weatherreturn an error string and watch how the model recovers (or doesn't). This is agent debugging in miniature.
Summary
- A plain LLM call is text-in/text-out; an agent wraps the model in a loop where it can act via tools, observe results, and decide the next step.
- The core cycle: Thought → Action → Observation, repeated until the model produces a final answer.
- Anatomy: model (reasoning) + tools (typed functions) + memory (scratchpad/history) + orchestration loop with guardrails.
- Workflows (you decide the steps) beat agents (the model decides) whenever the path is predictable.
- Autonomy has costs — loops, compounding errors, token burn — so caps and human approval gates are non-negotiable in production.