What Is Prompt Chaining?

A prompt chain is a sequence of LLM calls where each call's output becomes (part of) the next call's input. Unlike an agent loop, the structure is fixed at design time — no autonomous tool selection, no dynamic loops.

Use a chain when you know the steps needed in advance. Use an agent when the steps depend on what the LLM discovers during execution.

When to Chain vs Single Prompt

Prefer chaining when...Prefer single prompt when...
Steps are distinct (research → summarise → format)The task fits in one context window
Each step benefits from full focus on one sub-taskOverhead of multiple calls is not worth it
You want to use different models per stepOutput quality is already good in one call
Quality doesn't meet requirements in one shotLatency is critical

A Simple 3-Step Chain

from openclaw import Chain, Step

chain = Chain(
    steps=[
        Step(name="research",
             prompt="Research the following topic and provide key facts: {topic}",
             model="gpt-4o"),
        Step(name="summarise",
             prompt="Summarise this research in 3 bullet points:\n{research}",
             model="gpt-4o-mini"),
        Step(name="format",
             prompt="Format these bullet points as a professional email body:\n{summarise}",
             model="gpt-4o-mini"),
    ]
)

result = chain.run(topic="quantum computing breakthroughs in 2025")
print(result["format"])  # Final formatted output

Variable Passing Between Steps

Each step receives the outputs of all previous steps as template variables using {step_name} syntax. You can also inject external variables at run time:

result = chain.run(
    topic="quantum computing",
    audience="non-technical executives",  # Extra variable injected at any step
)

Conditional Branching

Use a ConditionalStep to route to different sub-chains based on intermediate output:

from openclaw import ConditionalStep

chain = Chain(steps=[
    Step(name="classify",
         prompt="Classify this support ticket as 'billing', 'technical', or 'general': {ticket}",
         model="gpt-4o-mini"),
    ConditionalStep(
        condition_key="classify",
        branches={
            "billing": billing_chain,
            "technical": technical_chain,
            "general": general_chain,
        },
        default=general_chain,
    ),
])

Async Chains for Parallel Steps

Independent steps can run in parallel using an async chain:

from openclaw import AsyncChain, ParallelStep

chain = AsyncChain(steps=[
    ParallelStep(name="gather", parallel=[
        Step(name="competitors", prompt="List the top 5 competitors of {company}"),
        Step(name="financials", prompt="Summarise recent financial news for {company}"),
        Step(name="sentiment", prompt="Analyse social media sentiment for {company}"),
    ]),
    Step(name="report",
         prompt="Write an executive summary using:\n{competitors}\n{financials}\n{sentiment}"),
])
import asyncio
result = asyncio.run(chain.run(company="OpenAI"))

Error Handling and Retry

chain = Chain(
    steps=[...],
    retry=2,           # Retry failed steps up to 2 times
    on_error="skip",   # skip | raise | substitute
    substitute="N/A",  # Value to use if skipped
)
Key takeaways:
  • Chains are deterministic and predictable — prefer them when you know the steps in advance.
  • Use agents for open-ended tasks; use chains for structured pipelines.
  • Outputs flow between steps as named template variables {step_name}.
  • Use ConditionalStep for branching logic without building a full agent.
  • Parallel steps reduce chain latency when steps are independent.

Error Handling in Chains

A prompt chain is only as reliable as its weakest step. Handle failures gracefully with per-step retry and fallback logic:

from openclaw import Chain, Step

chain = Chain([
    Step("extract",  "Extract the key facts from: {input}",
         retry=3, fallback_output="No facts extracted."),
    Step("verify",   "Verify these facts are correct: {extract}",
         timeout_seconds=30),
    Step("format",   "Format as bullet points: {verify}"),
])

# Access individual step outcomes
result = chain.run(input=document)
for step_name, step_result in result.steps.items():
    if step_result.error:
        print(f"{step_name} failed: {step_result.error}")

Chain Observability and Debugging

Prompt chains produce multi-step traces that help you diagnose quality issues in specific steps without re-running the full pipeline:

  • Use chain.run(return_trace=True) to capture all intermediate outputs for debugging
  • Each step’s input, output, token count, and latency are available in result.trace
  • Export traces to OpenTelemetry for visualisation in Jaeger or Datadog
  • Log step-level quality scores using a lightweight LLM-as-judge check on each step output