DEVELOPER GUIDE PATTERNS + PRACTICES

AI architecture: design patterns and best practices

Most AI systems are built from a small set of recurring shapes. Knowing them means you reach for the simplest one that solves the problem, instead of defaulting to a fully autonomous agent for a job a straight pipeline could do more cheaply and reliably.

01
WHY IT MATTERS

Why AI systems need deliberate architecture

A model call is probabilistic, not deterministic — the same input can produce a slightly different output twice in a row. It's also slow and costly relative to normal code, and it can fail in ways a function call can't: a confidently wrong answer, a malformed tool call, a hallucinated fact.

Architecture is how you contain that. The right pattern breaks a big, fuzzy task into smaller pieces the model is reliably good at, adds checks where mistakes are expensive, and keeps the system's cost and latency proportional to how hard the task actually is.

02
PATTERNS

Six recurring design patterns

These range from simplest to most autonomous. Start from the top and only move down the list when a simpler pattern genuinely can't do the job.

1. Prompt chaining

Break one big task into an ordered sequence of smaller model calls, each working from the previous one's output. Best for a task that decomposes cleanly into fixed stages — draft, then check facts, then adjust tone.

Step 1 Step 2 Step 3 Output
Each stage's output becomes the next stage's input — simple, predictable, easy to debug one step at a time.

2. Routing

Classify the input first, then send it down a specialized path built for that category. Best when requests fall into distinct types that each deserve a different prompt, model, or tool set.

Input Classifier Handler A Handler B Handler C
One classification step keeps each downstream prompt short, focused, and easier to get right.

3. Parallelization

Run several model calls at once on the same input — either splitting the work into sections, or running the same prompt multiple times and voting on the results. Best for cutting latency or improving reliability through consensus.

Input Model call 1 Model call 2 Model call 3 Aggregate
Fan out to run calls concurrently, then combine or vote on the results.

4. Orchestrator–workers

A central model breaks an open-ended task into sub-tasks it can't fully predict in advance, and dispatches each to a worker. Best when the number and shape of sub-tasks genuinely depends on the specific input.

Orchestrator Worker A Worker B Worker C results merged back by the orchestrator
Unlike routing, the orchestrator decides the sub-tasks dynamically rather than picking from a fixed set of paths.

5. Evaluator–optimizer

One model generates a response; a second call — or the same model in a different role — critiques it against explicit criteria and sends it back for revision. Best when quality is easy to judge but hard to get right on the first attempt.

Generator draft Evaluator needs revision Accepted
The loop between generator and evaluator repeats until the output passes, or a retry limit is hit.

6. Retrieval-augmented generation (RAG)

Look up relevant information from an external source before generating an answer, instead of relying only on what the model already knows. Best when answers must be grounded in specific, current, or private data.

Query Retriever vector / doc store Model query + retrieved context Answer
The model reasons over retrieved passages instead of guessing from memory alone — reducing hallucination on facts it was never trained on.
03
CHOOSING

Step by step: picking the right pattern

  1. Write down the task as fixed steps

    If you can describe it as "always do A, then B, then C," you likely need nothing more than prompt chaining — don't reach for autonomy you don't need.

  2. Check whether inputs fall into distinct categories

    If requests cleanly split into a few types that need different handling, add a routing step before you build separate pipelines for each.

  3. Check whether steps can run independently

    If sub-tasks don't depend on each other's output, parallelize them instead of running them one after another.

  4. Check whether the sub-tasks are predictable in advance

    If you can't know ahead of time how many pieces a task breaks into, that's the signal for an orchestrator-workers setup rather than fixed routing.

  5. Check whether quality is easy to judge but hard to nail first try

    Tasks like precise translation or code that must pass tests benefit from an evaluator-optimizer loop layered on top of whichever pattern generates the draft.

  6. Check whether the model needs facts it wasn't trained on

    Private documents, current data, or anything post-dating training data calls for retrieval — add RAG regardless of which control-flow pattern you land on.

  7. Only then consider a fully autonomous agent

    Reach for an open-ended tool-calling loop when the path truly can't be predetermined by any of the above — it's the most flexible pattern and also the hardest to test and the most expensive to run.

04
BEST PRACTICES

Practices that hold up in production

05
PITFALLS

Anti-patterns worth avoiding