langgraph-agent
LangGraph Agent Developer
Overview
LangGraph is a low-level orchestration framework for building stateful, multi-actor applications with LLMs. It enables you to create cyclical graphs that define agent workflows, with built-in support for persistence, streaming, and human-in-the-loop interactions.
Core Concepts
State Management
LangGraph applications revolve around a State object that passes between nodes:
from typing_extensions import TypedDict
from typing import Annotated
from operator import add
class State(TypedDict):
# Single value
query: str
# Accumulates across nodes
messages: Annotated[list, add]
# Optional values
context: str | None
Graph Structure
LangGraph uses StateGraph to define workflows:
from langgraph.graph import START, END, StateGraph
graph = StateGraph(State)
# Add nodes
graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)
# Add edges
graph.add_edge(START, "agent")
graph.add_conditional_edges("agent", should_continue, {
"continue": "tools",
"end": END
})
graph.add_edge("tools", "agent")
# Compile and invoke
app = graph.compile()
result = app.invoke({"query": "hello"})
Key Features
- Durable Execution: Persist state and resume from checkpoints
- Human-in-the-Loop: Interrupt execution for human approval
- Streaming: Stream tokens, steps, or graph updates
- Memory: Built-in short-term and long-term memory
- Multi-agent: Coordinate multiple agents in single workflow
Workflow
1. Design the Agent Architecture
Identify the core components:
Nodes: Define what each step does
- Agent nodes (LLM calls)
- Tool nodes (function execution)
- Router nodes (conditional logic)
- Sub-graph nodes (nested workflows)
Edges: Define flow control
- Simple edges: unconditional transition
- Conditional edges: routing based on state
State: Define shared data
- Input/output schema
- Accumulated data (messages, results)
- Configuration (model params, settings)
2. Implement the Graph
Start with a minimal working example:
from langgraph.graph import START, StateGraph
from langchain_anthropic import ChatAnthropic
from typing_extensions import TypedDict
class State(TypedDict):
messages: list
def agent(state: State):
model = ChatAnthropic(model="claude-sonnet-4-5-20250213")
response = model.invoke(state["messages"])
return {"messages": [response]}
graph = StateGraph(State)
graph.add_node("agent", agent)
graph.add_edge(START, "agent")
app = graph.compile()
3. Add Tools (if needed)
Use LangChain's tool integration:
from langchain_core.tools import tool
from langgraph.prebuilt import ToolNode
@tool
def search(query: str) -> str:
"""Search the web."""
return f"Results for: {query}"
tools = [search]
tool_node = ToolNode(tools)
# Bind tools to model
def agent(state: State):
model = ChatAnthropic(model="claude-sonnet-4-5-20250213")
model_with_tools = model.bind_tools(tools)
response = model_with_tools.invoke(state["messages"])
return {"messages": [response]}
4. Implement Conditional Routing
Add decision logic with conditional edges:
def should_continue(state: State) -> str:
messages = state["messages"]
last_message = messages[-1]
if last_message.tool_calls:
return "tools"
return END
graph.add_conditional_edges(
"agent",
should_continue,
{"tools": "tools", END: END}
)
5. Add Memory and Persistence
Enable checkpointing for stateful conversations:
from langgraph.checkpoint.memory import MemorySaver
memory = MemorySaver()
app = graph.compile(checkpointer=memory)
# Use thread_id for conversation continuity
config = {"configurable": {"thread_id": "conversation-1"}}
result = app.invoke({"messages": [("user", "hello")]}, config)
6. Implement Human-in-the-Loop
Add interruption points for human approval:
from langgraph.checkpoint.memory import MemorySaver
memory = MemorySaver()
app = graph.compile(
checkpointer=memory,
interrupt_before=["tools"] # Pause before executing tools
)
# Resume after human approval
app.invoke(None, config)
Common Patterns
ReAct Agent
Reason + Act pattern for tool-using agents:
from langgraph.prebuilt import create_react_agent
tools = [search, calculator]
agent = create_react_agent(
model="claude-sonnet-4-5-20250213",
tools=tools,
checkpointer=MemorySaver()
)
Multi-Agent System
Coordinate specialized agents:
from langgraph.graph import StateGraph
# Define sub-agents
researcher = create_research_agent()
coder = create_coder_agent()
# Coordinator
def coordinator(state: State):
# Route to appropriate agent
if "code" in state["query"]:
return "coder"
return "researcher"
# Build multi-agent graph
graph = StateGraph(State)
graph.add_node("coordinator", coordinator)
graph.add_node("researcher", researcher)
graph.add_node("coder", coder)
graph.add_conditional_edges("coordinator", coordinator)
Sequential Chain
Linear workflow with clear steps:
def step1(state):
# Process input
return {"data": transform(state["input"])}
def step2(state):
# Process output from step1
return {"result": analyze(state["data"])}
graph = StateGraph(State)
graph.add_node("step1", step1)
graph.add_node("step2", step2)
graph.add_edge(START, "step1")
graph.add_edge("step1", "step2")
graph.add_edge("step2", END)
Router Pattern
Route inputs to different branches:
def route_intent(state: State) -> str:
query = state["query"].lower()
if "weather" in query:
return "weather_agent"
elif "code" in query:
return "code_agent"
else:
return "general_agent"
graph.add_conditional_edges(
START,
route_intent,
{
"weather_agent": "weather",
"code_agent": "code",
"general_agent": "general"
}
)
Debugging
Visualize the Graph
from IPython.display import Image, display
try:
display(Image(app.get_graph().draw_mermaid_png()))
except Exception:
print(app.get_graph().print_ascii())
Inspect State
# Get current state
state = app.get_state(config)
print(state.next) # Next nodes to execute
print(state.values) # Current state values
# Get state history
for state in app.get_state_history(config):
print(state.values, state.next)
Stream Execution
# Stream tokens
for chunk in app.stream({"messages": [("user", query)]}, config):
print(chunk)
# Stream updates
for event in app.stream({"messages": [("user", query)]}, config, stream_mode="updates"):
print(event)
# Stream debug info
async for event in app.astream_events(
{"messages": [("user", query)]},
config,
version="v1"
):
print(f"Node: {event['name']}, Type: {event['event']}")
Deployment
LangGraph Platform (Recommended)
Deploy to LangGraph Cloud for production:
# Install CLI
pip install langgraph-cli
# Initialize project
langgraph init
# Deploy
langgraph deploy
Self-Hosted
Use FastAPI for custom deployment:
from fastapi import FastAPI
from langgraph.graph import StateGraph
app_api = FastAPI()
graph_app = graph.compile()
@app_api.post("/invoke")
async def invoke(request: dict):
result = graph_app.invoke(request["state"], request["config"])
return {"result": result}
Best Practices
- Start Simple: Begin with a basic graph, then add complexity
- Type State: Use TypedDict for clear state schemas
- Error Handling: Wrap LLM calls in try-except blocks
- Idempotent Nodes: Nodes should handle re-execution safely
- Separate Concerns: Keep business logic separate from graph definition
- Test Locally: Use
invokefor testing beforestream/astream - Monitor: Use LangSmith for tracing and debugging
Implementation Rules
- Read
references/official-docs-index.mdfor focused documentation links - Use Python type hints for all State definitions
- Prefer
create_react_agentfor simple tool-using agents - Use conditional edges for all branching logic
- Always include proper error handling in production code
- Test with streaming to understand execution flow
- Use checkpointing for any long-running or stateful workflow
- Keep nodes small and focused on single responsibilities
- Document complex routing logic in comments
Task Playbooks
Create Simple Sequential Agent
- Define State with input/output fields
- Create 2-3 processing nodes
- Chain nodes with simple edges
- Compile and test with invoke
- Add streaming if needed
Build Tool-Using Agent
- Define tools with type hints and docstrings
- Create agent node with model.bind_tools()
- Add ToolNode for tool execution
- Implement should_continue conditional logic
- Add checkpointing for conversation memory
Implement Multi-Agent System
- Define each agent's purpose and state interface
- Create individual agent graphs or functions
- Design coordinator/routing logic
- Combine agents in parent graph
- Test routing and communication flows
References
Use references/official-docs-index.md for direct links to official documentation.