Guide

LangChain vs LangGraph: when to use each

Use LangChain when your application is mostly a straight line of steps and you want ready-made components for models, prompts, retrievers and tools. Use LangGraph when you need explicit control over state, branching, loops, retries or pauses for human review. They are not strict rivals, and a project can use both.

The short version of the difference

The two libraries answer different questions. LangChain mainly answers "how do I connect to models, prompts, retrievers and tools without writing every integration myself?" LangGraph mainly answers "how do I control what happens next, keep track of state and recover when a run does not go to plan?"

That makes the choice less about which library is better and more about the shape of your program. A pipeline that always runs the same steps in the same order has little need for a graph. A process that can loop, branch, wait for a person or resume after a failure is difficult to express and operate without something that treats those behaviours as first-class.

QuestionLangChainLangGraph
Main concernComponents and integrationsControl flow and state
Natural shapeA sequence of stepsA graph that may contain cycles
StateUsually passed along from step to stepA defined object that nodes read and update
Recovery and pausesSomething you would generally add yourselfSupported through checkpointing and interrupts
Good first fitSummarising, extraction, simple RAGAgents, routers, multi-step workflows with review

Both projects change quickly, so treat this as a description of their general purpose and check the current documentation for specific APIs. Choosing by need also holds up better over time than choosing from a feature list you read once.

When LangChain is the better fit

Reach for LangChain's components when the difficult part of your work is connecting things, not deciding what happens next. Common examples include:

  • Single-pass transformations. Summarise a document, classify a ticket or extract fields, then return the result.
  • Straightforward RAG. Retrieve passages, build a prompt and generate an answer, with no decisions in between.
  • Swapping providers. A common interface can reduce the code that changes when you try another model, although providers still differ in behaviour and features.
  • Using existing integrations. Document loaders, text splitters and vector store connectors can save writing and maintaining the same code yourself.

The cost is an extra layer of abstraction. When something behaves unexpectedly, you may need to work out what the library sent to the model. Log the final prompts and responses from the beginning, so that you are never guessing.

When LangGraph is the better fit

LangGraph earns its extra concepts when the path through your program depends on what happens during the run. Look for these signs:

  • The next step depends on a result. A router sends a question to different handlers, or a low-confidence answer goes to a person.
  • The program needs loops. An agent calls tools until it has enough information, or a draft is revised until it passes a check. Loops also need limits, and a graph gives them an obvious place to live.
  • A run must survive interruptions. Long processes should be able to resume from a saved point without repeating completed work.
  • A person has to approve something. Pausing a run, waiting for a decision and continuing later is a state problem. Human-in-the-loop approval covers the design decisions involved.
  • Several specialised roles work together. If you have established that several agents are justified, a graph can make the handoffs between them visible.

The cost here is more design work up front. You define a state schema, nodes and routing, and you think about what happens when a step is run again. For a two-step pipeline, that is overhead with no return.

The same task in each shape

Imagine answering a support question from a knowledge base. The linear version is a plain sequence. This sample is illustrative, and the helper functions stand in for your own code or library components:

# Illustrative only. Helper functions are placeholders.
def answer(question):
    passages = retrieve(question)
    prompt = build_prompt(question, passages)
    return call_model(prompt)

Now suppose the requirements change. If no good passage is found, rewrite the query and try once more. If there is still nothing, hand over to a person. The logic now has a branch, a loop and a limit, and the graph version makes those explicit. This sample is also illustrative, so check the current LangGraph documentation for exact usage:

# Illustrative only. Node functions and check_results are placeholders.
from langgraph.graph import StateGraph, START, END

graph = StateGraph(SupportState)
graph.add_node("retrieve", retrieve_node)
graph.add_node("rewrite", rewrite_node)
graph.add_node("answer", answer_node)
graph.add_node("handoff", handoff_node)

graph.add_edge(START, "retrieve")
graph.add_conditional_edges("retrieve", check_results, {
    "good": "answer",
    "retry": "rewrite",
    "give_up": "handoff",
})
graph.add_edge("rewrite", "retrieve")
graph.add_edge("answer", END)
graph.add_edge("handoff", END)

app = graph.compile()

Here, check_results reads the state, including a retry counter, and returns one of the three labels. The worked example in building an orchestrator with LangGraph goes through state, routing and checkpointing in depth.

Using them together

Because the two libraries work at different levels, a common arrangement is to use LangGraph for the overall flow and LangChain components inside individual nodes. A node might use a LangChain retriever or model wrapper, while the graph decides when that node runs and what happens afterwards.

Neither direction is compulsory. A LangGraph node is essentially your own function, so it can call a provider's SDK directly or query your database with ordinary code. You can adopt the graph without building everything else from LangChain's higher-level pieces.

Keep the boundary clean by putting business logic in plain functions and calling them from nodes. Those functions can then be tested without a graph or a model, and replacing a library later affects far less code.

When to use neither

Frameworks are optional. If your application makes one or two model calls with a known prompt, the provider's SDK and a few functions may be clearer than any abstraction. Plain code also has advantages when you are learning, because you see exactly what is sent and returned. Tool calling, for example, is much easier to reason about once you have written the loop by hand.

Consider adding a library once you can name the specific problem it solves, such as a persistence layer you would otherwise write yourself, or several integrations you would otherwise maintain. "We might need it later" is a weak reason, since moving from plain functions to a graph is usually straightforward when those functions are already well separated.

A simple way to decide

  1. Draw the process on paper. Include failures, retries and any point where a person gets involved.
  2. Is it a straight line? Use plain code, or LangChain components if they save real work.
  3. Are there branches but no state to keep? Ordinary conditionals may be all you need.
  4. Are there loops, long-running work, resumption or approval? Consider LangGraph, and write down the limits on each loop.
  5. Prototype the hardest path. Test the failure or pause, not only the path where everything works.

Common mistakes

  • Choosing by popularity. Neither library is a mark of a serious project. A short, readable script is often the right design.
  • Hiding logic inside prompts. If a rule must always hold, such as a retry limit or a permission check, enforce it in code or graph structure instead of asking the model.
  • Letting state grow unchecked. A state object that holds everything becomes hard to understand. Store only what later steps need.
  • Ignoring upgrades. Fast-moving libraries can change their interfaces. Pin your dependencies, keep your own wrappers thin and rely on tests to reveal what changed.

For help designing the control layer of an agent system, see AI orchestration with LangGraph.

Frequently asked questions

Is LangGraph a replacement for LangChain?

Not in general. LangGraph focuses on control flow and state, while LangChain focuses on components and integrations. They can be used together, and a graph's nodes can also call plain code instead.

Do I need LangChain to use LangGraph?

You do not need to build your application from LangChain's higher-level pieces. A node is essentially your own function, so it can call a provider's SDK directly. Check the current documentation for package details.

Should a beginner start with LangChain or LangGraph?

Start with the simplest thing that works, often a direct model call in plain code. That shows what the libraries are doing for you. Add components when they save work, and a graph when control flow demands it.

Can a simple RAG application use LangGraph?

It can, but a linear retrieve-and-answer pipeline gains little from it. A graph becomes more useful once you add query rewriting, retries, routing or human review.