Why Architecture Patterns Matter
An AI agent is just a loop. But how that loop is structured: what controls the flow, how state is passed, when tools are called, and how multiple agents cooperate, determines whether the system is reliable and maintainable or brittle and expensive.
This lesson maps six foundational patterns. Real production systems usually combine two or three of them.
Pattern 1: Simple ReAct Loop
The original agent architecture, still the workhorse for moderate-complexity tasks.
flowchart LR
T([User Task]) --> R[Reason]
R --> A[Act / Tool Call]
A --> O[Observe Result]
O --> R
O --> D{Done?}
D -- YES --> ANS([Answer])
D -- NO --> R
How it works: At each step, the LLM reasons about what to do (Thought), decides on an action (Action), executes it via a tool, observes the result (Observation), and repeats until it has a final answer.
Best for: Research tasks, Q&A with tools, moderate-complexity workflows where the path is hard to predict in advance.
Failure modes: Loops (LLM keeps trying the same failing action), context exhaustion (long tasks accumulate too many observations), and getting stuck without knowing it.
Pattern 2: Plan-and-Execute
Separates planning from execution. A planner LLM first generates a list of steps; an executor agent then works through them one by one.
flowchart TD
I([Input]) --> P[Planner\nmake step list]
P --> E1[Execute Step 1]
P --> E2[Execute Step 2]
P --> E3[Execute Step N]
E1 & E2 & E3 --> S[Synthesize Results]
S --> O([Output])
Best for: Well-structured tasks where the general shape of the solution is knowable upfront, data processing pipelines, report generation, multi-step research.
Failure modes: Rigid plans that can’t adapt. If step 2 fails or reveals new information that invalidates step 3, a naive plan-and-execute system still tries step 3. Fix this with replanning nodes that re-evaluate the plan when a step produces unexpected results.
Pattern 3: Reflection / Self-Critique
The agent evaluates its own output and iterates until it meets a quality bar.
flowchart LR
I([Input]) --> G[Generator]
G --> C[Critic\nself-review]
C -->|needs revision| G
C -->|approved| O([Output])
Best for: Writing, code generation, structured data extraction where output quality must meet a threshold before being returned.
Failure modes: Infinite loops (critic always finds something to improve), expensive (every revision is another LLM call), and the critic hallucinating problems that don’t exist.
Production fix: Cap iterations (typically 2–3 max), use a deterministic evaluation function alongside the LLM critic when possible.
Pattern 4: Orchestrator-Worker (Supervisor)
A central orchestrator LLM delegates subtasks to specialized worker agents. Each worker has its own system prompt, tool set, and specialization.
flowchart LR
I([Task]) --> OR[Orchestrator]
OR --> W1[Worker 1]
OR --> W2[Worker 2]
OR --> W3[Worker N]
W1 & W2 & W3 --> OR
OR --> O([Result])
Best for: Complex tasks that naturally decompose into distinct specializations: a marketing pipeline where one agent researches, one writes, and one optimizes for SEO.
Failure modes: Orchestrator hallucinating wrong worker assignments, poor handoff protocols leading to workers duplicating effort, and the orchestrator itself becoming the token bottleneck.
Pattern 5: Map-Reduce
A coordinator fans out the same task to N parallel worker agents, each processing a chunk of data, then aggregates all results.
flowchart TD
I([Input]) --> M[Map\nfan-out]
M --> T1[Task 1]
M --> T2[Task 2]
M --> T3[Task N]
T1 & T2 & T3 --> R[Reduce\naggregate]
R --> O([Output])
Best for: Processing large datasets, batch document analysis, running the same analysis across multiple sources.
Failure modes: Unbounded parallelism (spawning 10,000 workers crashes your API rate limits), reducer getting overwhelmed by massive combined context.
Production fix: Batch workers in groups of 10–20, use a tiered reduce for very large inputs.
Pattern 6: Human-in-the-Loop
The agent pauses at critical decision points and waits for human approval before continuing.
flowchart LR
I([Input]) --> A[Agent]
A -->|needs approval| H[Human Review]
H -->|approved| AC[Execute Action]
H -->|rejected| A
AC --> A
A -->|complete| O([Done])
Best for: Any agent with real-world consequences, sending emails, making purchases, modifying production databases, posting to social media.
Implementation: LangGraph’s interrupt() primitive is purpose-built for this. The graph state is serialized to a database, the human reviews and responds, and the graph resumes from the checkpoint.
Composing Patterns: Real-World Hybrid Architectures
Production systems rarely use one pattern in isolation. A typical enterprise agent system:
flowchart TD
U([User Request]) --> R{Router}
R -->|Simple query| RL["ReAct Loop\nsingle-agent"]
R -->|Complex task| OR["Orchestrator"]
OR --> W1["Worker 1\nReAct"]
OR --> W2["Worker 2\nPlan + Execute\n+ Reflect"]
OR --> W3["Map-Reduce\nParallel Doc Scan"]
W1 & W2 & W3 --> HC{"Human\nCheckpoint\nif high-risk?"}
HC -->|approved| FIN([Final Output])
HC -->|rejected| OR
style R fill:#EEF0F7,stroke:#6366F1,color:#0F172A
style OR fill:#EEF0F7,stroke:#818CF8,color:#0F172A
style HC fill:#fff7ed,stroke:#f59e0b,color:#0F172A
This lesson gives you the vocabulary. Every technique in this course maps onto one or more of these patterns. When you encounter a new agent framework feature, ask yourself: “Which pattern does this implement, and what failure mode does it prevent?”