The five agentic workflow patterns
Anthropic's canonical taxonomy — prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer — and the agent shape itself. What each one is for, the cost, and the order to reach for them.
What you'll learn
- Anthropic's five workflow patterns and what each one is for
- The agent itself as the catch-all when no workflow pattern fits
- Why most production "agents" are actually workflows
- An honest heuristic for which pattern to reach for first
Before you start
Picture a team launching a customer-support bot. Day one, someone wires up an “agent” with twenty tools and a giant prompt. The traces are chaotic, the bills are scary, and every regression is a mystery. Two weeks later they rip it out and replace it with a tiny classifier that routes to one of three focused prompts. Latency drops, cost drops, quality goes up. They didn’t need an agent — they needed a workflow.
Anthropic’s Building Effective Agents gave the field a clean vocabulary for exactly this distinction: there are five workflow patterns (where the code paths are predefined) and then the agent shape itself (where the LLM dynamically directs its own process). Every modern agent framework — LangGraph, MS Agent Framework, Google ADK — maps to these. If you understand the patterns, switching frameworks is a syntax change.
The honest hierarchy: most production “AI agents” are workflows, not agents. Workflows are predictable, debuggable, and cheap. True agents are flexible but expensive and brittle. Start with a workflow shape; upgrade to an agent only when the task demands it.
Five workflow patterns plus the agent shape. Solid boxes are predetermined; dashed boxes appear only at runtime.
The five workflow patterns
1. Prompt chaining
A fixed sequence of LLM calls — each call processes the previous output. You add programmatic gates between steps to validate, branch, or stop.
Use when sub-tasks are clear and you can trade a little latency for a lot of accuracy: outline then draft then polish; extract then classify then translate.
draft = llm(f"Outline a blog post about: {topic}")
if not is_valid_outline(draft): # programmatic gate
return None
body = llm(f"Write the post using this outline:\n{draft}")
final = llm(f"Polish for tone:\n{body}")
2. Routing
Classify the input first, then dispatch to a specialized prompt or model. The classifier is its own (usually cheap) LLM call.
Use when inputs fall into distinct categories that benefit from different handling: refund queries vs. technical support, simple lookups vs. complex reasoning, FAQ-style questions vs. needs-tools questions.
category = classifier_llm(user_message) # 'refund' / 'tech' / 'sales'
return ROUTES[category](user_message) # specialized prompt per route
3. Parallelization
Run multiple LLM calls concurrently and aggregate. Two flavours:
- Sectioning — split a task into independent sub-tasks that run in parallel (one model writes the body, another generates citations).
- Voting — run the same task N times and combine (majority vote, best-of-N, ensemble). Higher confidence at proportional cost.
import asyncio
draft, citations, fact_check = await asyncio.gather(
llm_async(draft_prompt),
llm_async(citations_prompt),
llm_async(fact_check_prompt),
)
4. Orchestrator-workers
A central LLM dynamically decomposes the task into sub-tasks and delegates each to a worker LLM, then synthesizes the results. The key difference from parallelization: the sub-tasks aren’t fixed up front — the orchestrator decides them at runtime.
Use when the right decomposition can only be known after looking at the input: multi-file code edits, multi-source research, “answer this question using whichever of these 30 docs are relevant”.
5. Evaluator-optimizer
One LLM generates, another evaluates, you iterate. Stop when the evaluator approves or you hit a budget. This is what older lessons called “reflection” — Anthropic’s name for it is now standard.
Use when you have clear evaluation criteria and iteration measurably improves the output: literary translation, code review, structured extraction with validation.
draft = llm(generate_prompt)
for _ in range(max_iters):
critique = evaluator_llm(f"Critique:\n{draft}")
if critique.startswith("APPROVED"):
break
draft = llm(f"Revise using critique:\n{critique}\n\nOriginal:\n{draft}")
…and then “the agent”
When none of the above fits, you reach for the maximally flexible shape: an LLM in a loop with tools. The model picks the next action, runs it via a tool, reads the result, and decides again. No predefined path, just a loop that ends when the model says “done” or you hit a cap.
Use when the steps genuinely can’t be enumerated in advance and the model needs ground-truth feedback (tool results, test pass/fail, search hits) to plan. This is what Claude Code, Cursor’s agent mode, and SWE benchmark agents look like.
All five patterns in one playground
Read this carefully. Same loop, different shapes — the difference is where you spend your tokens and who decides what runs next.
# Anthropic's five workflow patterns plus the agent, with a mocked LLM.
# Same loop machinery, different orchestration.
def mock_llm(prompt, role="assistant"):
p = prompt.lower()
if "next action" in p: # used only by the agent loop
return "DONE: LangGraph is a state-machine library" if "tool result" in p else "CALL_TOOL search"
if "plan sub-tasks" in p:
return "research / analysis / review"
if "classify" in p:
return "refund" if "money back" in p else "tech"
if "revise" in p:
return "polished final answer"
if "critique" in p or "evaluate" in p:
return "APPROVED" if "polished" in p else "needs an example"
if "outline" in p:
return "1. intro / 2. body / 3. closing"
if "draft" in p:
return "first pass draft"
if role == "researcher":
return "found 3 sources"
return "direct answer"
# 1. PROMPT CHAINING — fixed sequence
def prompt_chaining(topic):
outline = mock_llm(f"Outline: {topic}")
body = mock_llm(f"Draft the post from these points: {outline}")
return mock_llm(f"Revise to be polished: {body}")
# 2. ROUTING — classify then dispatch
def routing(user_msg):
category = mock_llm(f"Classify: {user_msg}")
routes = {
"refund": lambda m: mock_llm(f"refund flow: {m}"),
"tech": lambda m: mock_llm(f"tech support: {m}"),
}
return routes[category](user_msg)
# 3. PARALLELIZATION — independent sub-tasks, aggregated
def parallelization(task):
# In real code: asyncio.gather(...)
return {
"draft": mock_llm(f"Draft: {task}"),
"citations": mock_llm(f"Citations for: {task}"),
"fact_check": mock_llm(f"Fact-check: {task}"),
}
# 4. ORCHESTRATOR-WORKERS — dynamic decomposition
def orchestrator_workers(task):
plan = mock_llm(f"Plan sub-tasks for: {task}") # decided at runtime
results = [mock_llm(f"Execute: {s.strip()}", role="researcher")
for s in plan.split("/")]
return f"synthesized {len(results)} worker results"
# 5. EVALUATOR-OPTIMIZER — generate, critique, revise
def evaluator_optimizer(task, max_iters=2):
draft = mock_llm(f"Draft: {task}")
for _ in range(max_iters):
critique = mock_llm(f"Evaluate this draft: {draft}")
if "APPROVED" in critique:
return draft
draft = mock_llm(f"Revise using critique '{critique}': {draft}")
return draft
# 6. THE AGENT — LLM in a loop with tools (catch-all)
def agent(task, max_steps=5):
history = task
for _ in range(max_steps):
action = mock_llm(f"Pick next action. History: {history}")
if action.startswith("CALL_TOOL"):
history += " | tool result: ok"
continue
return action # final answer
return "(hit step cap)"
task = "Explain LangGraph in 2 lines."
print("CHAIN :", prompt_chaining(task))
print("ROUTE :", routing("I want my money back"))
print("PARALLEL :", parallelization(task))
print("ORCH-WORK :", orchestrator_workers(task))
print("EVAL-OPT :", evaluator_optimizer(task))
print("AGENT :", agent(task))
CHAIN : polished final answer
ROUTE : direct answer
PARALLEL : {'draft': 'first pass draft', 'citations': 'direct answer', 'fact_check': 'direct answer'}
ORCH-WORK : synthesized 3 worker results
EVAL-OPT : polished final answer
AGENT : DONE: LangGraph is a state-machine library
Trace each one. The five workflows have predefined shapes: you know
in advance how many calls happen and in what order — CHAIN always makes
three calls, PARALLEL always three, EVAL-OPT loops a fixed number of
times. The agent has a dynamic shape: it called a tool, read the result,
and only then decided to stop — the path was discovered at runtime, not
written by you.
When to reach for which
| Pattern | Reach for it when | Relative token cost |
|---|---|---|
| Single prompt | Task is one transformation | 1x baseline |
| Prompt chaining | Sub-tasks are clear; accuracy needs focus | 2–4x |
| Routing | Inputs fall into distinct categories | ~1–2x |
| Parallelization | Sub-tasks are independent / you want voting | Nx (N branches) |
| Orchestrator-workers | Right decomposition only knowable at runtime | dynamic |
| Evaluator-optimizer | Clear criteria; iteration measurably helps | 2–Nx |
| Agent | Steps genuinely unknowable; needs tool feedback | unbounded |
Costs compound. An agent that uses prompt chaining for its tool descriptions and evaluator-optimizer for each tool result is easily 30x the tokens of a single prompt. That’s not hypothetical — it’s where most “we’ll just use agents” projects bleed budget.
How do you know it works?
Picking the right pattern is only half the job. Once your agent is running, you need to measure whether it’s actually good — and this is where most teams get surprised. A single aggregate (“success rate”) hides everything. Cost optimizations silently raise hallucination rates. Tool-call quality degrades on edge cases while headline accuracy holds steady.
The standard approach is a multi-metric scorecard: run the agent over a fixed evaluation set of representative tasks, and track every dimension you care about — task completion, token cost, tool-call validity, hallucination rate — across both versions before you ship any change.
| Metric | v1 | v2 (a “cost optimization”) |
|---|---|---|
| Task completion | 91% | 92% — basically flat |
| Token cost / task | 1.00× | 0.58× — much cheaper |
| Tool-call validity | 96% | 93% |
| Hallucination rate | 3% | 14% ⚠ nearly 5× worse |
Read the headline row and you’d ship v2 in a heartbeat — completion even
ticked up, and it’s 42% cheaper. But the cost optimization quietly drove the
hallucination rate from 3% to 14%. That is the regression a single-metric
“success rate” dashboard misses every single time — which is why the scorecard
has to be multi-metric and run on a fixed eval set before any change ships.
What you’ll see in frameworks
Each framework names the patterns differently, but they all wrap the same shapes:
- LangChain —
Runnablesequences are prompt chaining.RouterChainis routing. Parallelization isRunnableParallel. - LangGraph — every pattern becomes an explicit graph. State machines for prompt chaining and orchestrator-workers; conditional edges for routing; parallel branches for parallelization.
- MS Agent Framework (MAF) —
Workflowprimitives for chaining and routing,GroupChatfor orchestrator-workers and agent-style loops. - Google ADK —
SequentialAgentfor chaining,ParallelAgentfor sectioning/voting,LlmAgentwith tools for the open agent shape.
You won’t go wrong picking any of them. Pick the one that matches your cloud and your team’s preference for imperative vs. declarative code.
In one breath
- There are five workflow patterns (predefined code paths) plus the agent (the LLM directs its own process) — every framework maps to these.
- Prompt chaining (fixed sequence), routing (classify then dispatch), parallelization (sectioning/voting), orchestrator-workers (decompose at runtime), evaluator-optimizer (generate→critique→revise).
- The agent is the catch-all for when steps can’t be enumerated in advance and the model needs tool feedback — but most production “agents” are really workflows.
- Cost compounds (an agent layering chaining + eval-optimizer is easily 30× a single prompt), so start with the simplest shape and promote only after watching it fail.
- Once it runs, judge it on a multi-metric scorecard — a single “success rate” hides regressions like a quietly 5× higher hallucination rate.
Quick check
Quick check
Next
The next three lessons go deep on evaluator-optimizer (the generate-critique-revise pattern), tool use (the contract behind every agent), and the emerging Model Context Protocol (MCP) standard for tool integration.
Practice this in an interview
All questionsUse multiple agents when a task decomposes into distinct specialties or parallel subtasks that exceed one agent's context or reliability; avoid it when a single agent suffices, since multi-agent systems add coordination overhead, latency, cost, and error propagation. A supervisor architecture has an orchestrator routing work to specialized sub-agents, while a swarm lets peer agents hand off control to one another without a central coordinator.
An agent is an LLM placed in a loop where it reasons, chooses and calls tools or actions, observes the results, and repeats until a goal is met, rather than producing one response and stopping. The key differences are autonomy, tool use, memory and state, and multi-step control flow driven by the model's own decisions.
Tool calling extends the LLM's output space to include structured function invocations. The model emits a JSON object naming a tool and its arguments; the runtime executes the tool and feeds the result back as a new message. An agent is a loop that repeats this cycle — observe, think, act — until the task is complete or a stopping condition is met.
ReAct interleaves reasoning traces with actions step by step, deciding the next tool call based on the latest observation. Plan-and-Execute first drafts a full multi-step plan and then executes it, which is more efficient and predictable for complex tasks but less adaptive, while Reflexion adds a self-reflection step where the agent critiques past failures and retries with that feedback.