Technical

LangChain vs LangGraph

Not an either/or. One composes pipelines, the other manages control flow — and knowing which problem you have saves weeks.

Home Blog LangChain vs LangGraph
Short answer

LangChain composes LLM calls, tools and retrievers into pipelines that run from start to finish. LangGraph models your application as a state machine — explicit nodes, edges and shared state — so it can branch, loop, pause for a human and resume.

Use LangChain for linear work: a RAG pipeline, a summarisation chain, a single tool-calling step. Use LangGraph the moment the system needs to decide what to do next based on what just happened. They are built by the same team and compose together — this is not an either/or.

What LangChain is good at

LangChain is a component library plus a composition syntax. Its real value is the breadth of integrations — dozens of model providers, vector stores, document loaders and tools behind consistent interfaces — and the ability to wire them together compactly.

# a RAG chain: retrieve, format, generate, parse
chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)
chain.invoke("What is the refund policy?")

That runs left to right, once. For a large share of real applications — search over documents, classify then route, summarise then extract — that is exactly the right shape, and reaching for anything heavier is over-engineering.

Where it gets uncomfortable is control flow. Expressing "retry with a rewritten query if retrieval returned nothing relevant, but give up after three attempts" inside a chain means conditionals scattered through composition syntax, and it becomes difficult to see what the program actually does.

What LangGraph adds

LangGraph reframes the application as a graph. You define a state object, functions that read and update it (nodes), and rules for which node runs next (edges). Control flow becomes data you can inspect rather than logic buried in composition.

class State(TypedDict):
    question: str
    docs: list
    attempts: int
    answer: str

graph = StateGraph(State)
graph.add_node("retrieve", retrieve)
graph.add_node("grade", grade_relevance)
graph.add_node("rewrite", rewrite_query)
graph.add_node("generate", generate)

graph.add_edge("retrieve", "grade")
graph.add_conditional_edges("grade", route, {
    "good":  "generate",
    "retry": "rewrite",     # cycles back to retrieve
    "give_up": END,
})
graph.add_edge("rewrite", "retrieve")

Four capabilities follow from that structure, and they are the reason production agent work has moved this way:

Side by side

LangChainLangGraph
ShapePipeline, runs once throughState machine with explicit transitions
BranchingAwkward — conditionals inside compositionFirst-class conditional edges
LoopsNot really supportedCore feature, with bounds
StatePassed along the chainExplicit, typed, shared, inspectable
Pause & resumeNoYes, via checkpointing
Human approvalHand-rolledBuilt in — interrupt before a node
DebuggingTrace the chainInspect state at each node; replay from any point
Best forRAG, summarisation, classification, single tool callsAgents, multi-step workflows, multi-agent systems
OverheadLowMore setup — worth it once control flow is real

Why AgentExecutor gave way to graphs

LangChain's original agent abstraction, AgentExecutor, ran a hidden loop: call the model, parse a tool request, run the tool, feed the result back, repeat until it decided to stop. It was elegant to start with and painful in production, for one reason — the control flow was inside the framework, not in your code.

When an agent looped twelve times, called the wrong tool, or stopped early, you could observe that it happened but not easily change how the decision was made. There was no clean way to insert an approval step, bound a specific branch, or resume a failed run partway through.

LangGraph's answer is to make the loop yours. The cost is more code up front; the benefit is that every failure has a location. In a system where an LLM decides what happens next, that is not a nicety — it is the difference between something you can operate and something you can only restart.

The practical tell. If you cannot draw your application's control flow on a whiteboard, you should not be running it in production. LangGraph forces you to draw it before it will run at all — which is a feature disguised as friction.

When to use neither

Worth saying plainly, because framework enthusiasm costs teams real time: if your application is one LLM call, or a fixed two-step sequence with no branching, use the provider SDK directly.

# this needs no framework
response = client.messages.create(
    model="claude-opus-5",
    messages=[{"role": "user", "content": prompt}],
)

Fewer dependencies, no abstraction to learn, and a stack trace that points at your own code. Frameworks earn their overhead when there is genuine complexity to manage — many integrations, real control flow, state that must survive a restart. Below that threshold they add indirection and nothing else.

What to learn, in what order

  1. Raw API calls first. Understand messages, tokens, temperature and tool schemas without a framework in the way. Everything above this is a convenience layer over it.
  2. Retrieval and RAG. Embeddings, chunking, vector stores, evaluation. See RAG vs fine-tuning for where each belongs.
  3. LangChain. Components and composition. Build a real RAG pipeline with it.
  4. LangGraph. State, nodes, conditional edges, checkpointing, human-in-the-loop. Build something that loops and can be interrupted.
  5. Tracing and evaluation. LangSmith. Agents fail in ways single calls do not, and without tracing you are guessing.

That ordering is deliberate. Learning LangGraph before understanding retrieval and evaluation produces someone who can assemble a graph and cannot tell why it returns poor answers — because the problem is usually two layers below the graph. It is the sequence our Agentic AI course follows, after Generative AI and RAG are already solid.

Frequently asked questions

What is the difference between LangChain and LangGraph?

LangChain composes LLM calls, tools and retrievers into pipelines that run start to finish. LangGraph models an application as a state machine — explicit nodes, edges and shared state — which lets it branch, loop, pause and resume. LangChain suits linear workflows; LangGraph suits anything that needs to make decisions about what to do next.

Is LangGraph replacing LangChain?

No. They are built by the same team and compose together — LangGraph nodes routinely call LangChain retrievers, tools and models. LangGraph replaces LangChain's old AgentExecutor for agent control flow, but not LangChain's component library.

Do I need LangChain to use LangGraph?

No. LangGraph works with plain provider SDK calls inside its nodes. Most teams use LangChain components because the retrievers and tool abstractions save time, but it is not a requirement.

When should I not use a framework at all?

When your application is a single LLM call, or a fixed two-step sequence with no branching. A direct call to the provider SDK is clearer, has fewer dependencies and is easier to debug. Frameworks earn their overhead when there is real control flow to manage.

Which should I learn first?

LangChain first, for components and the mental model of chaining. LangGraph immediately after, because production agent work is converging on it. Learning LangGraph without understanding retrieval, tools and evaluation produces systems you cannot debug when they loop or stall.

PreviousRAG vs Fine-Tuning: When to Use Which

Build agents that survive production

LangChain, LangGraph, MCP and multi-agent systems — taught after RAG and evaluation are solid, because that ordering is what makes them debuggable.