home / skills / htooayelwinict / claude-config / langgraph
This skill helps you design and manage stateful, multi-agent workflows with LangGraph, enabling dynamic routing, memory, and subgraph architectures.
npx playbooks add skill htooayelwinict/claude-config --skill langgraphReview the files below or copy the command above to add this skill to your agents.
---
name: langgraph
description: Expert guidance for building stateful, multi-actor AI agents with LangGraph - graphs, nodes, edges, state management, and agent architectures.
allowed-tools: Read, Edit, Bash, Grep, mcp_context7
---
# LangGraph Skill
Use this skill when building stateful, cyclic AI agent workflows with LangGraph.
## 📚 Documentation Lookup (Context7)
Always verify patterns with latest docs:
```
mcp_context7_resolve-library-id(libraryName="langgraph", query="StateGraph conditional edges")
mcp_context7_query-docs(libraryId="/langchain-ai/langgraph", query="checkpointer persistence")
```
## Core Concepts
### 1. State Definition
```python
from typing import Annotated, TypedDict
from langgraph.graph.message import add_messages
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
context: str
iteration: int
# With Pydantic
from pydantic import BaseModel
class State(BaseModel):
messages: list = []
current_step: str = "start"
```
### 2. Basic Graph Structure
```python
from langgraph.graph import StateGraph, START, END
# Define the graph
workflow = StateGraph(AgentState)
# Add nodes (functions that transform state)
def agent_node(state: AgentState) -> dict:
response = llm.invoke(state["messages"])
return {"messages": [response]}
def tool_node(state: AgentState) -> dict:
# Execute tools based on last message
return {"messages": [tool_result]}
workflow.add_node("agent", agent_node)
workflow.add_node("tools", tool_node)
# Add edges
workflow.add_edge(START, "agent")
workflow.add_edge("tools", "agent")
# Conditional edge
def should_continue(state: AgentState) -> str:
last_message = state["messages"][-1]
if last_message.tool_calls:
return "tools"
return END
workflow.add_conditional_edges("agent", should_continue)
# Compile
app = workflow.compile()
```
### 3. Prebuilt Components
```python
from langgraph.prebuilt import create_react_agent, ToolNode
# Quick ReAct agent
tools = [search_tool, calculator_tool]
agent = create_react_agent(llm, tools)
# Tool execution node
tool_node = ToolNode(tools)
```
### 4. Checkpointing (Memory/Persistence)
```python
from langgraph.checkpoint.memory import MemorySaver
from langgraph.checkpoint.sqlite import SqliteSaver
# In-memory (for development)
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)
# SQLite (for persistence)
with SqliteSaver.from_conn_string(":memory:") as saver:
app = workflow.compile(checkpointer=saver)
# Invoke with thread_id for conversation continuity
config = {"configurable": {"thread_id": "user-123"}}
result = app.invoke({"messages": [HumanMessage("Hi")]}, config)
# Continue conversation
result = app.invoke({"messages": [HumanMessage("Follow up")]}, config)
```
### 5. Human-in-the-Loop
```python
from langgraph.graph import StateGraph
# Add interrupt before sensitive operations
app = workflow.compile(
checkpointer=memory,
interrupt_before=["sensitive_action"] # Pause here
)
# Resume after human approval
result = app.invoke(None, config) # Continues from checkpoint
```
### 6. Subgraphs
```python
# Define inner graph
inner_workflow = StateGraph(InnerState)
inner_workflow.add_node("process", process_node)
inner_workflow.add_edge(START, "process")
inner_workflow.add_edge("process", END)
inner_graph = inner_workflow.compile()
# Use as node in outer graph
outer_workflow = StateGraph(OuterState)
outer_workflow.add_node("subgraph", inner_graph)
```
### 7. Streaming
```python
# Stream node outputs
for event in app.stream({"messages": [HumanMessage("Hello")]}):
for node_name, output in event.items():
print(f"{node_name}: {output}")
# Stream tokens from LLM
async for event in app.astream_events(input, version="v2"):
if event["event"] == "on_chat_model_stream":
print(event["data"]["chunk"].content, end="")
```
## Agent Architectures
### ReAct Agent
```python
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model=llm,
tools=tools,
state_modifier="You are a helpful assistant." # System prompt
)
```
### Plan-and-Execute
```python
class PlanExecuteState(TypedDict):
input: str
plan: list[str]
past_steps: list[tuple[str, str]]
response: str
def planner(state):
# Generate plan
plan = plan_chain.invoke({"input": state["input"]})
return {"plan": plan.steps}
def executor(state):
# Execute current step
task = state["plan"][0]
result = execute_chain.invoke({"task": task})
return {
"past_steps": [(task, result)],
"plan": state["plan"][1:]
}
def should_end(state):
return END if not state["plan"] else "executor"
workflow = StateGraph(PlanExecuteState)
workflow.add_node("planner", planner)
workflow.add_node("executor", executor)
workflow.add_edge(START, "planner")
workflow.add_conditional_edges("planner", should_end)
workflow.add_conditional_edges("executor", should_end)
```
### Multi-Agent Supervisor
```python
from langgraph.prebuilt import create_react_agent
# Create specialized agents
researcher = create_react_agent(llm, [search_tool])
coder = create_react_agent(llm, [code_tool])
class SupervisorState(TypedDict):
messages: Annotated[list, add_messages]
next: str
def supervisor(state):
# Decide which agent to call
decision = router_chain.invoke(state["messages"])
return {"next": decision.next_agent}
def call_researcher(state):
result = researcher.invoke({"messages": state["messages"]})
return {"messages": result["messages"]}
def call_coder(state):
result = coder.invoke({"messages": state["messages"]})
return {"messages": result["messages"]}
workflow = StateGraph(SupervisorState)
workflow.add_node("supervisor", supervisor)
workflow.add_node("researcher", call_researcher)
workflow.add_node("coder", call_coder)
workflow.add_edge(START, "supervisor")
workflow.add_conditional_edges("supervisor", lambda s: s["next"])
workflow.add_edge("researcher", "supervisor")
workflow.add_edge("coder", "supervisor")
```
## Best Practices
1. **State Design** - Keep state minimal; use `add_messages` reducer for message accumulation
2. **Node Functions** - Return partial state updates, not full state
3. **Conditional Edges** - Use for dynamic routing based on state
4. **Checkpointing** - Always use for production to enable persistence
5. **Streaming** - Use `astream_events` for real-time UX
6. **Error Handling** - Add retry logic in nodes or use fallback edges
7. **Testing** - Test nodes individually before composing
## Common Patterns
### State Reducer
```python
from operator import add
from typing import Annotated
class State(TypedDict):
items: Annotated[list, add] # Appends to list
messages: Annotated[list, add_messages] # Smart message merging
```
### Parallel Branches
```python
workflow.add_node("branch_a", node_a)
workflow.add_node("branch_b", node_b)
workflow.add_edge(START, "branch_a")
workflow.add_edge(START, "branch_b") # Both run in parallel
workflow.add_edge("branch_a", "join")
workflow.add_edge("branch_b", "join")
```
### Dynamic Tool Selection
```python
def route_to_tool(state):
tool_call = state["messages"][-1].tool_calls[0]
return tool_call["name"]
workflow.add_conditional_edges("agent", route_to_tool, {
"search": "search_node",
"calculate": "calc_node"
})
```
## Installation
```bash
pip install langgraph
pip install langgraph-checkpoint-sqlite # For SQLite persistence
```
This skill provides expert guidance for designing stateful, multi-actor AI agent workflows using LangGraph. It focuses on graphs, nodes, edges, state management, checkpointing, streaming, and common agent architectures like ReAct, Plan-and-Execute, and multi-agent supervisors. The guidance emphasizes practical patterns, persistence, and human-in-the-loop control for reliable, production-ready agents.
The skill explains how to define a typed state, add nodes that return partial state updates, and connect nodes with edges or conditional edges to create cyclic, stateful workflows. It covers compiling graphs into runnable apps with optional checkpointers for persistence, streaming node outputs and model tokens, and composing subgraphs or prebuilt agent components such as ReAct or ToolNode. It also shows patterns for parallel branches, dynamic tool routing, and interrupt points for human approval.
How do I persist conversation state between runs?
Compile your StateGraph with a checkpointer (MemorySaver for dev, SqliteSaver for persistence) and invoke with a thread_id in config to continue the same conversation.
Can I stream both node outputs and LLM tokens?
Yes. Use app.stream for node-level events and astream_events for model token streaming to support real-time UX.