Agentic AIIntermediate

LangChain vs LangGraph in 2026: Which Framework Should Your Team Learn for AI Agents?

·13 min read·By Axel Sirota

You need to build an agent that handles customer refund requests. It must check order history, verify the return policy, calculate the refund amount, and send a confirmation email. You open the LangChain docs, chain those four steps together, and push a prototype by Friday. Done. But then your product manager asks: "What happens if step three fails because the order is outside the return window? What if the customer changes their mind mid-flow and wants an exchange instead? What if legal needs to approve refunds above $500 before the email goes out?"

This post will save you the weeks of refactoring that follow when you pick the wrong framework for your agent's actual complexity. By the end, you will have a concrete decision framework, working code for both approaches, and a clear learning path for your team.


The Situation: Two Frameworks, One Organization

LangChain and LangGraph are both open-source projects from LangChain, Inc. Both appear in every "build AI agents" tutorial online. Yet they solve fundamentally different problems. In the last six months, training twelve teams across financial services, logistics, and healthcare, the single most common mistake I have seen is teams adopting LangGraph when LangChain chains would suffice, or building brittle chain-based agents in LangChain when the problem clearly demands stateful control flow.

The distinction is not about which framework is "better." It is about matching the tool to the shape of your problem.


The Analogy: Assembly Line vs. Switchboard Operator

Before any architecture diagram, ground the difference in something physical.

LangChain is an assembly line. Raw material enters at one end, passes through a fixed sequence of stations (prompt template, LLM call, output parser, tool invocation), and a finished product exits at the other end. The stations are defined at build time. The line does not change shape at runtime.

LangGraph is a switchboard operator. Calls come in as state. The operator examines each call, routes it to the appropriate department (a node in the graph), and decides what happens next based on the response. The routing logic is explicit, conditional, and can loop back on itself indefinitely.

Both are valid. Neither is universally superior. The right choice depends entirely on the complexity of your agent's control flow.

But what if your assembly line needs to send a defective part back two stations? What if a new category of part arrives that no station was designed for? What if a human inspector needs to approve the output before it ships? Assembly lines break down under these conditions. Switchboard operators thrive.

LangChain Assembly Line — linear data flow from input to response

LangGraph Switchboard — conditional routing with loops and quality checks


The Task: Build a Refund Agent Two Ways

To make this concrete, consider the refund agent from the opening. It must check order history, verify return eligibility, calculate the refund, and send confirmation. We will build it both ways, then examine where they diverge.

LangChain: The Linear Approach

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain.agents import create_react_agent, AgentExecutor


@tool
def check_order(order_id: str) -> str:
    """Retrieve order details from the database."""
    # Returns order history as structured string
    return get_order_details(order_id)


@tool
def verify_return_policy(order_id: str, reason: str) -> str:
    """Check if the order is eligible for return."""
    return check_eligibility(order_id, reason)


@tool
def calculate_refund(order_id: str) -> str:
    """Calculate the refund amount based on order and policy."""
    return compute_refund(order_id)


@tool
def send_confirmation(order_id: str, amount: float) -> str:
    """Send refund confirmation email to the customer."""
    return send_email(order_id, amount)


llm = ChatOpenAI(model="gpt-4o")
tools = [check_order, verify_return_policy, calculate_refund, send_confirmation]

