2026-07-078 min readRishi Choudhary

Agentic Architecture Patterns: When to Use Multi-Step Agents, Tool Chains, and Orchestration Layers

Share

Most AI in production is not an agent, and many systems that are agents shouldn't be. We tried three different architectures before finding the one that survived real conversations, and the deciding factor turned out to be debuggability, not capability.

This post is a deep dive from our WhatsApp hotel booking case study.

Most AI in Production Is Not an Agent

And many systems that are agents shouldn't be.

The distinction is simple. If you can draw the complete execution flow before writing code, you have a chain. Document Q&A, summarization, classification: fixed sequences where the model does useful work at each step but the sequence itself is predetermined. If the next step depends on what the user just said or what a tool returned, you have an agent.

Most teams jump to agents because they sound more capable. In practice, every pattern is a tradeoff between control and flexibility. Chains give you maximum control with minimum flexibility. Agents give you flexibility at the cost of control. The production question is always: how much flexibility does this feature actually need?

The real question is where you want intelligence to live: in the model, the structure, or the system around it. "Agent or chain" is downstream of that. The decision shapes everything: cost, debuggability, reliability, and how badly things break when the model does something unexpected.


Pattern 1: Single Agent With Tools

One LLM with a defined set of tools, deciding when to invoke each. This works for a surprising range of problems: support bots, product discovery, document Q&A. The model sees the user's message, picks a tool, processes the result, responds.

The key design decision is tool granularity. Fewer tools with broader scope means the model picks the right one more often. More narrow tools give you finer control but forces the model to discriminate between similar options, which it will sometimes get wrong.

We started here with our agentic commerce platform. One model, tools scoped to each state. It handled single-turn queries well. By turn 6 or 7, the model started over-calling tools: a guest saying "sounds good, let's book" triggered another availability check instead of proceeding to confirmation. It oscillated between tool calls and freeform answers with no consistency. It forgot which property the guest had picked.

The breaking point is when the model has to infer state instead of read it. You'll see it as repeated questions, inconsistent recommendations, or the agent "forgetting" what the user confirmed five turns ago. At that point you need explicit state, not a longer context window.

Cost note: every turn reprocesses the full conversation history. Long conversations burn tokens on context the model has already seen. A 15-turn booking conversation with 8,000-token system prompt costs significantly more on turn 15 than turn 3, even when the model isn't doing anything new.


Pattern 2: State Machine Agent

This is where most production-grade agent systems end up. Not because it's elegant. It's the only pattern that balances flexibility with control under real traffic. An explicit state machine constrains what the model can do at each step. The AI still decides things (classification, ranking, generating copy), but the graph controls which transitions are possible and which tools are available.

We built 8 states in LangGraph. Three illustrate the principle:

Inbox ran a fast classifier (intent, language, existing booking reference). A single cheap call, under 200 tokens output. It decided where to route, nothing more.

CollectStayConstraints extracted dates, guests, budget, amenities into typed fields on a state object. Not free-text summaries the next node would re-parse. Structured fields. Once a date was confirmed, it lived as check_in: date, not as a sentence. This was the single most important design decision: structured fields are authoritative, the message list is context.

SearchInventory built a PMS query entirely from those typed fields. No LLM involvement in query construction. Deterministic mapping from {destination, dates, occupancy, budget_max} to API call. This eliminated the "fuzzy search when we needed exact filters" problem entirely.

The model never had to decide whether to call check_availability or create_booking. The graph already knew, based on the current state. That constraint is the point. The moment we moved from "the model remembers everything" to "the system knows exactly where it is," failures dropped dramatically.

When it breaks: when the state machine itself becomes the bottleneck. Too many states, too many conditional edges, transitions that feel like reimplementing business logic in graph config. If your graph has 20+ states and you're spending more time on transition logic than on what the model does at each state, you've over-indexed on control.

Cost note: scoped prompts per state. The classification node uses a cheap fast model, the ranking node uses a capable expensive one. You pay for reasoning only where reasoning matters.

If you're evaluating LangGraph specifically, the framework tradeoffs matter before you commit: LangChain and LangGraph in Production. The full 8-state walkthrough is in the WhatsApp case study.


Pattern 3: Orchestrated Multi-Agent

Multiple specialized agents, each with its own prompt, tools, and potentially its own model, coordinated by an orchestrator.

