LangGraph
LangGraph is a Python (and JS) framework for building stateful, multi-step agents as directed graphs. Each step is a node; transitions between steps are edges; cycles are supported. It's part of the LangChain ecosystem but can be used independently.
Core Concepts
Node — a function that takes state as input and returns an updated state. A node is a model call, a tool execution, a data transformation, or any Python function.
Edge — a connection between nodes. Edges can be unconditional (always go to node B after node A) or conditional (route based on the current state value).
State — a typed dictionary that flows through the graph. Every node reads from and writes to state. State is the shared memory of the agent.
Cycles — unlike a linear pipeline, LangGraph graphs can loop. An agent can call a tool, evaluate the result, and decide to call another tool or loop back before producing a final answer.
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
tool_calls_made: int
def call_model(state: AgentState) -> AgentState:
# Call model with current messages
response = llm.invoke(state["messages"])
return {"messages": [response], "tool_calls_made": state["tool_calls_made"]}
def should_continue(state: AgentState) -> str:
last_message = state["messages"][-1]
if last_message.tool_calls:
return "tools"
return END
graph = StateGraph(AgentState)
graph.add_node("agent", call_model)
graph.add_node("tools", tool_executor)
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", should_continue)
graph.add_edge("tools", "agent")
app = graph.compile()
When It Fits
LangGraph earns its overhead for agents with genuine branching complexity:
- Multi-step agents with conditional logic — research agents that decide between search, calculation, or document retrieval based on intermediate results
- Retry and error recovery loops — if a tool call fails, route to an error handler node that decides whether to retry, fall back, or surface the error
- Human-in-the-loop workflows — pause graph execution at a checkpoint, wait for human approval, then resume
- Parallel execution — fan out to multiple nodes simultaneously, then join results
The state machine model makes complex agent logic explicit and debuggable. You can visualize the graph, inspect state at each node, and replay failed runs from any checkpoint.
When It Doesn't
LangGraph adds real complexity. For most tasks, it's the wrong tool:
Simple pipelines — if your agent is prompt → tool call → response, you don't need a graph framework. Write three functions and call them sequentially.
One-shot tasks — classification, extraction, single-turn Q&A. No agent loop, no branching. Use generateText or a direct API call.
Overkill for most agentic-workflows — the built-in tool use loop (model calls tool, result goes back, model continues) already handles the common case without a graph framework. Add LangGraph when that loop isn't expressive enough for your branching requirements.
The right question: can I draw a flowchart of this agent that has more than two branches? If not, LangGraph is probably overhead.
Persistence and Checkpointing
LangGraph supports checkpointing graph state to a database (SQLite, Postgres). This enables:
- Resuming interrupted runs
- Long-running agents that span multiple sessions
- Debugging by replaying from a specific checkpoint
Checkpointing is the main reason to use LangGraph for long-running multi-agent-setup workflows even when the graph structure is simple.
Related
agentic-workflows · multi-agent-setup