Thousands of teams have built LLM-powered agents that work flawlessly in notebooks and demos. Fewer teams have shipped them to production. The difference isn't talent or effort — it's design patterns. A pattern that feels like a minor optimization in isolation becomes the difference between an agent that handles edge cases gracefully and one that crashes silently under load.

This article distills five architectural patterns from production deployments and research: ReAct (the thinking loop), planning agents (task decomposition), tool-augmented reasoning, multi-agent orchestration, and human-in-the-loop feedback. For each pattern, I'll walk through the failure modes that motivate it, the implementation tradeoffs, and when to apply it. These patterns form the foundation of Building Agentic AI Systems, my Packt book on production agentic architecture.

Why Agent Demos Fail in Production

The typical agent demo follows a happy path: (1) user asks a question, (2) agent reasons about the question, (3) agent calls a tool, (4) tool returns a clean result, (5) agent formulates a confident answer. The failure modes don't appear until production:

The five patterns address these failure modes head-on. They're not theoretical — they're battle-tested solutions to problems you will encounter at scale.

Core Insight

Production agents don't think harder; they think differently. They decompose problems into smaller, bounded tasks. They enforce tool-use contracts. They hand off work to specialized agents. And critically, they give humans a way to intervene before damage is done.

Pattern 1: ReAct — The Foundation

ReAct stands for Reasoning + Acting. It's the simplest production pattern and the foundation that all others build on. The idea: instead of asking an LLM to produce a single response, ask it to interleave reasoning steps with tool calls, with observations from those calls informing the next reasoning step.

The loop looks like this:

Thought: I need to find the user's account balance.
Action: get_account_balance(user_id=12345)
Observation: Balance is $4,230.50
Thought: The user has sufficient funds. I should process the withdrawal.
Action: process_withdrawal(user_id=12345, amount=1000)
Observation: Withdrawal successful. New balance: $3,230.50
Thought: The withdrawal is complete. I can now report to the user.

Why does this work better than a single end-to-end LLM call? Three reasons:

  1. Observability. You can see exactly what the agent thought and what it did at each step. When something goes wrong, the trace is legible.
  2. Grounding. Each thought is immediately validated against real data from tool observations. The agent can't hallucinate — it must reason about data it actually received.
  3. Recoverable errors. If a tool call fails, the agent sees the failure as an observation and can reason about how to retry or work around it.

Implementation: Structured Tool Use

The naive ReAct implementation asks the LLM to output free text like Action: get_balance(12345) and then parses it with regex. This is brittle — the model might output variants like I'll use the get_balance function with 12345, and your parser breaks.

Modern LLM APIs solve this with structured tool declarations. You define your tools as JSON schemas:

{
  "name": "get_account_balance",
  "description": "Retrieve the current account balance",
  "parameters": {
    "type": "object",
    "properties": {
      "user_id": { "type": "integer" }
    },
    "required": ["user_id"]
  }
}

You pass this schema to the API along with your prompt. The model's response is guaranteed to include a structured tool-call object, not text you have to parse:

{
  "type": "tool_use",
  "id": "call_abc123",
  "name": "get_account_balance",
  "input": { "user_id": 12345 }
}

This eliminates parsing errors entirely. Your code is also simpler: no regex, no ambiguity, no silent failures. (I cover the gory details of function calling APIs in Chapter 3 of Building Agentic AI Systems.)

When ReAct Is Enough

ReAct handles single-goal queries: "What's the balance on account 12345?", "Send a message to alice@example.com", "Get the current stock price of AAPL". One observation loop gets the job done. ReAct fails when the problem requires multiple steps, prioritization, or backtracking — which brings us to the next pattern.

Pattern 2: Planning Agents — Task Decomposition

ReAct assumes a linear sequence of thoughts and actions. But real-world problems are branching. "Migrate all my emails to a new folder and notify my team" requires: (1) list all emails matching a filter, (2) move each email, (3) post to Slack, (4) send a follow-up email. Some of these steps are independent and could run in parallel. Others depend on earlier steps.

A planning agent explicitly decomposes the goal into a task graph, tracks dependencies, and executes in the right order.

The Plan-Then-Execute Model

The architecture has two phases:

  1. Planning. The agent receives the user's goal and generates a structured plan: a list of tasks, their dependencies, and success criteria. This plan is visible to the user and can be modified before execution begins.
  2. Execution. The agent runs each task in dependency order, updating the plan with results. If a task fails, the agent can replan or escalate.

