LangGraph vs LangChain: Two Faces of the Same Ecosystem
*A deep dive into the architectural DNA, use cases, and synergy of the two frameworks*
Reading both the LangChain and LangGraph docs evokes an image: a carpenter's toolbox containing both a hammer and a power drill. Which is better? Nobody asks — the answer is always "depends whether you're hammering nails or drilling holes."
LangChain and LangGraph, both from LangChain Inc. and part of one ecosystem, solve fundamentally different problems. Yet "LangChain vs LangGraph" debates persist because the boundary between them has shifted over time. This article clarifies both faces: their origins, their boundaries, when each should stand alone, and when they should work together.
Key points
1. Origins: From a chain to a graph
- Harrison Chase open-sourced LangChain in October 2022 to solve a simple pain point: manually gluing prompts, API calls, and output parsing. Its answer: standardized components (LLMs, prompt templates, vector stores, loaders) chained together. It grew to 80k GitHub stars within six months and became the de facto LLM app standard.
- LangChain's fatal built-in assumption: data flows one way along the chain — no loops, no backtracking, no pausing for human approval. Fine for RAG/translation/summarization; crippling for agents that need "search → think → search again → answer."
- In autumn 2023, drawing on Google's Pregel bulk-synchronous-parallel model, the team released LangGraph: model agent workflows as a directed graph where nodes are functions, edges are control flow, with loops, branching, and conditional routing.
- On October 22, 2025, both shipped v1.0 GA with a clear division of labor: LangChain = agent framework (abstractions/integrations for models, tools, prompts); LangGraph = orchestration runtime (durable execution, streaming, human-in-the-loop, resumability). LangChain's
create_agentruns on LangGraph's graph engine — they were never competitors. - LangChain's LCEL uses the pipe operator (
prompt | model) to compose components like Unix pipes. Underneath is a DAG execution model: deterministic successors, one-way data flow, no cycles. - LangGraph's StateGraph is a directed graph that allows cycles, built on Pregel-style supersteps (Plan → Execute → Update). Three pillars: 1. Explicit state — you define a global schema with
- LangChain
create_agent— a few lines start a working agent that decides when to search and when to answer. Covers 80% of common cases, but the decision logic is hidden inside the runtime; you can't inspect why step three chose to search rather than answer. - LangGraph native — the same agent in ~20 lines with
StateGraph,ToolNode, and a hand-writtenshould_use_toolrouter. Five times the code, but every routing decision is visible, loggable, and yours to modify. Notably,create_agentitself runs on a LangGraphStateGraph— it just writes fifteen of those twenty lines for you. - Checkpointer: after each superstep, full state snapshots are saved (SQLite/Postgres). Crashed runs resume via the same
thread_id; long-running agents can span minutes, hours, or sessions. Enables time-travel debugging — replay step N to inspect state, tool outputs, and decisions. - Human-in-the-loop:
interrupt()pauses the graph at a sensitive node (e.g. before emailing 10,000 users), collects human approval, then resumes — the agent asks before acting, rather than humans auditing after the fact.
2. Architectural DNA: DAG vs StateGraph
TypedDict; nodes return partial updates. Annotated[list, operator.add] declares additive (append) merging via custom reducers.
2. Explicit control flow — routing is a named function you write, e.g. should_continue() returning "summarize" or "search".
3. The graph is the documentation — compiled graphs export to Mermaid and debug visually in LangSmith Studio, valuable for code review and compliance audits.| Dimension | LangChain (LCEL) | LangGraph (StateGraph) |
|---|---|---|
| Graph model | DAG (acyclic) | Directed graph (cyclic) |
| State | Implicit, runtime-managed | Explicit TypedDict |
| Control flow | Automatic pipeline routing | Conditional edges + named functions |
| Loops | Not supported | Native |
| Parallelism | RunnableParallel | Graph parallel branches |
| Interrupt/resume | None | interrupt() + Command(resume=) |
| Persistence | DIY | Built-in SQLite/Postgres checkpointer |
| Streaming | Token-level | 7 modes (values/updates/messages/custom/checkpoints/tasks/debug) |