LangChain vs LangGraph is usually a layer choice, not a swap between unrelated agent stacks: LangChain provides the agent framework for models, tools, and loops, while LangGraph provides the lower-level orchestration runtime for long-running, stateful agents (LangChain’s product map; LangGraph overview). In practice, LangChain organizes the harness around a model loop; LangGraph makes shared state, graph transitions, persistence, and external-input pauses part of the workflow you control (LangChain overview; Graph API overview; LangGraph interrupts). This comparison is based on each project’s documentation; we have not benchmarked either framework.
LangChain vs LangGraph
At the LangChain layer, create_agent is described as a minimal, configurable harness: everything around the model loop, including the prompt, tools, and middleware that shapes behavior. Your immediate setup work is therefore selecting those components and deciding how the agent should call them. LangChain’s broader framing is a framework for agents and LLM-powered applications assembled from interoperable components and integrations.
The projects are not mutually exclusive. LangChain is built on LangGraph, but its documentation says you do not need to understand LangGraph to use LangChain. Conversely, LangGraph can be used without LangChain, although its documentation commonly uses LangChain components for models and tools. Selecting one does not require removing the other from the architecture.
Stateful agent workflows
LangGraph represents a workflow as a graph built around State, Nodes, and Edges. State is the shared data structure holding the application’s current snapshot. That explicit state model is the central practical difference: the workflow has a defined place where its current data lives, rather than leaving state implicit in the agent harness.
A LangGraph checkpointer saves a graph-state snapshot at each super-step and organises those snapshots into threads. The documentation says compiling a graph with a checkpointer enables human-in-the-loop workflows, time-travel debugging, fault-tolerant execution, and conversational memory. These are orchestration capabilities attached to the graph runtime, not features implied merely by having tools and a model loop.
What changes in practice
With LangChain, the main setup surface remains the agent harness. A LangChain agent can receive thread-level short-term persistence by specifying a checkpointer when the agent is created, but that capability sits around the agent rather than replacing its model-and-tool structure.
With LangGraph, you also have to define the state shape, identify workflow nodes, connect them with edges, and decide how execution should be persisted. The documentation particularly associates LangGraph with fine-grained orchestration and workflows that mix deterministic steps with agentic steps. The practical shift is from choosing agent components to owning the complete state-transition model.
In our setup, we keep a single writer per file and inspect real system state after a restart before redoing work. Those are coordination rules we apply whichever framework is chosen, not claims about either framework’s built-in behaviour.
| Concern | LangChain | LangGraph | What changes in practice |
|---|---|---|---|
| Primary role | Agent framework and configurable harness | Low-level orchestration runtime and stateful-agent runtime | The level at which you define control moves upward |
| Core design | Prompt, tools, middleware, and model loop | State, Nodes, and Edges | Component configuration becomes explicit graph design |
| State and memory | Thread-level short-term memory can be attached through a checkpointer |
Checkpointers save state snapshots in threads | Persistence is available around either architecture, but Graph makes it a central runtime concern |
| Human input | Its human-in-the-loop flow saves graph state through LangGraph’s persistence layer | Interrupts pause selected points until execution resumes | Approval becomes an explicit state and resume path |
| Relationship | Built on LangGraph, without requiring direct knowledge of it | Can run without LangChain | The frameworks can be layers in the same system rather than competing packages |
When each one fits
LangChain’s documented fit is quick agent construction, standard abstractions for models, tools, and agent loops, and straightforward applications without complex orchestration. If the agent’s main job is to choose tools and return an answer, staying at the harness level keeps the application boundary smaller.
LangGraph’s documented fit is long-running, stateful execution; fine-grained control; deterministic and agentic steps combined in one workflow; and production-oriented deployment infrastructure. These use cases arise when pausing, resuming, branching, or recovering execution is part of the application itself.
A practical test is to inspect where the difficult behaviour lives. If it is inside model selection, tool use, or the agent loop, LangChain directly addresses that layer. If it is in transitions between steps, approval waits, or recovering a partially completed workflow, LangGraph’s explicit orchestration model is the more relevant layer.
Where each gets in the way
LangChain becomes the less direct abstraction when orchestration itself is the main engineering problem. Its documentation positions complex, low-level workflow control under LangGraph. An application with long-lived state and explicit pause-resume points may therefore begin with LangChain’s agent harness but still need the Graph runtime underneath it.
LangGraph introduces more design work for a simple agent. You must define State and the graph structure, select persistence, and decide where execution should pause. The documentation calls it a low-level framework, so it does not describe a universal threshold at which that additional structure becomes worthwhile.
Neither project’s documentation establishes comparative limits for latency, throughput, token use, graph size, or success rate. There is no documented rule that reliably predicts which framework will be faster or cheaper for your workload, and we have no measurements to add.
Set it up
The documentation does not specify one installation command, CLI flag, configuration-file path, or copy-and-run setup that applies to both projects. It does provide the following setup names. Treat them as an identifier checklist, not an importable script:
create_agent
checkpointer
MemorySaver
InMemorySaver
PostgresSaver
SqliteSaver
For a LangChain-centred agent, create the harness with create_agent. If the application needs thread-level short-term memory, supply a checkpointer when creating the agent. The current LangChain documentation should determine the exact import and call signature for your environment.
For a LangGraph workflow, define State and arrange the workflow’s behaviour through Nodes and Edges. Compile the graph with a checkpointer when you need checkpointed execution. Persistence is not interchangeable: MemorySaver and InMemorySaver keep checkpoints in RAM and lose them when the process restarts; the documentation identifies PostgresSaver as a PostgreSQL option with asynchronous support for production and SqliteSaver as file-based storage for local development.
If the workflow waits for a person or another system, plan the pause and resume path as part of the graph rather than as an incidental callback. LangGraph interrupts can pause at selected points, save state through the persistence layer, and wait for external input. Use the current project documentation for exact setup syntax; the names above do not establish package versions or function signatures.
Check it worked
Check the system at the boundary introduced by your choice:
- Agent harness: Confirm that the prompt, tools, and middleware are attached to the agent harness rather than scattered through unrelated call paths.
- Shared state: Inspect State after a workflow transition and confirm that it represents the current application snapshot you intended to preserve.
- Checkpoints: Let execution cross graph super-steps, then inspect the saved snapshots for the relevant thread. A checkpointer is what enables the documented checkpoint capabilities.
- Restart behaviour: With a persistent backend, restart the process and resume the same thread to verify that the saved state is available. Do not use an in-memory saver as evidence of restart persistence.
- External input: Trigger an interrupt, confirm that execution waits, provide the required input, resume the graph, and inspect the resulting state.
- User-visible result: Read the workflow result back from the application surface that will actually use it.
In our setup, done means checked. A successful process exit or an agent summary is a signal, not proof that the persisted state or user-visible result is correct.
Where it breaks
The first failure mode is treating live state as durable state. A graph can hold State during execution without a checkpointer preserving snapshots for later recovery. Do not infer restart safety merely because the current process can see the state.
The second failure mode is choosing RAM persistence for a process that must survive restart. The documented behaviour of MemorySaver and InMemorySaver is explicit: all checkpoints are lost when the process restarts.
A waiting workflow can also remain incomplete indefinitely when an interrupt is triggered but the expected external input never arrives. That is documented behaviour, so your application needs an operational way to identify, resume, or deliberately end the waiting execution.
Checkpoint schema evolution is another boundary the documentation does not settle here. It does not specify in this overview how to migrate previously saved state after you change the State structure, so check the current persistence documentation before changing a live schema.
Finally, time-travel debugging should not be interpreted as automatic rollback of external side effects. The documentation says checkpointing enables time-travel debugging, but it does not say that database writes, messages, payments, or deployments are reversed with the graph state. Our operating rule after a restart is to check the real external state before retrying, rather than assuming that resuming the graph tells us whether an outside action already landed.