What is LangGraph?
Understand LangGraph, graph-based agents vs traditional chains, stateful vs stateless execution, and how LangGraph differs from LangChain.
What is LangGraph?
LangGraph is a framework from LangChain for building stateful, multi-actor applications using directed graphs as the core abstraction. Each node in the graph modifies a shared state, and edges define the flow of execution.
LangGraph is not a workflow DAG tool. Nodes can be revisited, loops can form, and state is preserved across cycles. This is what makes it suitable for agentic systems that need to reason, act, and adapt.
Graph-Based Agents vs Traditional Chains
Traditional Chains
In traditional LangChain, you build linear chains where each step passes its output to the next:
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
prompt = PromptTemplate.from_template("Tell me about {topic}")
chain = prompt | llm | output_parser
result = chain.invoke({"topic": "AI agents"})Chains are linear, predictable, and stateless between runs. Once a chain completes, all intermediate data is lost. There is no concept of loops, branching, or state management.
Graph-Based Agents
LangGraph replaces the linear chain with a graph where:
- Nodes are independent functions that can read and write to a shared state
- Edges define which node runs next
- Conditions can route execution based on the current state
- Loops allow agents to iterate until a condition is met
from langgraph.graph import StateGraph
from typing import TypedDict, List
class AgentState(TypedDict):
messages: List[str]
agent_decision: str
def analyze(state: AgentState) -> dict:
decision = decide_next_step(state["messages"])
return {"agent_decision": decision}
def execute(state: AgentState) -> dict:
result = perform_action(state["agent_decision"])
return {"messages": state["messages"] + [result]}
graph = StateGraph(AgentState)
graph.add_node("analyze", analyze)
graph.add_node("execute", execute)
graph.add_edge("analyze", "execute")
graph.set_entry_point("analyze")
graph.set_finish_point("execute")Graphs give you loops, branching, persistence, and dynamic routing β all essential for building autonomous agents.
Stateful vs Stateless Execution
Stateless Execution
In a stateless system, each invocation is independent. No information persists between calls:
# Stateless β each call starts fresh
response = llm.invoke("What is 2+2?")
response = llm.invoke("Now add 5") # LLM forgot the previous answerStateful Execution
LangGraph maintains a shared state object that persists across all nodes in the graph. Each node can read the full state and return updates:
class ConversationState(TypedDict):
messages: List[str]
turn_count: int
def chatbot(state: ConversationState) -> dict:
user_msg = get_user_input()
new_messages = state["messages"] + [user_msg]
response = llm.invoke("\n".join(new_messages))
return {
"messages": new_messages + [response],
"turn_count": state["turn_count"] + 1
}The state flows through every node and is preserved across cycles, enabling memory, context, and multi-step reasoning.
State in LangGraph is not persisted to disk by default. You add persistence via MemorySaver or other checkpointers (covered in the Intermediate course).
LangChain vs LangGraph
| Feature | LangChain | LangGraph |
|---|---|---|
| Execution model | Linear chains (DAG) | Cyclic graphs |
| State management | Manual (pass between steps) | Automatic (shared state) |
| Loops | Not supported | First-class support |
| Branching | Sequential only | Conditional, parallel |
| Persistence | Not built-in | Via checkpointers |
| Human-in-the-loop | Not supported | Via interrupt() |
| Best for | Simple LLM pipelines | Complex agent workflows |
When to Use LangChain Alone
- You have a straightforward prompt β LLM β output pipeline
- No looping or conditional logic is needed
- You don't need to persist intermediate state
- Example: summarization, translation, simple Q&A
When to Use LangGraph
- You need agents that can reason, act, and observe in a loop
- The flow depends on intermediate results (conditional routing)
- You need memory, persistence, or human-in-the-loop
- Example: autonomous coding agents, research assistants, customer support bots
# LangChain: Simple and linear
chain = prompt | llm | parser
result = chain.invoke(input)
# LangGraph: Flexible and stateful
graph = StateGraph(State)
graph.add_node("think", think_node)
graph.add_node("act", act_node)
graph.add_node("observe", observe_node)
graph.add_conditional_edges("think", should_continue, {True: "act", False: END})
graph.add_edge("act", "observe")
graph.add_edge("observe", "think")
app = graph.compile()
result = app.invoke(initial_state)Why Graphs for Agents?
Agents need to perform multi-step reasoning, use tools, interpret results, and decide on the next action. This naturally maps to a graph structure:
- Think: The agent analyzes the current state and decides what to do
- Act: The agent executes a tool call or generates a response
- Observe: The agent processes the tool output
- Loop: The agent repeats until the task is complete
Input β [Think] β decide β [Act] β [Observe] β decide β [Think] β ...
β |
βββ continue βββββββββββ
[Stop] β Output
This loop is the foundation of every ReAct agent. LangGraph makes it trivial to implement.
The ReAct pattern (Reason + Act) is the most common agent architecture. LangGraph's graph structure is the ideal way to implement it β each turn of the loop is a node execution.
Core Primitives
LangGraph has five core primitives:
| Primitive | Description | Example |
|---|---|---|
StateGraph | The graph builder class | StateGraph(AgentState) |
State | A typed dictionary shared across nodes | class AgentState(TypedDict) |
Node | A Python function that mutates state | def my_node(state) -> dict |
Edge | A connection between nodes | graph.add_edge("a", "b") |
Condition | A routing function for conditional edges | lambda s: "b" if s["done"] else "c" |
Installation
pip install langgraph langchain-openaiLangGraph requires Python 3.9+. It is compatible with all LangChain integrations (LLMs, vector stores, tools, etc.).
Minimal setup for a first graph:
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
class MyState(TypedDict):
value: str
def echo(state: MyState) -> dict:
return {"value": f"Echo: {state['value']}"}
builder = StateGraph(MyState)
builder.add_node("echo", echo)
builder.add_edge(START, "echo")
builder.add_edge("echo", END)
app = builder.compile()
result = app.invoke({"value": "hello"})
print(result["value"]) # Echo: helloReal-World Use Cases
Customer Support Agent
A graph routes customer queries through intent classification, knowledge base search, ticket creation, and escalation to humans.
Code Generation Agent
An agent that writes code, runs tests, reads error output, and iteratively fixes bugs β all within a single graph with a loop.
Research Assistant
A multi-step agent that searches the web, summarizes findings, generates reports, and asks clarifying questions when needed.
Data Pipeline Orchestrator
A graph that ingests data, validates it, transforms it, loads it into a database, and sends notifications β with error handling at every step.
LangGraph transforms complex agent logic from spaghetti code into a clean, visual, and debuggable graph structure.
Practice Questions
What is the main difference between LangChain chains and LangGraph graphs?
What does a LangGraph node function receive and return?
Which LangGraph class should you use for building stateful agents?
What is the ReAct pattern?
LangGraph is best suited for which type of application?
What command installs LangGraph?
Which of the following is NOT a feature of LangGraph?
How does state flow in a LangGraph application?
What makes LangGraph suitable for building autonomous agents?
What does the compile() method do in LangGraph?
Key Takeaways
- LangGraph uses directed graphs with shared state for building agents
- Graphs support loops, conditional branching, and persistence β unlike linear chains
- State flows through all nodes; each node receives full state and returns partial updates
- StateGraph is the primary class for building LangGraph applications
- The ReAct pattern (reason β act β observe β loop) is a natural fit for graphs
- LangGraph is installed via
pip install langgraphand integrates with all LangChain components