LangChain vs. LangGraph: When to Use Each

By Carlos Montiel | Enterprise AI Specialist
Leer en español →
Published: 2026-07-28 | By: Carlos Montiel | Reading time: ~4 minutes

They aren't competitors, they're different layers of the same ecosystem. The right question isn't which one is better but what kind of flow control your problem needs.

The structural difference

LCEL models flows as a directed acyclic graph (DAG): each step runs once, in an order determined by the pipe composition. It's the right abstraction when the flow is fundamentally linear or parallel: retrieve, format, generate. LangGraph models flows as a state machine with `StateGraph`: nodes can run in any order determined dynamically, including cycles — going back to a previous node — and conditional branching based on accumulated state, not just the output of the immediately preceding step.

This difference isn't cosmetic. An agent that, after reading a tool's result, decides it needs to call the model again with more context, or repeat a search with a reformulated query, requires a cycle. Pure LCEL doesn't express cycles natively; LangGraph does.

When LCEL is enough

If your flow can be drawn as a straight line or a fan of parallel steps that converge exactly once, LCEL is the right tool and the simplest to maintain:

from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser classify = ( ChatPromptTemplate.from_template("Classify the ticket: {ticket}\nCategories: technical, billing, general") | ChatOpenAI(model="gpt-4o-mini", temperature=0) | StrOutputParser() )

Typical cases: classification, summarization, entity extraction, a simple single-pass RAG. Adding LangGraph here is complexity with no benefit: more boilerplate code for a flow that never needed mutable state or cycles.

When you need LangGraph

The clearest signal is the presence of at least one of these conditions: the flow needs to remember state between steps that isn't simply "the previous output" (for example, a retry counter, an accumulated list of tools used); the flow may need to repeat a step (a ReAct agent that calls tools until the query is satisfied); or the flow requires pausing for human intervention before continuing.

from langgraph.graph import StateGraph, END, START from typing import TypedDict, Annotated import operator class AgentState(TypedDict): messages: Annotated[list, operator.add] attempts: int def call_model(state: AgentState): response = llm.invoke(state["messages"]) return {"messages": [response], "attempts": state["attempts"] + 1} def should_continue(state: AgentState): if state["attempts"] >= 3: return END return "tools" if needs_tool(state) else END graph = StateGraph(AgentState) graph.add_node("model", call_model) graph.add_node("tools", run_tools) graph.add_edge(START, "model") graph.add_conditional_edges("model", should_continue, {"tools": "tools", END: END}) graph.add_edge("tools", "model") app = graph.compile()

The `model -> tools -> model` cycle is exactly what LCEL can't express natively without manual recursion outside the framework.

The real relationship between the two

LangGraph doesn't replace LCEL: it uses it as a building block. Every node in a `StateGraph` can be, and in practice almost always is, a full LCEL chain. It's common to have a node that internally is `prompt | llm | parser`. LangGraph provides the high-level flow control (when to run what, how many times, with what state); LCEL provides efficient composition within each step.

The cost of complexity

LangGraph introduces concepts LCEL doesn't have: an explicit state schema definition (`TypedDict` or `Pydantic`), checkpointers for persistence, and a directed-graph mental model with conditional edges. For a team just starting with LLMs, this complexity jump needs to be justified by a real requirement for cycles, cross-session persistent state, or human intervention. Starting every new project directly with LangGraph "just in case" adds development friction with no benefit if the flow ends up being linear.

A practical decision rule

In our projects we apply a simple rule: if you can draw the flow on a whiteboard with no arrows going backward, use LCEL. The moment you draw an arrow going back to a previous node — or need the system to "remember" something more complex than the immediately preceding message — migrate that specific flow to LangGraph, while the rest of the system stays on LCEL.

Carlos Montiel
Enterprise AI Solutions Architect
Specialist in LLMs, Agents, and Orchestration
guatemalia.com/en/#contact · info@guatemalia.com

Need to implement AI at your company?

Carlos Montiel is an enterprise AI solutions architect. He implements LLMs, Agents, RAG, and orchestrators for companies across Guatemala and Latin America. Reach out for a consultation.

Contact Carlos Montiel

info@guatemalia.com