What are AI agents
“Agent” is one of the most overused words in AI. This lesson gives it a precise meaning: an agent is a system in which the model, not your code, decides what to do next. You will learn how that differs from a workflow, the patterns that solve most real problems without full autonomy, the parts every agent is built from, and a simple test for deciding whether you need one at all.
A precise definition
A system where a language model directs its own process: it chooses which actions to take (usually tool calls), observes the results, and decides the next action, repeating until it reaches the goal or a stop condition.
A system where your code defines the sequence of steps, and the language model performs some of those steps. The path is fixed in advance; the model fills in the content.
The key question is who controls the flow. In a workflow, you wrote the if statements and loops. In an agent, the model's output decides what happens next.
| Chatbot | Workflow | Agent | |
|---|---|---|---|
| Who decides the next step | The user | Your code | The model |
| Number of steps | One reply per message | Fixed | Variable, decided at run time |
| Tools | Optional | Called by your code | Chosen by the model |
| Predictability | High | High | Lower |
| Cost and latency | Low | Known in advance | Variable, can be high |
| Failure impact | Wrong text | Wrong step output | Wrong actions, loops, runaway cost |
The agent loop
+----------------------------------+
| goal + history + tool results |
+----------------+-----------------+
v
+-------------+
| MODEL | decides: call a tool, or finish?
+------+------+
tool call | final answer
+----------------+-----------------> done
v
+-------------+
| your code | validates and runs the tool
+------+------+
| observation (result or error)
+-----------> back to the model
Everything that makes agents useful — and risky — comes from this loop. The model can recover from errors and take as many steps as a task needs; it can also loop forever, choose the wrong tool, or act on bad information. Later lessons add the guardrails.
Five workflow patterns that often beat agents
| Pattern | How it works | Good for |
|---|---|---|
| Prompt chaining | Output of step 1 is input to step 2, with checks in between | Outline → draft → edit; extract → validate → format |
| Routing | Classify the input, then send it to a specialised prompt or model | Support tickets: billing vs technical vs sales |
| Parallelisation | Run independent sub-tasks at once, or the same task several times and vote | Checking a document against ten policies |
| Orchestrator–workers | A model splits a task into sub-tasks and other calls complete them | Changes across several files |
| Evaluator–optimizer | One call drafts, another critiques, repeat until it passes | Translation, writing to a strict rubric |
Here is routing — a workflow, not an agent: the model only classifies; your code decides what happens.
def fake_classifier(ticket: str) -> str:
text = ticket.lower()
if any(w in text for w in ("refund", "charge", "invoice")):
return "billing"
if any(w in text for w in ("error", "crash", "fails")):
return "technical"
return "general"
HANDLERS = {
"billing": lambda t: "Routed to billing prompt (has refund policy in context).",
"technical": lambda t: "Routed to technical prompt (has error-code docs in context).",
"general": lambda t: "Routed to general FAQ prompt.",
}
for ticket in ["I was charged twice", "Backup fails with E-504", "Do you have a mobile app?"]:
route = fake_classifier(ticket)
print(f"{ticket!r:<30} -> {route:<9} | {HANDLERS[route](ticket)}")
And prompt chaining with a gate: each step is a separate, simple model call, and plain code checks the result before continuing.
def step_outline(topic: str) -> list[str]:
return [f"What {topic} is", f"Why {topic} matters", f"How to start with {topic}"]
def step_draft(outline: list[str]) -> str:
return " ".join(f"{point}: ..." for point in outline)
def gate(outline: list[str]) -> bool:
return 2 <= len(outline) <= 5 # deterministic check between steps
outline = step_outline("vector databases")
if not gate(outline):
raise ValueError("outline failed the check; stop before drafting")
print(step_draft(outline))
The building blocks of an agent
| Block | Role | Covered in |
|---|---|---|
| Model | Reasons about the goal and chooses actions | LLM Fundamentals |
| Instructions | System prompt: goal, rules, when to stop, when to ask | Prompt Engineering |
| Tools | Functions the model can call to read or change the world | Tool calling |
| Memory | History of steps, plus long-term facts | A chatbot with memory |
| Loop and stop conditions | Runs the cycle; enforces max steps, budgets, and timeouts | ReAct agents |
| Guardrails | Validation, permissions, and human approval | Human in the loop |
| Observability | Traces of every step for debugging and evaluation | Evaluating LLM apps |
Do you need an agent?
Use the simplest thing that works. Ask these questions in order:
- Can one well-designed prompt do it? Then use a single call.
- Can you write the steps down in advance? Then build a workflow — it is cheaper, faster, and easier to test.
- Is the number and order of steps truly unknown until run time (research, debugging, open-ended data exploration)? Then an agent may be justified.
- Can you tolerate its mistakes? Agents compound errors across steps. Make sure actions are reversible or approved, and that you can measure success.
Small error rates multiply. If each step succeeds 95% of the time, a ten-step task succeeds only about 60% of the time (0.9510 ≈ 0.60). Fewer, more reliable steps beat clever autonomy.
- List three tasks from your work. Classify each as single call, workflow, or agent, and justify it with the questions above.
- Extend the router with an
escalateroute for angry messages that goes to a human. - Calculate the success rate of a 5-step and a 20-step task at 98% per-step reliability.
Key takeaways
- An agent is a system where the model decides the next action; in a workflow, your code does.
- The agent loop is: model chooses → code executes → result returns → repeat.
- Prompt chaining, routing, parallelisation, orchestrator–workers, and evaluator–optimizer solve most problems without full autonomy.
- Agents are built from a model, instructions, tools, memory, a loop with stop conditions, guardrails, and observability.
- Prefer the simplest design: per-step errors compound across long agent runs.