◢ Chapter 02 · Patterns

The agentic pattern library.

Eight patterns cover ~95% of real agentic systems. Almost every production agent is a composition of these. Learn them; stop reinventing. Each card has the PM questions you should answer before shipping it.

◢ The PM Lens

Every pattern below is annotated with four PM-side quadrants: When to use · PM questions to ask · Failure modes · Composability. Use these to spec a pattern, not just admire the diagram.

Pattern · 01

Prompt Chaining

Sequential workflow

Multi-stage transformation — each output feeds the next input. Outline → Draft → Polish.

Input
LLM · Step 1
gate
LLM · Step 2
LLM · Step 3
Output
When to use
  • ·Multi-stage transformation: research → draft → review
  • ·Each step needs a different specialisation or tool set
  • ·Earlier stages gate the logic of later ones
PM questions to ask
  • What exactly passes between stages — full text or a structured schema?
  • Where can the chain fail, and what is the fallback for each stage?
  • Does each agent need full history or just the prior stage's output?
Failure modes
  • ·Error amplification — a bad Stage A produces a worse Stage B
  • ·Context loss at handoffs when only partial data is passed
  • ·No recovery path if a mid-chain agent fails silently
Composability
  • ·Replace any node with an Orchestrator-Worker sub-flow
  • ·Insert Human-in-the-Loop between high-stakes stage transitions
  • ·Add Reflection to any stage's output before passing downstream
ts
async function chain(input) {
  const outline  = await llm({ prompt: outlinePrompt(input) });
  if (!isValid(outline)) return fallback();    // gate between steps
  const draft    = await llm({ prompt: draftPrompt(outline) });
  const polished = await llm({ prompt: polishPrompt(draft) });
  return polished;
}
Pattern · 02

Routing

Dispatch workflow

Classify the input first — then route to the right specialist.

Input
classify
Classifier (cheap LLM)
Specialist A
Specialist B
Specialist C
When to use
  • ·High-volume, multi-intent inputs (support, search, triage)
  • ·Different intent types need very different handling logic
  • ·Cost optimisation — cheap classifier, expensive specialists only when warranted
PM questions to ask
  • What are the routing categories — and what is the explicit fallback?
  • How confident must the classifier be before routing?
  • Who owns adding new categories as the intent space grows?
Failure modes
  • ·Misclassification sends input to the wrong specialist
  • ·Unrecognised intent falls into a poor or absent fallback handler
  • ·Category space grows stale relative to real user behaviour
Composability
  • ·Each specialist can be a Pipeline or Orchestrator pattern
  • ·Add Reflection to the classifier for confidence scoring
  • ·Route low-confidence cases directly to Human-in-the-Loop
ts
async function route(query) {
  const { kind } = await classify({ query });   // small/cheap LLM
  switch (kind) {
    case "refund":    return refundAgent(query);
    case "technical": return techAgent(query);
    case "billing":   return billingAgent(query);
    default:          return generalAgent(query);
  }
}
Pattern · 03

Parallelization / Fan-Out

Concurrent workflow

Multiple agents tackle the same task in parallel — a synthesiser merges results.

Input
fan-out
Worker
Worker
Worker
merge
Output
When to use
  • ·Research, competitive analysis, document review
  • ·Tasks that benefit from multiple independent perspectives
  • ·Speed matters and sub-tasks can run in true parallel
PM questions to ask
  • How does the synthesiser handle contradictions between agents?
  • Are agents truly independent, or sharing context that biases results?
  • What is the latency and cost implication of N parallel inference calls?
Failure modes
  • ·Conflicting outputs the synthesiser cannot reconcile meaningfully
  • ·Synthesis hallucination — inventing a consensus that wasn't there
  • ·One slow agent blocking the entire merge step
Composability
  • ·Fan-out workers can each be Single Agent + Tools internally
  • ·Wrap the synthesiser with Reflection for quality validation
  • ·Use Human-in-the-Loop at the selection step instead of auto-synthesis