Here's a concrete example: User asks "Prepare my weekly report". The planning phase produces:

Task 1: Retrieve last week's sales data (from CRM)
  - Depends on: nothing
  - Success criteria: JSON array with at least 5 records
  
Task 2: Summarize the data into 5 key insights
  - Depends on: Task 1
  - Success criteria: 5 bullet points, each < 100 words
  
Task 3: Create a document with the summary
  - Depends on: Task 2
  - Success criteria: Document is saved and has title + summary section
  
Task 4: Email the document to manager@company.com
  - Depends on: Task 3
  - Success criteria: Email delivery confirmed

The user sees this plan before anything runs. They can delete Task 4 if they want to review first, or reorder tasks. Then execution begins.

Advantages Over Flat ReAct

The downside: planning adds latency. You're making at least two LLM calls (one to plan, one per task). But for high-stakes operations (financial transfers, report generation), the extra round-trip is worth the visibility and auditability.

Pattern 3: Tool-Augmented Agents — The Contract Approach

Even with structured tool calling, agents hallucinate. They invoke tools with the wrong parameters, call tools in the wrong order, or misinterpret tool output. This pattern enforces a contract between the agent and the tool layer: each tool declares what it requires, what it guarantees, and how it fails.

The contract is encoded in the tool schema and in how you handle tool errors.

Example: The Database Query Tool

Naive tool definition: "I have a tool called query_database(sql_string). The agent can pass any SQL." The agent will write DELETE FROM users, and you've just wiped your database.

Contract-based approach:

{
  "name": "query_database",
  "description": "Execute a read-only SQL SELECT query",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "pattern": "^SELECT\\s+.*$",
        "description": "Must start with SELECT (read-only)"
      },
      "timeout_seconds": {
        "type": "integer",
        "minimum": 1,
        "maximum": 30,
        "description": "Query timeout, max 30 seconds"
      }
    },
    "required": ["query"]
  },
  "error_codes": {
    "SYNTAX_ERROR": "The query has invalid SQL syntax",
    "TIMEOUT": "Query exceeded timeout",
    "COLUMN_NOT_FOUND": "Requested column does not exist",
    "PERMISSION_DENIED": "You don't have access to this table"
  }
}

Now when the agent tries to call this tool:

This pattern is critical for safety. By constraining what tools can do and how they fail, you prevent whole categories of bugs.

Error Recovery as a First-Class Pattern

Most agent frameworks treat tool errors as exceptions and crash or retry blindly. In production, errors are data. When a tool returns an error, the agent should reason about it:

"The query timed out. The user asked for the top 10,000 transactions. Maybe I should limit it to the top 1,000 instead and try again."

This requires wrapping tool calls in error-handling logic that passes structured error information back to the LLM's reasoning loop, not just to an exception handler.

Pattern 4: Multi-Agent Orchestration

At a certain scale of complexity, a single agent isn't enough. Consider a customer support system that needs to: (1) classify the incoming ticket, (2) fetch customer history and product info, (3) draft a response, and (4) route to a human if escalation is needed. One agent trying to do all four will be generalist and slow. Four specialized agents, each expert at their task, will be faster and more reliable.

Multi-agent orchestration splits work across specialized agents and coordinates their execution. There are three main orchestration patterns:

Pattern 4a: Supervisor Pattern

A supervisor agent receives the task and decides which worker agents to invoke and in what order. The supervisor doesn't execute work; it orchestrates.

Supervisor Responsibility Worker Responsibility
Classify incoming request Execute specialized task
Determine which workers to call Call domain-specific tools
Sequence and coordinate work Handle errors in their domain
Aggregate results for user Return structured results

Example flow: User asks "What's my balance and recent transactions?" Supervisor recognizes this needs two workers. It invokes AccountWorker (get_balance) and TransactionWorker (get_recent_transactions) in parallel, then aggregates their results.

Pattern 4b: Pipeline Pattern

Agents pass work sequentially, each transforming the input for the next agent. There's no supervisor; instead, each agent knows its successor.

Example: Email arrives. RetrievalAgent fetches customer history. ClassificationAgent analyzes the email and history to determine category. DraftAgent writes a response. ReviewAgent checks the response for tone and accuracy. The output is the final response ready to send.

Pipeline is simpler to implement (each agent has one responsibility) but less flexible than supervisor (you need to know the order in advance).

Pattern 4c: Debate Pattern

