What an AI Agent Actually Is
“Agent” is the most overloaded word in AI right now. It gets stuck on chatbots, cron jobs, RAG pipelines, and anything with an LLM inside. That vagueness is a real problem when your job is to build one.
This article gives the word a precise, mechanical meaning. By the end you will be able to look at any “agent” and say what it actually is, and you will have seen the whole thing in about 20 lines of code.
An agent is an LLM in a loop with tools
Here is the whole idea in one sentence: an agent is an LLM that runs in a loop, calling tools, until it decides the task is done.
Strip it into three parts:
- An LLM. The model. On its own it is a stateless function: text in, text out, no memory, no ability to act on the world.
- Tools. Functions the model can call to do things: search the web, query a database, write a file, hit an API.
- A loop. The part that makes it an agent. The model’s output is fed back in as new input, over and over, until it stops.
A single LLM call answers once and forgets. An agent keeps going: it acts, sees the result, and decides what to do next.
The loop: plan, act, observe
Every agent, no matter how fancy, is some version of this loop:
flowchart LR
START([Goal]) --> PLAN[Model decides<br/>next step]
PLAN --> ACT{Tool call<br/>or done?}
ACT -->|tool call| RUN[Run the tool]
RUN --> OBS[Feed result<br/>back to model]
OBS --> PLAN
ACT -->|done| DONE([Answer])
- Plan. Given the goal and everything seen so far, the model picks the next action.
- Act. If it chose a tool, the surrounding code runs that tool.
- Observe. The tool’s result is added to the conversation and handed back to the model.
Then it repeats. The model plans again with the new information, acts again, observes again. The loop ends when the model returns a final answer instead of a tool call.
What makes it an agent and not a workflow
This is the distinction that matters most, and the one most “agent” demos get fuzzy about.
In a workflow, you write the control flow. Step 1 retrieves documents, step 2 summarizes, step 3 emails the result. The path is fixed. You decided it.
In an agent, the model decides the control flow. You give it a goal and a set of tools, and it chooses which tool to call, in what order, and when to stop. You wrote the tools; the model wrote the plan.
flowchart TB
subgraph WF ["Workflow: you own the path"]
direction LR
A1[Retrieve] --> A2[Summarize] --> A3[Send]
end
subgraph AG ["Agent: the model owns the path"]
direction LR
G[Goal] --> M[Model picks<br/>each step] --> T[Tools]
T --> M
end
That is the trade. An agent is more flexible, because it can handle tasks you did not script. It is also less predictable, because you no longer control the exact steps. Most of the hard parts of building agents come straight from that loss of control.
Why a loop instead of one big prompt?
You could try to do everything in a single prompt: “here is the goal, here are the tools, write out all the steps and results.” It falls apart fast.
The model cannot know a tool’s result before the tool runs. If it needs the output of a database query to decide the next step, it has to actually see that output first. A single prompt forces the model to guess, and it will happily produce a plausible-looking result that is wrong.
The loop fixes this by grounding each step in real output. The model proposes one action, the code runs it, and the real result comes back before the model plans again. Each decision is made with actual information instead of a guess.
The whole thing in ~20 lines
Here is a minimal agent loop. No framework, just the shape:
def run_agent(goal, tools):
messages = [{"role": "user", "content": goal}]
while True:
# PLAN: ask the model what to do next
response = model.call(messages, tools=tools)
messages.append(response.message)
# DONE: no tool call means the model is finished
if not response.tool_calls:
return response.text
# ACT + OBSERVE: run each requested tool, feed results back
for call in response.tool_calls:
result = tools[call.name](**call.arguments)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": str(result),
})
That is a working agent. Everything else, planning strategies, memory, multiple agents, is elaboration on this core. If you can read this loop, you understand agents.
Where the loop breaks
The loop is simple. Making it reliable is not. The failure modes show up immediately once you run one:
- It never stops. The model keeps calling tools in circles and never returns a final answer. Without a step limit, this burns tokens until you kill it.
- It calls the wrong tool, or the right tool with wrong arguments, then acts on the bad result.
- It loses the thread on long tasks as the conversation grows past what the model tracks well.
- A tool fails and the model does not know how to recover, so it retries the same broken call.
None of these mean agents do not work. They mean a demo agent and a production agent are different things, and the difference is the reliability work.
Common beginner mistakes
- No step limit. Always cap the loop iterations. A runaway agent is a runaway bill.
- Vague tool descriptions. The model picks tools from their descriptions. Fuzzy descriptions mean wrong choices.
- Calling it an agent when it is a workflow. If you scripted the steps, it is a workflow. That is often the better choice; do not add autonomy you do not need.
- Trusting tool arguments blindly. The model generates the arguments. Validate them before running anything with side effects.
- Skipping observation. Summarizing or dropping a tool’s result before the model sees it defeats the point of the loop.
Questions you will face in production
“How do I stop an agent from looping forever?” Cap the number of iterations, and give the model a clear way to signal it is done. Many teams also add a cost or time budget that ends the loop regardless. Treat the step limit as a hard safety rail, not a rare edge case.
“Should this feature even be an agent?” Ask whether the steps are known in advance. If they are, write a workflow: it is cheaper, faster, and predictable. Reach for an agent only when the path genuinely depends on what the model finds along the way.
“How do agents call tools under the hood?” Through the model’s tool-calling (function-calling) support. The model returns a structured request to call a named function with arguments; your code runs it. If you want a standard way to expose those tools across different apps, that is what MCP is for.
What to remember
- An agent is an LLM in a loop with tools, running until it decides it is done
- The loop is plan, act, observe, repeated
- The model owns the control flow; that is what separates an agent from a workflow
- Agents are flexible but less predictable, and the hard parts come from that
- Prefer a workflow when the steps are known; use an agent only when they are not
- A working loop is ~20 lines; reliability is the rest of the work
What to study next
You have the core loop. The reliability problems above, stopping conditions, tool design, state, and recovery, are where this curriculum goes next.
For grounding right now, two live pieces help: read what LLMs actually are if the “stateless function” framing was new, and read what MCP is to see how tools get exposed to a model in a standard way.
Further reading
- Anthropic: Building effective agents. A practical breakdown of agents versus workflows and when to use each. Start here.
- ReAct: Synergizing Reasoning and Acting in Language Models. The paper behind the plan-act-observe pattern most agents use.
- Anthropic: Tool use documentation. How function calling works at the API level, the mechanism under every agent.
Where this article comes from. This is a synthesis of common practice in AI engineering as of 2026, not a citation of any single paper. The sources above are where the mechanics come from. If you find an error or have a better source for a claim, the article gets fixed within a day, send me a note.