ts
// Sectioning
const sections = await Promise.all(
  chapters.map((c) => llm({ prompt: writeChapter(c) }))
);
return assemble(sections);

// Voting / fan-out
const variants = await Promise.all(
  hookTypes.map((h) => llm({ prompt: generate(h, signals) }))
);
return critic.pickBest(variants);
Pattern · 04

Orchestrator–Workers

Hierarchical agent

One planner breaks the task — many specialists execute it. The shape of subtasks isn't known in advance.

Orchestrator
plans
Plan: [task1, task2, task3 ...]
Worker 1
Worker 2
Worker 3
Synthesizer → Final output
When to use
  • ·Complex tasks that can be cleanly decomposed at runtime
  • ·Sub-tasks independent enough to delegate in parallel
  • ·High-quality research, analysis, or multi-file coding projects
PM questions to ask
  • How does the orchestrator decide how to decompose the task?
  • How does it know a worker finished — and finished correctly?
  • What is the aggregation strategy (merge, rank, synthesise)?
Failure modes
  • ·Poor task decomposition causes workers to drift off-target
  • ·Workers executing without sufficient context from the original task
  • ·Orchestrator overconfident in worker outputs without validation
Composability
  • ·Workers can internally use Pipeline or Single Agent patterns
  • ·Wrap worker outputs with Reflection before the orchestrator sees them
  • ·Add Human-in-the-Loop before the orchestrator aggregates final output
ts
async function orchestrate(goal) {
  const plan = await planner({ goal });   // returns Task[]
  const results = await Promise.all(
    plan.tasks.map(t => workerAgent(t))
  );
  return synthesizer({ goal, results });
}
Pattern · 05

Evaluator–Optimizer Loop ⭐

Reflection / self-critique

Generate → critique → regenerate. Loop until quality threshold is met. The powerhouse of agentic quality.

Generator

Drafts the artifact.

v1
Evaluator

Returns structured review via tool-calling.

json
[
  { "location": "para 2",
    "comment": "Too generic",
    "severity": "high" }
]
Editor

Applies fixes, produces v2. Loop.

v2
⟲ repeat until clean or maxRounds reached
When to use
  • ·High-stakes outputs: writing, code, legal, medical, financial
  • ·Output quality is hard to specify precisely in advance
  • ·Trust-building phases where errors are expensive to correct after the fact
PM questions to ask
  • What is the quality rubric the critic evaluates against — and who wrote it?
  • How many iterations before a forced exit to prevent infinite loops?
  • Who defines 'good enough' — the agent, a threshold, or a human?
Failure modes
  • ·Infinite loops when no convergence criterion is defined
  • ·Critic missing the real problem while nitpicking surface-level issues
  • ·Over-refinement producing generic, hedged, over-cautious output
Composability
  • ·Wrap any pattern's final output step with Reflection
  • ·The Critic can be a separate, smaller specialised model
  • ·Combine with HITL: human reviews only outputs below threshold
ts
async function evaluatorOptimizer(input, maxRounds = 2) {
  let draft = await generator({ input });
  for (let i = 0; i < maxRounds; i++) {
    const review = await evaluator({ input, draft });   // returns Issue[]
    if (review.issues.length === 0) break;
    draft = await editor({ input, draft, review });
  }
  return draft;
}
Pattern · 06

ReAct (Reason + Act)

Single-agent tool loop

The agent dynamically chooses tools based on intermediate observations. Thought → Action → Observation, repeat.

Goal
Thought
Action (tool call)
Observation
loop
Final Answer
When to use
  • ·Agent must choose tools dynamically based on intermediate results
  • ·Open-ended research, debugging, or exploration tasks
  • ·Inputs vary widely enough that you can't predetermine a tool sequence
