beginnerarchitecture-patternsworkflowpatternsprompt-chainingrouting

Chapter 3 of 5

Workflow Patterns: Chaining, Routing, Parallelization

The three workflow patterns that cover most real tasks — prompt chaining, routing, and parallelization (sectioning and voting).

Workflow Patterns: Chaining, Routing, Parallelization

These three patterns, from Anthropic's Building Effective Agents, cover the majority of real tasks. Each trades a little latency for a lot of reliability.

1. Prompt chaining

Decompose a task into a sequence of steps, where each LLM call processes the output of the previous one. Add programmatic checks ("gates") on intermediate steps to catch problems early.

[LLM 1] → gate → [LLM 2] → gate → [LLM 3] → output

When to use it: the task decomposes cleanly into fixed subtasks. You're trading latency for accuracy — each call becomes easier.

Examples:

  • Generate marketing copy, then translate it.
  • Write a document outline, check it meets criteria, then write the document from the outline.
outline = llm("Write an outline for: " + task)
if not meets_criteria(outline):
    return "Outline rejected at gate"
document = llm("Write the document from this outline: " + outline)

2. Routing

Classify an input and direct it to a specialized follow-up. This separates concerns and lets you build more specialized prompts.

            ┌→ [specialist A]
[input] → [classifier] ┼→ [specialist B]
            └→ [specialist C]

When to use it: there are distinct categories that are better handled separately, and classification can be done accurately.

Examples:

  • Route customer-service queries (refunds, tech support, general) into different prompts and tools.
  • Route easy questions to a cheaper model (Haiku) and hard ones to a stronger model (Sonnet) — optimizing cost per query.

Routing is the cheapest cost optimization

Before adding any other complexity, routing lets you send 80% of traffic to a cheap, fast model and reserve the expensive one for the 20% that needs it. It's a workflow that pays for itself.

3. Parallelization

Run LLM calls simultaneously and aggregate their outputs programmatically. Two variations:

  • Sectioning — break a task into independent subtasks run in parallel.
  • Voting — run the same task multiple times to get diverse outputs.
Sectioning:               Voting:
   ┌→ [LLM A] ─┐            ┌→ [LLM 1] ─┐
[input] ┼→ [LLM B] ─┼→ aggregate  [input] ┼→ [LLM 2] ─┼→ vote
   └→ [LLM C] ─┘            └→ [LLM 3] ─┘

When to use it: when subtasks can run in parallel for speed, or when multiple perspectives raise confidence.

Examples:

  • Sectioning: one model instance processes a user query while another screens it for policy violations — performs better than one model doing both.
  • Voting: review code for vulnerabilities with several different prompts; flag if any find a problem.
import concurrent.futures

# Sectioning: review different aspects in parallel
with concurrent.futures.ThreadPoolExecutor() as ex:
    security = ex.submit(llm, "Review for security issues: " + code)
    style = ex.submit(llm, "Review for style: " + code)
    correctness = ex.submit(llm, "Review for correctness: " + code)

review = aggregate(security.result(), style.result(), correctness.result())

Parallelization multiplies token cost

Sectioning with three calls costs roughly 3× the tokens of one call. Voting with five identical calls costs 5×. Parallelization buys speed or confidence — never use it "just because"; use it when the added cost buys something you can measure.

The meta-pattern

Notice what these three share: the path is written down. Chaining is a fixed sequence. Routing is a classifier plus branches. Parallelization is a fan-out plus aggregation. None of them asks the model to decide what to do next — that decision lives in your code.

That's what makes them workflows, not agents. The next chapter covers the one workflow that starts to blur the line — orchestrator-workers — where the model does decide, but within bounds you control.


Next: Orchestrator-Workers — dynamic decomposition, the bridge between fixed workflows and full agents.