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.

python.python

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.