PM questions to ask
  • Which tools does the agent actually need — and nothing more?
  • What is the maxSteps budget and what happens when it's hit?
  • How does the agent know when it's done vs. when to keep going?
Failure modes
  • ·Tool hallucination (inventing results that weren't returned)
  • ·Infinite tool loops or step-budget exhaustion with no answer
  • ·Context window overflow on long-running ReAct chains
Composability
  • ·Use as a worker inside Orchestrator-Workers for research subtasks
  • ·Wrap the final answer with Reflection for quality-critical outputs
  • ·Pair with Memory-Augmented to persist observations across sessions
ts
async function react(goal, maxSteps = 8) {
  const messages = [systemPrompt, { role: "user", content: goal }];
  for (let i = 0; i < maxSteps; i++) {
    const r = await llm({ messages, tools });
    if (r.finish) return r.answer;
    const obs = await runTool(r.tool, r.args);   // ACT
    messages.push(r.assistant, { role: "tool", content: obs });
  }
}
Pattern · 07

Human-in-the-Loop

Control / governance

Agent pauses at a defined checkpoint — human decides — flow continues. The pattern that buys you trust.

Task
Agent
⏸ Human Reviewapprove / edit / reject
Agent (cont.)
Output
When to use
  • ·High-risk or irreversible decisions (publishing, spending, deleting)
  • ·Regulated domains: finance, legal, medical, compliance
  • ·Early trust-building phase before moving to full automation
PM questions to ask
  • Exactly where does the flow pause — what trigger condition?
  • What information does the human need at that moment to decide well?
  • What is the escalation path if the human is unavailable or unresponsive?
Failure modes
  • ·Checkpoint fatigue — humans rubber-stamping without reading
  • ·Poorly designed review interface — human lacks context to decide
  • ·Bottleneck breaks real-time or low-latency flow requirements
Composability
  • ·Insert between any two stages in a Pipeline
  • ·Pair with Reflection to reduce the volume reaching human review
  • ·Route low-confidence Router outputs to HITL automatically
ts
async function withApproval(stage, payload) {
  const draft = await stage(payload);
  const decision = await humanReview({
    draft,
    context: payload,
    deadline: minutes(15),
  });
  if (decision.action === "reject") return null;
  if (decision.action === "edit")   return decision.edits;
  return draft; // approved as-is
}
Pattern · 08

Memory-Augmented

Persistent state

Agent maintains context and learns across sessions. The pattern that turns one-shot tools into ongoing assistants.

Input
recall
Memory Store
context
Agent
write
Memory Store
Output
When to use
  • ·Persistent assistants with ongoing user or account relationships
  • ·Workflows where prior context is essential (projects, campaigns, accounts)
  • ·Systems designed to improve by learning from interaction history
PM questions to ask
  • What gets stored — and with what retention and deletion policy?
  • How is memory retrieved: keyword match, semantic search, recency ranking?
  • Who can inspect, correct, or permanently delete memories?
Failure modes
  • ·Memory poisoning — bad data persists and compounds over time
  • ·Irrelevant retrieval polluting the agent's context window
  • ·Privacy and data-governance risks at scale, especially across users
Composability
  • ·Add to any pattern to give it session persistence
  • ·Combine with HITL for memory write-approval in v1
  • ·Use Reflection to validate what gets stored before it enters memory
ts
async function withMemory(userId, input) {
  const memories = await memory.search({
    userId, query: input, k: 5,
  });
  const result = await agent({
    input,
    context: memories,
  });
  await memory.write({
    userId, content: extractFacts(result),
  });
  return result;
}
◢ Composition

Real systems mix patterns.

◢ The big insight
The LinkedIn Writer in Chapter 5A is an orchestrator at the top, with a ReAct research subagent, a chain for guideline generation, and an evaluator-optimizer loop for the writer. The AI PM Briefing in Chapter 5B stacks Single Agent → Memory → Fan-Out + Reflection → HITL → Tool. Patterns are LEGO bricks, not religions.