This is often an overcorrection. Teams hit prompt bloat in a single agent and jump to multiple agents, trading one problem for three: coordination, latency, and observability. A shared state store means tight coupling between agents. Message passing means guests repeat information. And when the final output is wrong, you need to figure out which agent caused it and what the orchestrator's handoff looked like.

We considered this for the booking system: separate agents for booking, post-booking, and concierge. The state machine handled it better because the phases were sequential, not parallel. The conversation naturally flowed from one phase to the next, and the state machine expressed that progression without coordination overhead.

Multi-agent earns its complexity in two situations: when agents genuinely operate in parallel, or when different phases need fundamentally different model capabilities that can't share a prompt. If neither applies, a state machine is almost always simpler and more reliable.

When it breaks: when coordination costs exceed the complexity the separation was supposed to manage. If your orchestrator is more complex than any individual agent, you've moved the problem rather than solved it.

Cost note: context duplication across agents, plus the orchestrator adds an inference call per turn just to decide routing.

Cost scales very differently across these patterns. Chains scale linearly. Single agents scale with conversation length. Multi-agent systems scale with both length and agent count. State machines let you bound cost by scoping where reasoning actually happens.


The Anti-Pattern: Everything Inside n8n

Before any of the above, we tried building the entire booking agent as an n8n workflow. The latency and retry cascade that caused is covered in the case study. Speed was the lesser problem. Debuggability was the real one.

Each node consumed the previous node's text output. Minor misclassifications early on snowballed. Debugging meant tracing through 20+ nodes with no compact view of what went wrong. We spent more time debugging the workflow than improving the product. That's when we knew the architecture was wrong. Workflow engines are for deterministic orchestration, not probabilistic reasoning. n8n is excellent. For the right job.


Pattern 4: Workflow + AI Hybrid

After the rebuild, we settled on a clean division. LangGraph owns conversation state and decisions. n8n owns side-effects.

Concrete example: on a booking.confirmed event from LangGraph, n8n fetches the booking payload, blocks PMS inventory (idempotent via booking_intent_ref), sends WhatsApp confirmations to guest and owner, posts to the ops channel. Retry logic and idempotency around PMS timeouts are easier in a workflow than inside the agent. Non-AI engineers change notification templates without touching LangGraph.

The general principle: the agent emits domain events (booking.confirmed, payment.failed, escalation.requested). The workflow engine subscribes and handles downstream effects. New integrations are new subscribers, not agent changes. The agent can be tested with a mocked event bus. Workflows can be tested with synthetic events. They ship on different release cadences.

Cost note: side-effects are deterministic and free of inference cost. Every external call you move from the agent to a workflow is a call the model doesn't need to reason about.

The full set of workflow examples (payment recovery, human escalation, SLA tracking) is in the WhatsApp case study.


Anti-Patterns

Unlimited tool access. In our booking system, giving the agent modification tools during the search phase led to it occasionally trying to modify a booking that didn't exist yet. Fix: state-based tool eligibility. If a tool isn't in the current state's allowed set, the model can't call it.

"Let the AI figure it out." No state machine, no defined transitions, no guardrails. Works with curated demo inputs. Under real traffic with diverse, ambiguous, multilingual input, the model will call tools in sequences you never imagined. Guardrails read like constraints on capability. In production they're what makes capability reliable.

n8n-as-agent. Covered above. Workflow engines for orchestration, not reasoning. The visual canvas makes it look easy. The debugging, latency, and hallucination costs are not.


Choosing Your Pattern

Start with a chain. If the steps are known and the sequence is fixed, don't introduce agent complexity. Most features in production are chains.

Move to a single agent when the next step genuinely depends on user input and conversations are short. Move to a state machine when conversations are long, phases are distinct, and you need to control which tools are available when. Consider multi-agent only when phases need fundamentally different model capabilities or genuinely run in parallel. Always separate side-effects into workflows.

The mistake most teams make is optimizing for capability before control. Production systems need the opposite. If your system only works when the model behaves perfectly, it's not production-ready. The model is the least stable part of your stack. Build around that fact.

For the production checklist we use before any AI deployment: AI Demo to Production: What Changes.

Share

Content on this page may not be reproduced, distributed, or republished without prior written permission. Sharing links is encouraged. See our Terms of Use for details.