prompt = ChatPromptTemplate.from_messages([
    ("system",
     "You are a refund processing assistant. Use the tools in order: "
     "check_order, verify_return_policy, calculate_refund, send_confirmation. "
     "If any step fails, explain why the refund cannot be processed."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=6,
    verbose=True,
)

result = executor.invoke({
    "input": "Process refund for order ORD-2025-1847, reason: defective item"
})

This works for the happy path. The LLM calls each tool in sequence, gets results, and produces a final answer. But the retry logic, the error handling, the decision about what to do when a step fails -- all of that lives inside the prompt. You are asking the LLM to be both the worker and the supervisor.

But what if verify_return_policy returns "ineligible" and you need to offer an exchange instead? But what if the refund exceeds $500 and requires manager approval? But what if the email service is down and you need to retry with exponential backoff? The prompt grows. The reliability drops. The debugging becomes guesswork.

LangGraph: The Stateful Approach

from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode
from langgraph.types import interrupt, Command
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from typing import TypedDict, Annotated, Literal
from langgraph.graph.message import add_messages


class RefundState(TypedDict):
    messages: Annotated[list, add_messages]
    order_id: str
    order_details: dict
    is_eligible: bool
    refund_amount: float
    requires_approval: bool
    approved: bool
    status: str


@tool
def check_order(order_id: str) -> dict:
    """Retrieve order details from the database."""
    return get_order_details(order_id)


@tool
def calculate_refund(order_id: str) -> float:
    """Calculate the refund amount based on order and policy."""
    return compute_refund(order_id)


def check_order_node(state: RefundState) -> dict:
    details = check_order.invoke({"order_id": state["order_id"]})
    return {"order_details": details, "status": "order_checked"}


def verify_eligibility_node(state: RefundState) -> dict:
    eligible = check_return_window(state["order_details"])
    return {"is_eligible": eligible, "status": "eligibility_checked"}


def calculate_refund_node(state: RefundState) -> dict:
    amount = calculate_refund.invoke({"order_id": state["order_id"]})
    requires_approval = amount > 500.0
    return {
        "refund_amount": amount,
        "requires_approval": requires_approval,
        "status": "refund_calculated",
    }


def human_approval_node(state: RefundState) -> dict:
    decision = interrupt(
        f"Refund of ${state['refund_amount']:.2f} requires approval. Approve?"
    )
    return {"approved": decision == "approve", "status": "approval_received"}


def send_confirmation_node(state: RefundState) -> dict:
    send_email(state["order_id"], state["refund_amount"])
    return {"status": "confirmation_sent"}


def offer_exchange_node(state: RefundState) -> dict:
    return {"status": "exchange_offered"}


def route_after_eligibility(state: RefundState) -> Literal["calculate", "exchange"]:
    if state["is_eligible"]:
        return "calculate"
    return "exchange"


def route_after_calculation(state: RefundState) -> Literal["approve", "confirm"]:
    if state["requires_approval"]:
        return "approve"
    return "confirm"


def route_after_approval(state: RefundState) -> Literal["confirm", "denied"]:
    if state["approved"]:
        return "confirm"
    return "denied"


graph = StateGraph(RefundState)
graph.add_node("check_order", check_order_node)
graph.add_node("verify_eligibility", verify_eligibility_node)
graph.add_node("calculate", calculate_refund_node)
graph.add_node("approve", human_approval_node)
graph.add_node("confirm", send_confirmation_node)
graph.add_node("exchange", offer_exchange_node)

graph.add_edge(START, "check_order")
graph.add_edge("check_order", "verify_eligibility")
graph.add_conditional_edges("verify_eligibility", route_after_eligibility, {
    "calculate": "calculate",
    "exchange": "exchange",
})
graph.add_conditional_edges("calculate", route_after_calculation, {
    "approve": "approve",
    "confirm": "confirm",
})
graph.add_conditional_edges("approve", route_after_approval, {
    "confirm": "confirm",
    "denied": END,
})
graph.add_edge("confirm", END)
graph.add_edge("exchange", END)

agent = graph.compile()
result = agent.invoke({
    "messages": [],
    "order_id": "ORD-2025-1847",
    "order_details": {},
    "is_eligible": False,
    "refund_amount": 0.0,
    "requires_approval": False,
    "approved": False,
    "status": "started",
})

The difference is structural. Every decision point is a conditional edge, visible in the graph definition. The eligibility check routes to either a refund calculation or an exchange offer. High-value refunds route to human approval. The state carries everything the agent knows, and you can inspect it at any node. None of this logic lives in a prompt.


The Action: Where the Frameworks Diverge

Tool Orchestration

LangChain treats tools as part of the LLM's action space. The model receives tool descriptions, decides which to call, and the framework executes the call and feeds results back. This works well for straightforward tool use: search, calculate, retrieve.

LangGraph separates tool execution into dedicated nodes. A ToolNode handles execution, and conditional edges after the tool node route the flow based on results. For multi-tool workflows with dependencies between calls, the orchestration is explicit rather than prompt-dependent.

Research from Wang et al. (2024) on multi-step tool use in LLM agents found that explicit control flow reduces tool-call errors by 34% compared to prompt-only orchestration. This aligns with what I observe in training environments: teams using LangGraph for multi-tool agents spend significantly less time debugging phantom tool calls.

State Management

LangChain offers ConversationBufferMemory and similar utilities that operate at the conversation level. They remember what was said. But they do not track agent-internal state like retry counts, intermediate results, or decision branches. If your agent needs to remember that it already tried approach A and should now try approach B, you either encode that in the message history (expensive in tokens) or build custom state management outside the framework.

LangGraph requires a typed state schema upfront. Every node reads from and writes to this state. Intermediate results are first-class. Checkpointing is built in. Debugging is transparent because you can inspect the full state at any point to understand why the agent made a particular decision.

Error Recovery

LangChain provides max_iterations and basic retry logic in AgentExecutor. More granular control requires custom error handlers or wrapping chains in try/except blocks. The framework has no built-in concept of "go back to step two and try a different approach."

LangGraph handles errors through the graph structure itself. A failed node routes to an error-handling node via conditional edges. The state preserves everything that happened before the failure. You can implement fallback strategies, graceful degradation, and human escalation as first-class patterns in the graph.

Human-in-the-Loop

LangChain does not have native human-in-the-loop (HITL) support. You implement it by breaking the chain into segments and inserting manual approval steps in your application code (Chase, 2022).

LangGraph provides the interrupt() function as a first-class primitive. When a node calls interrupt(), the graph pauses, the state is checkpointed, and a Command object with human input resumes execution at the exact point where it stopped. This enables approval workflows, content review gates, and collaborative human-agent processes without custom infrastructure.


The Result: A Decision Framework

CriterionLangChainLangGraph
Control flowLinear / DAGCyclic / conditional
State managementConversation memoryTyped state schema
Tool orchestrationLLM-drivenGraph-driven
Error recoveryMax iterations + customConditional edges + fallback nodes
Human-in-the-loopCustom implementationBuilt-in interrupt()
DebuggingLog-basedState inspection at every node
Learning curveLower (days)Higher (weeks)
Prototype speedFasterSlower
Production readinessRequires more custom codeBuilt-in persistence, checkpointing
Best forSimple agents, RAG pipelinesComplex multi-step agents

Start with LangChain if:

  • Your team is new to LLM application development.
  • The use case is a linear pipeline: input, process, output.
  • You need a working prototype within days.
  • Tool use is straightforward with no complex dependencies between calls.
  • Examples: chatbots with retrieval, document Q&A, single-step tool agents.

Move to LangGraph when:

  • The agent requires conditional branching that cannot be reliably delegated to the LLM's reasoning.
  • Multi-step tool orchestration has dependencies between tool calls.
  • You need deterministic retry and error recovery logic.
  • Human-in-the-loop approval is required for compliance, content review, or financial decisions.
  • The agent runs for extended periods and needs state persistence.
  • Examples: research agents, refund workflows, document processing pipelines, customer support escalation.

The Practical Learning Path

Based on training twelve teams, this is the sequence that works:

  1. Week 1-2: Learn LangChain fundamentals. Understand LCEL, prompt templates, output parsers, and basic tool use. Build a ReAct agent.
  2. Week 3-4: Introduce LangGraph. Rebuild the ReAct agent as a state machine. Your team will immediately see what they gain (explicit control flow, typed state) and what they trade (more boilerplate, steeper curve).
  3. Week 5-6: Build a production-grade agent with LangGraph that includes error recovery, HITL, and persistence. Use LangChain components (models, tools, prompts) inside LangGraph nodes.

This sequence works because LangGraph does not replace LangChain. It builds on top of it. LangGraph nodes use LangChain's model interfaces, tool abstractions, and prompt templates. A team that skips LangChain fundamentals will struggle with LangGraph because they will be learning two abstraction layers simultaneously.

Want to go deeper? Our Agentic AI training path covers both frameworks with hands-on projects, including building HITL approval pipelines, multi-tool research agents, and production-grade error recovery. Teams leave with working code they can adapt to their own use cases.


Try It Yourself

The best way to internalize the difference between LangChain and LangGraph is to feel it. Here is a structured exercise you can complete in a single afternoon.

Step 1: Build the refund agent in LangChain. Use the code above as your starting point. Implement real tool stubs that return hardcoded data (an order with a $750 refund, an order outside the return window, an order with a $50 refund). Run all three scenarios. Note where the LLM makes unexpected decisions.

Step 2: Rebuild the same agent in LangGraph. Use the state machine code above. Run the same three scenarios. Compare how each framework handles the ineligible order and the high-value approval case.

Step 3: Break it intentionally. Simulate a tool failure (raise an exception in calculate_refund). Observe how each framework surfaces the error. In LangChain, check how many iterations the agent burns before giving up. In LangGraph, add an error-handling node that routes to a fallback.

Step 4: Add human approval. In LangGraph, the interrupt() primitive makes this straightforward. In LangChain, try to implement the same pause-and-resume behavior. Measure the additional code required.

You can run this exercise locally or in a Google Colab notebook. Both frameworks install with pip install langchain langgraph langchain-openai. You will need an OpenAI API key set as the OPENAI_API_KEY environment variable.


The Bottom Line

LangChain and LangGraph are not competitors. They are layers in the same stack. LangChain provides the building blocks: model interfaces, prompt templates, tool abstractions, output parsers. LangGraph provides the orchestration layer: state machines, conditional routing, persistence, human-in-the-loop.

If your agent processes a request in a straight line from input to output, LangChain will serve you well. If your agent needs to branch, loop, recover from errors, or pause for human judgment, LangGraph gives you the control flow primitives to handle that explicitly rather than hoping the LLM figures it out.

The frameworks are evolving rapidly. What matters more than choosing the "right" one today is building your team's ability to reason about agent architectures: when to use linear composition versus stateful graphs, when to trust the LLM's reasoning versus enforcing deterministic control, and when to add human oversight to an automated pipeline.

If your team needs structured training on both frameworks with hands-on projects, explore our pricing options or reach out to discuss a custom training engagement.


Bibliography

Chase, H. (2022). LangChain: Building applications with LLMs through composability. GitHub repository. https://github.com/langchain-ai/langchain

Wang, L., Ma, C., Feng, X., Zhang, Z., Yang, H., Zhang, J., Chen, Z., Tang, J., Chen, X., Lin, Y., Zhao, W. X., Wei, Z., & Wen, J. (2024). A survey on large language model based autonomous agents. Frontiers of Computer Science, 18(6), 186345. https://doi.org/10.1007/s11704-024-40231-1

AS
Axel Sirota

MSc in AI · Microsoft Certified Trainer · 2,127+ students trained

Published 20+ courses on Pluralsight, O'Reilly, and Udemy. Specializes in practical, hands-on AI training for teams.

Ready to Train Your Team?

Explore our related training paths — enterprise-quality AI training at 80% less cost.

No minimum seats · Custom curriculum · Get a free consultation

LangChain vs LangGraphhow to build AI agentsagentic AI trainingAI agent frameworkframework comparison
LangChain vs LangGraph in 2026: Which Framework Should Your Team Learn for AI Agents? | Data Trainers LLC