Why LangGraph?
Understand what LangGraph adds over LangChain's linear chains, when to reach for it, and how its graph-based control flow enables true agentic systems.
Why LangGraph?
LangChain gave developers a toolkit for chaining LLM calls. It works well for pipelines where the sequence of steps is fixed at authoring time: retrieve context, format prompt, call LLM, parse output. But real agent behavior rarely follows a straight line. An agent needs to decide, retry, loop, and branch — and for that, LangChain's sequential chains hit a wall.
LangGraph is the answer. It replaces the linear chain metaphor with a directed graph, where nodes are functions and edges are explicit transitions. You keep everything you like about LangChain (ChatOpenAI, retrievers, tool calling) and add the ability to express cycles, branches, and multi-step stateful logic.
What LangGraph Adds
| Capability | LangChain LCEL | LangGraph | |---|---|---| | Sequential steps | Yes | Yes | | Branching (if/else routing) | Limited | First-class | | Cycles and loops | No | Yes | | Persistent state across steps | No | Yes (state schema) | | Built-in checkpointing | No | Yes | | Human-in-the-loop pausing | No | Yes | | Multi-agent orchestration | No | Yes |
LangGraph is not a replacement for LangChain — it is built on top of it. You still use ChatOpenAI, PromptTemplate, and tool integrations. LangGraph provides the orchestration layer that decides which component runs next and what data it sees.
When to Use LangGraph
Use LangGraph when your agent needs any of the following:
Cycles — The agent must loop: reason, act, observe, reason again. The classic ReAct pattern is a cycle. LCEL has no way to express this.
Conditional routing — Based on the LLM output or retrieved data, execution must take different paths. LangGraph's add_conditional_edges makes this explicit and debuggable.
Multi-step state accumulation — The agent builds up information across many steps (retrieved documents, tool results, intermediate answers) and later steps depend on earlier ones.
Checkpointing and resumability — The agent must be able to pause, persist state, and resume later — either for human review or because it runs for a long time.
Human-in-the-loop — Before taking an irreversible action (sending an email, writing to a database), the agent must pause and wait for human approval.
Multi-agent systems — A supervisor orchestrates specialist agents. Each agent is a subgraph; the supervisor routes between them.
LangChain LCEL vs LangGraph
LCEL (LangChain Expression Language) uses the | pipe operator to chain runnables:
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI(model="gpt-4o-mini")
chain = (
ChatPromptTemplate.from_template("Answer this question: {question}")
| llm
| StrOutputParser()
)
result = chain.invoke({"question": "What is the capital of France?"})
print(result) # ParisThis is perfect for a single-pass pipeline. The moment you need to look at the output and decide whether to retry or route elsewhere, LCEL becomes awkward.
LangGraph expresses the same logic as a graph, but lets you add conditional edges afterward:
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
from typing import TypedDict
llm = ChatOpenAI(model="gpt-4o-mini")
class State(TypedDict):
question: str
answer: str
def answer_node(state: State) -> dict:
response = llm.invoke(state["question"])
return {"answer": response.content}
graph = StateGraph(State)
graph.add_node("answer", answer_node)
graph.add_edge(START, "answer")
graph.add_edge("answer", END)
app = graph.compile()
result = app.invoke({"question": "What is the capital of France?"})
print(result["answer"]) # ParisNow suppose you want to validate the answer and retry if it is too short:
def validate_node(state: State) -> dict:
# just pass through — routing logic is in the edge function
return {}
def route_after_validate(state: State) -> str:
if len(state["answer"]) < 20:
return "answer" # retry
return END
graph = StateGraph(State)
graph.add_node("answer", answer_node)
graph.add_node("validate", validate_node)
graph.add_edge(START, "answer")
graph.add_edge("answer", "validate")
graph.add_conditional_edges("validate", route_after_validate)
app = graph.compile()
result = app.invoke({"question": "Explain quantum entanglement briefly."})This is impossible to express cleanly in LCEL. In LangGraph it is four lines.
Key Concepts Preview
Before diving into code, here is a quick map of the core concepts:
StateGraph — The main class. You instantiate it with your state schema and register nodes and edges on it.
from langgraph.graph import StateGraph
graph = StateGraph(MyState)State schema — A TypedDict (or Pydantic model) that defines every piece of data that flows through the graph. Every node receives the full state and returns a partial update.
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
query: str
retrieved_docs: list[str]
final_answer: strNode — A plain Python function with the signature (state: MyState) -> dict. It reads from state, does work (call an LLM, query a database, call a tool), and returns only the keys it changed.
def retrieve_node(state: AgentState) -> dict:
docs = retriever.invoke(state["query"])
return {"retrieved_docs": [d.page_content for d in docs]}Edge — A connection from one node to another. Can be unconditional (add_edge) or conditional (add_conditional_edges).
graph.add_edge("retrieve", "generate") # always go from retrieve to generate
graph.add_conditional_edges("generate", decide_next) # routing functionSTART and END — Special sentinel nodes. START is the implicit entry point; END terminates the graph.
Installation
pip install langgraph langchain-openai langchain-coreFor checkpointing with SQLite (production-ready persistence):
pip install langgraph-checkpoint-sqliteFor the LangGraph development server and Studio UI (optional but recommended for debugging):
pip install langgraph-cliVerify installation:
import langgraph
import langchain_openai
print(langgraph.__version__) # e.g. 0.2.x
print(langchain_openai.__version__)Set your API key:
import os
os.environ["OPENAI_API_KEY"] = "sk-..."Or in a .env file:
OPENAI_API_KEY=sk-...A Minimal End-to-End Example
This is the smallest complete LangGraph program — a single-node graph that calls an LLM and returns the answer:
import os
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "sk-..."
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
class State(TypedDict):
question: str
answer: str
def llm_node(state: State) -> dict:
response = llm.invoke(state["question"])
return {"answer": response.content}
# Build the graph
builder = StateGraph(State)
builder.add_node("llm", llm_node)
builder.add_edge(START, "llm")
builder.add_edge("llm", END)
app = builder.compile()
# Run it
output = app.invoke({"question": "What is LangGraph used for?"})
print(output["answer"])Even this minimal example demonstrates the core pattern you will use throughout this course:
- Define a state schema
- Write node functions that read state and return partial updates
- Register nodes and edges on a
StateGraph - Compile and invoke
Why Not Just Use Python?
A fair question. You could implement branching and loops with plain Python functions. LangGraph adds:
- Automatic checkpointing — State is saved after every node with zero extra code
- Built-in streaming — Call
app.stream(input)to get updates after each node - Human-in-the-loop — Pause and resume with
interrupt_before - Studio visualization — The LangGraph Studio UI renders your graph interactively
- Thread management — Multiple concurrent conversations with separate state via
thread_id - Time travel — Replay from any past checkpoint
These are hard to build from scratch. LangGraph gives them to you out of the box.
Summary
| Use LCEL when | Use LangGraph when | |---|---| | Single-pass pipeline | Cycles or retries needed | | No state accumulation | State builds across many steps | | No human review needed | Human approval required | | Simple chains | Multi-agent orchestration | | Prototyping quickly | Production agent systems |
The rest of this course builds up every concept — state schemas, conditional edges, cycles, checkpointing, human-in-the-loop, subgraphs, and multi-agent supervision — using real LangGraph code you can run today.
Found this helpful?
Leave a comment
Have a question, correction, or just found this helpful? Leave a note below.