For high-stakes decisions, multiple agents propose different solutions and debate the merits. A judge agent or human picks the best.

Example: Should this transaction be flagged as fraud? ProAgent argues yes (unusual amount, new merchant). ConAgent argues no (customer is traveling, they texted about this purchase). JudgeAgent or human reviews both arguments and makes the call.

This pattern is slower (you're running multiple agents) but higher quality for decisions where error is costly.

Coordination Trade-offs

Supervisor is flexible (dynamic task selection) but adds latency (supervisor must decide before workers start). Pipeline is efficient (agents work in parallel) but rigid. Debate is most reliable but slowest. Choose based on your error tolerance and latency budget.

Orchestration Principle

The best orchestration pattern is the simplest one that meets your latency and reliability constraints. Don't add agents unless you have a specific failure mode they solve.

Pattern 5: Human-in-the-Loop — Approval Gates and Escalation

No matter how well you design your agent, it will eventually need to ask for permission. Transfer $50,000? Delete a document? Post to public social media? These are moments where the agent should pause and get human approval before proceeding.

Human-in-the-loop isn't a weakness; it's a feature that makes autonomous systems trustworthy.

Approval Gates

An approval gate is a decision point where the agent generates a proposed action and waits for human confirmation before executing it. The architecture looks like:

Agent planning: I should transfer $50,000 to account 123456.
System: PAUSE - High-value transfer detected
Human review: [sees: amount, source, destination, reason]
Human decision: Approve / Reject / Modify
System: Resume or abort

The key is that the human sees structured information, not raw LLM output. They see the exact action that will be taken, the context, and alternatives.

Escalation Paths

Not every human interaction is an approval gate. Sometimes the agent gets stuck and needs help. Escalation paths let the agent ask a human for guidance without halting execution of other tasks.

Example escalation flow:

This requires a human queue system and latency tolerance (the agent can't proceed instantly), but it's far more capable than hard-coded fallbacks.

Feedback Loops

The deepest level of human-in-the-loop is feedback: the agent produces a result, the human corrects it, and the agent learns. This isn't about pausing execution; it's about improving the agent over time.

Example: Agent drafts an email. Human sends it and later gets a reply that says "You didn't address my main concern." The human marks this as negative feedback. The agent's next draft for similar issues incorporates this lesson.

Implementing feedback requires capturing what the agent did, what the human did, and storing the pair for fine-tuning or in-context learning.

Pattern Selection Guide

You now have five patterns. When should you use each?

Pattern Best For Cost (Latency) Cost (Tokens) Risk If Deployed Alone
ReAct Single-goal queries with <5 steps Low (1-3 rounds) Low Infinite loops, hallucinated tools
Planning Multi-step tasks, high stakes Medium (plan + execute) Medium Over-planning, brittle to changes
Tool Contract Safety-critical tool calls Low Low (better validation) Misuse of unconstrained tools
Multi-Agent Complex domains, parallelizable work Medium-High (coordination overhead) High (multiple agents) Agents work at cross-purposes
Human-in-Loop High-stakes decisions, learning High (wait for human) Medium Decisions made without oversight

Recommended Combinations

You rarely use a single pattern in isolation. Here are proven combinations:

Key Takeaways

Production agentic systems don't emerge from better prompting. They emerge from deliberate architectural choices:

  1. Start with ReAct. It's the simplest pattern and works for 70% of use cases. Don't over-engineer.
  2. Enforce contracts on tools. Schema validation, error codes, and structured output eliminate silent failures.
  3. Make work visible before execution. Planning agents let humans see and modify the task graph. This is non-negotiable for high-stakes work.
  4. Specialize when complexity demands it. Multi-agent orchestration adds overhead. Use it only when single agents are too slow or unreliable.
  5. Build escalation paths. Agents will get stuck. Make it easy and fast for them to ask for help without crashing.
  6. Instrument everything. You can't improve what you can't measure. Log reasoning traces, tool calls, errors, and human decisions. Use these to debug and fine-tune.

These patterns are the content of Building Agentic AI Systems (Packt, 2026), with production code examples for each. The book goes deeper into implementation details: how to build resilient multi-agent orchestration, how to design approval workflows, and how to handle the real-world failures that textbook examples skip.

Learn More

For comprehensive coverage of these patterns with production code, read Building Agentic AI Systems (Packt Publishing, 2026). The book includes full implementations of ReAct loops, planning agents, tool contracts, multi-agent orchestration frameworks, and human-in-the-loop systems. Available now.