LangGraph Setup Guide
Complete setup and configuration guide for LangGraph — LangChain's low-level orchestration framework for building stateful agents. Graph-based, durable execution, checkpointing, and human-in-the-loop.
LangGraph
LangGraph is LangChain's low-level framework for building stateful, long-running agents. Instead of role-based or conversation-based coordination, LangGraph models agents as directed graphs — nodes are steps, edges are transitions, and state flows through. Built-in checkpointing means agents survive crashes and resume from exactly where they left off.
Companies like Klarna, Replit, and Elastic run LangGraph in production. For a higher-level agent framework built on top of LangGraph, see Deep Agents — same graph engine, more opinionated defaults.
Note:
LangGraph is lower-level than CrewAI or AutoGen. You define nodes, edges, and state schemas explicitly. This gives you full control but more code. Use LangGraph when you need durable execution (agents that run for hours), complex conditional routing, or fine-grained state management. Use CrewAI/AutoGen for rapid prototyping.
Installation
Install LangGraph
Python 3.10+ required. Install the core package plus a model provider.
pip install langgraph langchain-openai
Configure API Keys
LangGraph is model-agnostic. Set keys for your preferred provider.
export OPENAI_API_KEY=sk-...
# or for Anthropic
export ANTHROPIC_API_KEY=sk-ant-...
Verify Installation
Build a minimal graph that routes based on LLM output.
from langgraph.graph import StateGraph, END
from typing import TypedDict
class State(TypedDict):
messages: list
def chat_node(state):
# Your LLM logic here
return {"messages": state["messages"] + [{"role": "ai", "content": "Hello"}]}
graph = StateGraph(State)
graph.add_node("chat", chat_node)
graph.set_entry_point("chat")
graph.add_edge("chat", END)
app = graph.compile()
Core Concepts
Architecture Overview
Values: StateGraph(StateSchema)
Values: graph.add_node(name, function)
Values: graph.add_edge(from, to) | graph.add_conditional_edges(from, router, mapping)
Values: MemorySaver (dev), SqliteSaver, PostgresSaver (prod)
Building a Graph
A simple agent that decides whether to call a tool or respond directly.
from typing import TypedDict, Literal, Annotated
from langgraph.graph import StateGraph, END, add_messages
from langgraph.checkpoint.memory import MemorySaver
from langchain_openai import ChatOpenAI
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
llm = ChatOpenAI(model="gpt-4o")
def call_model(state: AgentState):
response = llm.invoke(state["messages"])
return {"messages": [response]}
def route_after_model(state: AgentState) -> Literal["call_tool", END]:
last_message = state["messages"][-1]
if hasattr(last_message, "tool_calls") and last_message.tool_calls:
return "call_tool"
return END
def execute_tool(state: AgentState):
last_message = state["messages"][-1]
# Execute tool calls and return results
results = []
for tool_call in last_message.tool_calls:
# ... tool execution logic
results.append(f"Tool {tool_call['name']} result: ...")
return {"messages": [{"role": "tool", "content": r} for r in results]}
# Build the graph
graph = StateGraph(AgentState)
graph.add_node("agent", call_model)
graph.add_node("tools", execute_tool)
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", route_after_model, {"call_tool": "tools", END: END})
graph.add_edge("tools", "agent") # Loop back to agent after tools
Checkpointing: Durable Execution
A checkpointer persists graph state after every super-step. If your process crashes mid-execution, resume with the same thread ID and the graph picks up where it left off.
from langgraph.checkpoint.sqlite import SqliteSaver
# Dev: in-memory (lost on restart)
checkpointer = MemorySaver()
# Production: SQLite or Postgres (survives restarts)
checkpointer = SqliteSaver.from_conn_string("checkpoints.db")
app = graph.compile(checkpointer=checkpointer)
# First run
config = {"configurable": {"thread_id": "user-123"}}
result = app.invoke({"messages": [{"role": "user", "content": "Research AI trends"}]}, config)
# If the process crashes here, restart and resume:
result = app.invoke(None, config) # Picks up from last checkpoint
Human-in-the-Loop
Interrupt graph execution at a specific node and wait for human approval before continuing.
from langgraph.types import interrupt, Command
def sensitive_action(state: AgentState):
# This node requires human approval
approval = interrupt(f"Approve this action? State: {state}")
if approval != "yes":
return {"messages": [{"role": "ai", "content": "Action rejected by human."}]}
# ... proceed with sensitive action
# The graph pauses at interrupt(). Resume with:
app.invoke(Command(resume="yes"), config)
Memory
LangGraph supports two memory layers:
Memory Types
Values: StateGraph(StateSchema)
Values: Store (InMemoryStore for dev, PostgresStore for prod)
Model Wiring
LangGraph is model-agnostic — use any LangChain chat model.
# OpenAI
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# Anthropic
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-20250514")
# Google
from langchain_google_genai import ChatGoogleGenerativeAI
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash")
# Ollama (local)
from langchain_ollama import ChatOllama
llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")
# All are dropped into the same graph node
def call_model(state):
response = llm.invoke(state["messages"])
return {"messages": [response]}
Note:
Graph complexity. LangGraph's power comes at a cost. A graph with 5 nodes, conditional edges, a checkpointer, and memory is ~100 lines of setup code. For simple chatbots, this is overkill. LangGraph earns its keep when you need durable execution, complex routing, or human-in-the-loop at specific execution points.
Key Takeaway
LangGraph is the right choice when your agent needs to survive restarts or run for extended periods. The checkpointing system means crash recovery is automatic — no custom retry logic. Pair it with LangSmith for debugging: visualize every node transition, inspect state at each step, and trace token usage. The tradeoff is verbosity: you define every node and edge explicitly. CrewAI gives you a working agent in 30 lines; LangGraph gives you a production-grade durable agent in 150.
Related Articles
Data Insights Agent Blueprint
AI agent that analyzes datasets: statistical summaries, correlation analysis, outlier detection, chart generation, and written insight reports. Runs on CSV and JSON files with pandas and matplotlib.
CrewAI Setup Guide
Complete setup and configuration guide for CrewAI — the most popular open-source multi-agent orchestration framework. Role-based agents, Flows + Crews architecture, event-driven state management.
Content Writer Agent Blueprint
Multi-step content creation agent with outline, research, draft, edit, and finalization stages. Includes grammar checking, tone adjustment, and SEO optimization tools.