AI Agents LangGraph

Prompt Chaining

Intermediate

Prompt Chaining

This post covers Prompt Chaining in LangGraph , showing how multiple prompts can work together in sequential workflows and multi-step reasoning pipelines. We explore planner–executor patterns, summarization, refinement, and reflection chains, along with state passing between prompts, error handling strategies, common chaining mistakes, and best practices for building reliable AI workflows.

What Is Prompt Chaining?

Prompt Chaining is the technique of connecting multiple prompts in a sequence, where the output of one prompt becomes the input (or part of the input) for the next prompt. Instead of solving a complex task in a single large prompt, you break it down into smaller, focused steps, making the system more reliable, interpretable, and maintainable. Prompt chaining is one of the foundational patterns in building advanced LLM applications and agents.
Sequential Prompt Pipelines
The simplest form of prompt chaining,  a linear sequence of prompts.
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# Step 1: Generate ideas
idea_prompt = ChatPromptTemplate.from_template(
    "Generate 5 creative ideas about: {topic}"
)

# Step 2: Evaluate & choose best
evaluator_prompt = ChatPromptTemplate.from_template(
    "Evaluate these ideas and pick the best one:\n{ideas}\n\nReturn only the best idea."
)

# Chain them
chain = idea_prompt | llm | StrOutputParser() | evaluator_prompt | llm | StrOutputParser()

result = chain.invoke({"topic": "AI agents in 2026"})

Multi-Step Reasoning Chains

Breaking down complex reasoning into explicit steps.
reasoning_chain = ChatPromptTemplate.from_messages([
    ("system", "You are an expert problem solver. Think step by step."),
    ("human", """Solve this problem using the following steps:
1. Understand the problem
2. Break it down
3. Solve each part
4. Combine the solution

Problem: {problem}""")
])

final_chain = reasoning_chain | llm | StrOutputParser()

Planner → Executor Chains

A very powerful and common pattern in LangGraph.
planner_prompt = ChatPromptTemplate.from_template(
    "Create a detailed step-by-step plan to solve: {task}"
)

executor_prompt = ChatPromptTemplate.from_template(
    """Follow this plan and execute it:

Plan:
{plan}

Now execute the plan and give the final result."""
)

# In LangGraph, this is usually implemented as separate nodes
def planner_node(state):
    plan = llm.invoke(planner_prompt.format(task=state["messages"][-1].content))
    return {"messages": [AIMessage(content=plan.content)], "plan": plan.content}

def executor_node(state):
    result = llm.invoke(executor_prompt.format(plan=state["plan"]))
    return {"messages": [AIMessage(content=result.content)]}

Summarization Chains

summarization_chain = ChatPromptTemplate.from_template(
    "Summarize the following text concisely:\n\n{text}"
) | llm | StrOutputParser()

refinement_chain = ChatPromptTemplate.from_template(
    "Improve this summary. Make it more clear and concise:\n\n{summary}"
) | llm | StrOutputParser()

# Full chain
full_chain = summarization_chain | refinement_chain

Refinement Chains

Iteratively improving an output.
def refinement_chain(state):
    current = state["messages"][-1].content
    
    refinement_prompt = ChatPromptTemplate.from_template(
        "Improve the following answer. Make it more accurate, clear, and professional:\n\n{answer}"
    )
    
    improved = llm.invoke(refinement_prompt.format(answer=current))
    return {"messages": [AIMessage(content=improved.content)]}
Often used in loops (Reflection Pattern).

Reflection Chains

One of the most powerful chaining patterns.
reflection_prompt = ChatPromptTemplate.from_template(
    """Review your previous answer and identify weaknesses.
    
    Original Answer: {answer}
    
    Provide constructive criticism and suggest improvements."""
)

final_prompt = ChatPromptTemplate.from_template(
    """Based on the reflection, provide an improved final answer:
    
    Reflection: {reflection}
    Original: {original}
    
    Final Answer:"""
)

# In LangGraph this becomes a cycle
def reflect_node(state):
    reflection = llm.invoke(reflection_prompt.format(answer=state["messages"][-1].content))
    return {"messages": [AIMessage(content=reflection.content)]}

Prompt Chaining in LangGraph

In LangGraph, prompt chaining is usually implemented using multiple nodes instead of a single long chain.
from langgraph.graph import StateGraph, START, END

class AgentState(MessagesState):
    plan: str | None = None
    draft: str | None = None

graph = StateGraph(AgentState)

graph.add_node("planner", planner_node)
graph.add_node("drafter", drafter_node)
graph.add_node("critic", critic_node)
graph.add_node("refiner", refiner_node)

graph.add_edge(START, "planner")
graph.add_edge("planner", "drafter")
graph.add_edge("drafter", "critic")
graph.add_conditional_edges("critic", should_refine)
graph.add_edge("refiner", "critic")  # loop
graph.add_edge("critic", END)

State Passing Between Prompts

Using state to pass data between chained prompts:
def planner_node(state):
    plan = llm.invoke(planner_prompt.format(task=state["messages"][-1].content))
    return {"plan": plan.content, "messages": [AIMessage(content=plan.content)]}

def executor_node(state):
    result = llm.invoke(executor_prompt.format(plan=state["plan"]))
    return {"messages": [AIMessage(content=result.content)]}

Error Handling in Chains

def safe_chain_node(state):
    try:
        result = llm.invoke(prompt.format(**state))
        return {"messages": [AIMessage(content=result.content)]}
    except Exception as e:
        return {
            "messages": [AIMessage(content=f"Error occurred: {str(e)}")],
            "error": str(e)
        }

Common Chaining Mistakes

  • Making chains too long (loses coherence)
  • Not passing necessary context between steps
  • Overly complex single prompts instead of chaining
  • Poor error handling
  • No validation between steps
  • Ignoring token limits across the chain


Best Practices for Prompt Chaining

  1. Keep each prompt focused on a single responsibility
  2. Use clear state fields to pass data between steps
  3. Add validation/reflection steps for critical chains
  4. Keep total token usage in check
  5. Make chains observable (use streaming + logging)
  6. Test each step independently
  7. Prefer nodes over long LCEL chains in complex workflows
Golden Rule:
If a prompt is doing more than one clear task, split it into a chain.

AI agent LangChain LangGraph Python

← All training