AI Agent Design Patterns That Actually Work
A practitioner's tour of the reusable patterns for building reliable LLM agents, and when each one earns its keep.
Key takeaways
A practitioner's tour of the reusable patterns for building reliable LLM agents, and when each one earns its keep.
On this page
AI Agent Design Patterns That Actually Work#
Most "agent frameworks" sell you an architecture before you have a problem. In practice, a handful of patterns cover the vast majority of what teams actually ship. Learn the patterns, understand the tradeoffs, and you can pick the smallest thing that solves the job. This is the pattern-level companion to our building AI agents guide.
Here is the uncomfortable truth up front: a plain reason-act loop with two or three well-designed tools beats an elaborate multi-agent graph almost every time. Start there. Reach for more structure only when you can name the specific failure the extra structure fixes.
The patterns#
1. ReAct (reason and act)#
The workhorse. The model thinks about what to do, calls a tool, reads the result, and repeats until it can answer. Reasoning and acting interleave, so each tool result informs the next decision.
When to use: Almost always as your default. It handles open-ended tasks where you cannot predict the steps ahead of time, like debugging, research, or querying systems until you have enough to answer.
def react_agent(question, tools, max_steps=8):
scratchpad = []
for step in range(max_steps):
thought, action = model.decide(question, tools, scratchpad)
if action.name == "final_answer":
return action.args["text"]
result = tools[action.name](**action.args) # observe
scratchpad.append((thought, action, result))
return "Stopped: step limit reached. Best effort: " + summarize(scratchpad)
Note the max_steps. Without a hard ceiling, a confused agent will loop forever, burning tokens and money. Every loop pattern needs a step limit and a graceful exit.
2. Planning (plan and execute)#
Instead of deciding one step at a time, the agent first decomposes the goal into an ordered set of subtasks, then executes them. The plan is explicit and inspectable before any action runs.
When to use: Multi-step tasks where the shape is known in advance and order matters, like a data migration or a release checklist. Planning also helps when a task is long enough that a pure ReAct loop drifts off course. The downside: a plan made up front can go stale, so allow re-planning when reality diverges from expectation.
3. Reflection (self-critique)#
The agent produces an output, then reviews its own work against the goal or a rubric, and revises. It is the difference between a first draft and a checked draft.
When to use: Quality-sensitive output where a second pass measurably helps, like generated code, structured extraction, or writing that must meet a spec. Cap the revision loop at one or two passes; reflection has sharply diminishing returns and can talk itself into worse answers. A separate critic model or an objective check (does the code compile, do the tests pass) beats self-grading.
4. Tool use (function calling)#
The foundation everything else sits on. You expose functions with typed schemas, the model picks one and fills in arguments, your code runs it and returns the result. Get this right and simple patterns carry you far; get it wrong and no architecture saves you.
What matters: Tight schemas with clear descriptions and enums so the model cannot pass garbage. Validation on every argument before you touch a real system. Idempotency where you can manage it. And confirmations or gates on anything destructive, so a write or a delete does not fire on a hallucinated argument. We go deep on this in tool design, boundaries, and confirmations.
5. Router (classify then dispatch)#
A lightweight classifier reads the input and routes it to the right handler, prompt, or specialized sub-agent. The router itself does no heavy lifting; it just decides where the work goes.
When to use: You have distinct request types with different needs, like a support system splitting billing, technical, and account questions. Routing keeps each path's prompt and toolset small and focused, which improves both accuracy and cost. Keep the router dumb and fast, and log its decisions so you can audit misroutes.
6. Human-in-the-loop#
An approval gate pauses the agent before a high-stakes step and waits for a person to confirm, edit, or reject. The agent proposes; a human disposes.
When to use: Anything with real consequences, like sending money, deleting production data, emailing customers, or merging code. Do not gate everything or people learn to rubber-stamp. Gate the specific actions where a wrong call is expensive or irreversible, and give the reviewer enough context to make the decision in seconds.
7. Memory (scratchpad vs retrieval)#
Two different things wear the same name. Short-term memory is the working scratchpad within a task: the running list of thoughts, actions, and observations that lives in context. Long-term memory is retrieval across sessions: you store facts, past decisions, or documents and fetch the relevant slice when needed.
When to use: Short-term memory is inherent to any multi-step loop. Reach for long-term memory when the agent needs to remember across sessions or ground its answers in a knowledge base. Do not stuff everything into context; retrieve the relevant few items on demand. We cover the split in memory.
Which pattern when#
- Open-ended task, unknown steps: ReAct.
- Known multi-step workflow, order matters: Planning, with re-planning allowed.
- Output quality must clear a bar: add Reflection, capped at one or two passes.
- Distinct request types: Router in front.
- Irreversible or expensive actions: Human-in-the-loop gate on those actions only.
- Needs to recall across sessions or ground answers: long-term Memory via retrieval.
- Every case: solid Tool use underneath, plus step limits and evaluation.
These compose. A real system is often a router in front of a couple of ReAct loops, with tool-level confirmations on the writes and reflection on one high-value output. You are stacking patterns, not choosing one.
Do not skip evaluation#
Patterns are hypotheses about what will work; evaluation tells you whether they did. Build a set of real tasks with known-good outcomes and score changes against it before and after you add complexity. Most of the time the eval will tell you the fancy addition did not help, which is exactly the feedback you want before production. Track cost and step counts alongside accuracy, because an agent that is right but takes twenty tool calls is its own kind of broken.
The call we'd make#
Start with a single ReAct loop, two or three genuinely useful tools with tight schemas, a hard step limit, and confirmations on anything that writes. Ship that. Add a router only when you have clearly different request types, planning only when the loop drifts on long tasks, reflection only where an eval shows it lifts quality, and long-term memory only when the agent must remember across sessions.
Every pattern past the first ReAct loop should earn its place by fixing a failure you can name and measure. If you cannot point at the problem it solves, you do not need it yet.
Get the DevOps Troubleshooting Cheat Sheet
Subscribe and get our free one-page reference for the errors that eat an afternoon — CrashLoopBackOff, OOMKilled, Terraform state locks, and more — plus new guides as we publish them.
AI Agent Observability Tools in 2026
A practitioner's guide to tracing, evaluating, and debugging LLM agents in production with the tools that actually earn their keep.
Cilium vs Istio: eBPF Service Mesh Compared (2026)
A practitioner's comparison of Cilium's eBPF, sidecar-less dataplane against Istio's Envoy sidecar and ambient mesh models.
More from AI
Explore more articles in this category
AI CLI Agents in CI: Claude Code vs Codex CLI vs Gemini CLI
Running a coding agent on a laptop is a preference. Running one in a pipeline is an architecture decision about credentials, sandboxing, and non-interactive failure.
Best Vector Databases in 2026: Do You Even Need One?
Most teams shipping retrieval do not need a dedicated vector database. Here is where Postgres runs out, and which specialist actually helps when it does.
Three LLM Providers, One Cloud Region: The September 3 Outage
ChatGPT, Claude, and Grok degraded together when Azure East US failed. Gemini stayed up. Multi-provider failover does not help when your providers share a substrate.
You might have missed
Evergreen posts worth revisiting.