Core AI Design Patterns Every Team Uses
Router, ReAct, Planner–Executor, and Reflection patterns explained with when to use each, when not to, and a small implementation sketch for production.

Teams rediscover the same four shapes under new product names. Naming them saves design time: Router, ReAct, Planner–Executor, and Reflection cover most production LLM control flow. The skill is not memorizing the labels. It is knowing which pattern fits the job before you invent a fifth agent.
Pattern map#
| Pattern | Control idea | Use when | Avoid when |
|---|---|---|---|
| Router | Classify, then dispatch | Clear categories, cheap decision | Categories blur; need multi-step repair |
| ReAct | Interleave thought and tool use | Exploratory lookup with short hops | Long plans need an explicit schedule |
| Planner–Executor | Plan first, then run steps | Multi-step jobs with reviewable plans | Single tool call would suffice |
| Reflection | Critique and revise | High-stakes drafts, grounding checks | Latency budget cannot afford a second pass |

Router#
A router is a small model call (or rules + model) that picks a destination: FAQ bot, billing tools, human queue. Keep the router dumb and the destinations strong. The failure mode is a confident misroute; mitigate with an "unsure → clarify or default safe path" class.
type Route = "billing" | "tech" | "human";
async function route(message: string, llm: LLM): Promise<Route> {
const out = await llm.classify(message, {
labels: ["billing", "tech", "human"],
instruction: "If unsure, choose human.",
});
return out.label as Route;
}
Routers shine behind support portals and multi-skill assistants. They are a poor fit when the next step depends on what the first tool returns — that is ReAct or Planner–Executor territory.
ReAct (reason + act)#
ReAct interleaves a short rationale with tool calls until the model emits a final answer. It is the default for "look something up, then maybe look again." Keep the trail short; force a stop when tools fail twice the same way.
The production version of ReAct is less about the chain-of-thought prose and more about the observe step: tool results must be appended as data the next decision can see. If you discard tool errors, the loop hallucinates success.
Planner–Executor#
Here the model (or a cheaper planner) proposes a step list, optionally gets approval, then an executor runs tools without re-planning every token. Plans are artifacts you can show a human and diff in evals.
plan = planner.make_plan(goal) # list[{"id","action","args"}]
validate_plan(plan) # schema + policy
for step in plan.steps:
result = executor.run(step)
if not result.ok:
plan = planner.repair(plan, step, result) # bounded repairs only
validate_plan(plan)
Use Planner–Executor when steps are numerous or costly enough that "winging it" with ReAct wastes money. Skip it for one-shot extraction.
Reflection (critic) pass#
Reflection is a second call that only checks: unsupported claims, schema drift, policy breaches. It should return structured findings, not a friendlier rewrite — unless your product explicitly wants rewrite.
Real systems compose these. A Router sends billing intents to a ReAct tool loop; high-value replies get a Reflection pass before send. Composition is fine. Spaghetti — router inside critic inside planner with no budgets — is how latency and cost become inexplicable.
Anti-patterns that look clever#
- God router — dozens of micro-destinations with overlapping labels; misroute rate explodes
- Unbounded ReAct — no repeated-failure detector; the loop burns budget on the same broken tool
- Plan forever — planner rewrites the whole plan after every minor tool glitch
- Reflective soup — three critique agents debating tone while the schema is invalid
Instrumentation per pattern#
Routers need confusion matrices on live traffic (predicted route vs human correction). ReAct needs tool-error histograms and duplicate-call rates. Planner–Executor needs plan stability (how often repairs fire) and step success. Reflection needs disagreement rate between critic and final publish, plus false-positive blocks that hurt UX. If you cannot graph those, you are flying on anecdotes.
Choosing quickly in a design review#
- Is the next step known from the user message alone? → Router or single call
- Does each step depend on live tool output? → ReAct
- Do you need a reviewable multi-step schedule? → Planner–Executor
- Is wrong output worse than extra latency? → add Reflection
If you need all four on day one, your scope is too wide. Ship the thinnest pattern that passes the eval set for the job class you actually have.
A note on "multi-agent" as a pattern#
Multi-agent is not a fifth control primitive so much as a deployment topology for the patterns above: an orchestrator may use Planner–Executor while workers use ReAct under tighter allowlists. Keep the pattern vocabulary for control flow; use "multi-agent" when you are talking about isolation and permissions. Mixing the terms is how design docs become unreadable.
Budget and stop conditions per pattern#
Every pattern needs explicit ceilings or it will eat your margin:
| Pattern | Budget knobs | Stop when |
|---|---|---|
| Router | Max tokens on classify call | Confidence below threshold → safe default |
| ReAct | Max tool hops, max duplicate tool signature | Same tool fails twice with same args |
| Planner–Executor | Max plan length, max repair iterations | Repair loop exceeds N or plan invalidates |
| Reflection | Single pass by default; rewrite only if flagged | Critic returns zero blocking findings |
Encode stops in the runtime, not in prompt prose. "Please stop after five tools" is a suggestion. A counter in the orchestrator is a contract.
When patterns compose, budgets compose too. A Router → ReAct → Reflection chain can silently triple latency if each layer has its own generous default. Set a global step budget for the user-visible request and allocate slices per layer in config.
From prototype to production handoff#
Notebooks hide the boring parts: schema validation, idempotency, logging, and what happens when the router mislabels a billing message as tech support. Before you call a pattern "shipped," require:
- Structured outputs at every handoff — JSON schemas, not markdown essays between components
- Trajectory logging — which pattern fired, which tools, which repair loops
- Fallback paths — misroute → human queue; plan invalid → clarify; critic block → safe template
- Eval coverage per pattern edge — misroutes, tool failures, policy violations
The pattern name belongs in your observability tags. When on-call sees a spike in planner_repair events, they should know which workflow to open — not guess from a generic "agent_error" metric.
One more discipline worth enforcing in design review: name the failure owner. Routers fail open or closed — pick one per surface and test it. ReAct failures are usually tool or retrieval bugs. Planner failures are schema or policy bugs. Reflection failures are false positives blocking good answers or false negatives shipping bad ones. If you cannot say which team owns each failure mode, the composition is too tangled to ship.
Record the chosen pattern in the service runbook header. When a latency spike hits overnight, that one line tells on-call which control path to inspect.
Summary#
Router, ReAct, Planner–Executor, and Reflection are the workhorses of AI control design. Pick by dependency structure and risk, not by novelty. Implement budgets and schemas first; the pattern name is just how you explain the graph to the next engineer on-call.
Want premium architecture blueprints?
Be among the first to explore interactive reference architectures, implementation playbooks, and premium engineering resources at launch.
Related Articles
Recommended reading based on this topic.
Why AI Design Patterns Are Essential for AI-Native Engineering
Why pattern literacy is a core competency for AI-native systems: shared control shapes, repeatable behaviour, and governance that survives team handoffs.
Read ArticleHow AI Design Patterns Evolve as LLM Capabilities Improve
Which AI design patterns persist, simplify, or fade as LLMs improve—and how to design control shapes that survive capability jumps without endless rewrites.
Read ArticleWhy Most AI Agents Are Workflows in Disguise
Tell true agentic reasoning from deterministic orchestration in disguise — and assess whether your system chooses next steps or follows scripts.
Read Article