LangChain and LangGraph come from the same team at LangChain Inc. They share an ecosystem, they share documentation pages, and they share a fanbase that's perpetually confused about which one to use. Fair enough. The naming doesn't help.
Here's the short version: LangChain is for building sequential pipelines. LangGraph is for building stateful, cyclical agent workflows. If your thing goes A then B then C and you're done, LangChain. If your thing goes A then B then maybe back to A then C then possibly D depending on what B found, LangGraph.
Now the long version.
## What LangChain Actually Is
LangChain started as a framework for chaining LLM calls with tools, memory, and retrieval. You build a sequence of steps: take user input, maybe retrieve some documents, feed them to a model, parse the output, maybe call a tool, format the response. It's a pipeline.
The core abstraction is the chain. Input goes in one end, gets transformed through a series of steps, output comes out the other end. LCEL (LangChain Expression Language) lets you pipe these together with the `|` operator, which feels clean until your workflow needs to loop.
```python
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
chain = (
ChatPromptTemplate.from_template("Summarize this: {text}")
| ChatOpenAI(model="gpt-4o")
| StrOutputParser()
)
result = chain.invoke({"text": "some long document..."})
```
That's LangChain at its best. Clean, readable, does exactly what you'd expect. For RAG pipelines, document processing, prompt chaining, classification workflows. Anything where the flow is linear or tree-shaped (branching but not looping), LangChain handles it well.
## What LangGraph Actually Is
LangGraph models your workflow as a state machine. Nodes are functions. Edges are transitions. The state is a typed object that gets passed between nodes and modified along the way. Crucially, edges can point backwards. Your graph can loop.
```python
from langgraph.graph import StateGraph, END
from typing import TypedDict
class AgentState(TypedDict):
messages: list
next_action: str
graph = StateGraph(AgentState)
graph.add_node("reason", reasoning_node)
graph.add_node("act", action_node)
graph.add_node("observe", observation_node)
graph.add_edge("reason", "act")
graph.add_edge("act", "observe")
graph.add_conditional_edges("observe", should_continue, {
"continue": "reason",
"done": END
})
```
The [broader framework comparison across CrewAI, AutoGen, and LangGraph](/blog/crewai-autogen-langgraph-comparison) goes further on this point.
That conditional edge from "observe" back to "reason" is the whole point. Your agent reasons, acts, observes the result, and decides whether to keep going or stop. That's the agent loop. LangChain can't express this natively because chains don't cycle.
## The Real Decision Framework
I've shipped both in production. Here's what actually matters:
**Use LangChain when:**
- Your workflow is a pipeline (input transforms through stages to output)
- You're building RAG (retrieve, augment, generate, done)
- You need document processing chains
- The number of steps is known at design time
- You don't need the output of step 5 to decide whether to go back to step 2
**Use LangGraph when:**
- Your agent needs to loop (reason/act/observe cycles)
- Multiple agents need to hand off work to each other
- You need human-in-the-loop checkpoints where the workflow pauses
- Your workflow has branching AND merging (not just branching)
- State needs to persist across turns, retries, or even server restarts
The human-in-the-loop thing is underrated. LangGraph has first-class support for checkpointing. Your graph runs, hits a checkpoint node, serializes its entire state, and waits. A human reviews something, approves it, the graph resumes from exactly where it paused. Try doing that cleanly with LangChain. You can't without reinventing half of what LangGraph gives you.
## Where People Go Wrong
The most common mistake I see is reaching for LangGraph when a simple chain would do. Someone builds a RAG pipeline. It retrieves documents, reranks them, feeds them to a model, returns the answer. They build it as a LangGraph state machine with six nodes and conditional edges. Why? Because agents are cool and graphs sound impressive.
That pipeline is sequential. It doesn't loop. It doesn't need checkpoints. It doesn't have multiple agents. A LangChain chain handles it with half the code and none of the state management overhead. This connects directly to [LangChain in production RAG](/blog/production-rag-langchain-pgvector).
The second most common mistake is the opposite. Someone builds an agent that needs to retry failed tool calls, escalate to different strategies when the first one doesn't work, and maintain context across multiple reasoning cycles. They build it as a giant LangChain chain with recursive function calls and manual state management. It works until it doesn't, and debugging it is a nightmare because the control flow is hidden inside Python functions instead of being visible in a graph definition.
## Performance and Debugging
LangGraph's state machine approach has a practical benefit beyond expressiveness: observability. Every node transition is a discrete event. Every state mutation is logged. When something goes wrong, you can see exactly which node failed, what the state looked like going in, and where the graph was going to go next.
LangChain with LangSmith gives you tracing too, but the traces are linear. For a pipeline, that's fine. For a complex agent workflow crammed into a chain, the trace is a flat list of LLM calls that doesn't reveal the actual decision structure.
LangGraph also integrates with LangSmith, and the combination is genuinely powerful. You get graph-aware traces that show the actual topology of your execution, not just a flat call stack.
## Memory and Persistence
LangGraph's state is first-class. You define a typed state object, nodes read from and write to it, and the framework handles serialization. It supports persistent checkpointing out of the box with SQLite, PostgreSQL, or custom backends. Your agent can crash, restart, and resume from the last checkpoint. For a deeper look, see [multi-agent workflow alternatives](/blog/multi-agent-workflow-crewai).
LangChain has memory classes, but they're bolted on. `ConversationBufferMemory`, `ConversationSummaryMemory`, the various window and token-based variants. They work fine for chat applications where "memory" means "conversation history." They don't work as well for complex state that includes tool results, intermediate reasoning, pending actions, and multi-agent coordination data.
## The Honest Take
LangChain is mature, well-documented, and has the largest ecosystem of integrations. If you need to connect an LLM to a vector store, a web scraper, a SQL database, or any of a hundred other tools, LangChain probably has an integration for it. That's not nothing.
LangGraph is the right tool when you're building actual agents. Not "chatbot with a system prompt" agents. Real agents that reason, act, observe, and iterate. The state machine model maps cleanly to the agent loop, and the framework gives you persistence, checkpointing, and multi-agent coordination without reinventing them yourself.
They're not competitors. They're layers. Many production systems I've built use LangChain components (models, retrievers, tools) inside LangGraph nodes. The graph defines the workflow. The chains define what happens at each step.
Use both. Just use each one for what it's actually good at.