Chapter 7 – Prompt Chaining

Decomposing Tasks into Sequential Steps

Prompt chaining is the simplest and most predictable of the workflow patterns. It decomposes a task into a fixed sequence of LLM calls, where each call processes the output of the previous one. Unlike planning (Chapter 5), where the LLM decides the steps, prompt chaining uses a developer-defined pipeline.

The Pattern

  ┌────────┐    ┌────────┐    Gate    ┌────────┐    ┌────────┐
  │ Step 1 │───►│ Step 2 │───►(check)─►│ Step 3 │───►│ Step 4 │
  │ (LLM)  │    │ (LLM)  │     │      │ (LLM)  │    │ (LLM)  │
  └────────┘    └────────┘     │      └────────┘    └────────┘
                               │
                          ┌────▼────┐
                          │  Fail   │
                          │ (abort  │
                          │  or fix)│
                          └─────────┘

The key insight: each step is a simpler task than the whole, and simpler tasks yield higher-quality LLM outputs. You trade latency (multiple sequential calls) for accuracy (each call is easier to get right).

Basic Prompt Chaining

# See code/prompt_chaining.py for the full implementation

def generate_article(llm, topic):
    """Generate an article through a chain of prompts."""
    
    # Step 1: Research and outline
    outline = llm.generate(
        f"Create a detailed outline for an article about: {topic}\n"
        f"Include 4-6 main sections with key points for each."
    )
    
    # Step 2: Gate - validate the outline
    validation = llm.generate(
        f"Review this outline for an article about '{topic}':\n{outline}\n\n"
        f"Is it comprehensive, well-structured, and logically ordered? "
        f"Answer YES or NO with a brief explanation."
    )
    
    if "NO" in validation.upper():
        # Refine the outline
        outline = llm.generate(
            f"Improve this outline based on the feedback:\n"
            f"Outline: {outline}\nFeedback: {validation}"
        )
    
    # Step 3: Write the article
    article = llm.generate(
        f"Write a complete article following this outline:\n{outline}\n"
        f"Write in a clear, engaging style."
    )
    
    # Step 4: Edit and polish
    final = llm.generate(
        f"Edit this article for clarity, grammar, and flow:\n{article}\n"
        f"Fix any issues and return the polished version."
    )
    
    return final

Gates: Quality Checkpoints

A distinguishing feature of prompt chaining is the use of gates — programmatic or LLM-based checks between steps that verify the intermediate output before proceeding:

# See code/prompt_chaining.py for the full implementation

def gate_check(llm, output, criteria):
    """Verify that output meets specified criteria."""
    result = llm.generate(
        f"Evaluate the following output against these criteria:\n"
        f"Criteria: {criteria}\n"
        f"Output: {output}\n\n"
        f"Does the output meet all criteria? "
        f"Respond with PASS or FAIL and explain."
    )
    return "PASS" in result.upper(), result

Gates can also be programmatic — checking for specific patterns, length constraints, or format requirements without involving the LLM:

def programmatic_gate(output, min_length=100, required_sections=None):
    """Non-LLM gate check."""
    if len(output) < min_length:
        return False, f"Output too short: {len(output)} < {min_length}"
    
    if required_sections:
        for section in required_sections:
            if section.lower() not in output.lower():
                return False, f"Missing required section: {section}"
    
    return True, "All checks passed"

Common Prompt Chaining Patterns

Generate → Translate

english_copy = llm.generate(f"Write marketing copy for: {product}")
french_copy = llm.generate(f"Translate to French:\n{english_copy}")

Extract → Transform → Load

data = llm.generate(f"Extract key data points from:\n{document}")
structured = llm.generate(f"Convert to JSON format:\n{data}")
summary = llm.generate(f"Summarize the key findings:\n{structured}")

Outline → Validate → Write → Edit

outline = llm.generate(f"Create an outline for: {topic}")
validated = llm.generate(f"Check this outline for completeness:\n{outline}")
draft = llm.generate(f"Write based on this outline:\n{validated}")
final = llm.generate(f"Edit for quality:\n{draft}")

Analyze → Recommend → Format

analysis = llm.generate(f"Analyze this data:\n{data}")
recommendations = llm.generate(f"Based on this analysis, recommend actions:\n{analysis}")
report = llm.generate(f"Format as a professional report:\n{recommendations}")

When to Use Prompt Chaining

Prompt chaining is ideal when:

When to Avoid

Prompt Chaining vs. Other Patterns

Aspect Prompt Chaining Planning Agent Loop
Steps defined by Developer LLM LLM
Predictability High Medium Low
Flexibility Low High High
Complexity Low Medium High
Best for Known workflows Unknown workflows Open-ended tasks

Practical Tips

  1. Keep chains short — 3–5 steps is usually optimal; longer chains accumulate errors
  2. Add gates at critical points — Don’t just chain blindly; verify intermediate outputs
  3. Pass only what’s needed — Each step should receive only the context it needs, not everything that came before
  4. Consider parallel branches — If steps are independent, run them in parallel (see Chapter 9)
  5. Make steps composable — Design each step so it can be tested and used independently

Navigation: