关于 langgraph
面向图式工作流开发者的 LangGraph Agent 设计技能,帮助构建结构化 AI Agent。内容涵盖状态、路由、持久化、人工参与、工具、流式处理及异步执行。
主要功能
- 01构建 StateGraph
- 02设计状态与 reducer
- 03条件路由
- 04检查点与持久化
- 05人工参与模式
- 06工具集成与流式处理
适用场景
- 01构建 ReAct 风格的 Agent 图
- 02在多种工作流间路由
- 03持久化状态以恢复对话
- 04在 Agent 流程中加入人工审核
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ davila7/ claude-code-templates --skill langgraph安装后在 Claude Code 中输入/langgraph确认已加载。
详细介绍
LangGraph
角色:LangGraph Agent 架构师
你是使用 LangGraph 构建生产级 AI Agent 的专家。你深知 Agent 需要明确的结构 —— 图能让流程可见且可调试。你会精心设计状态,恰当使用 reducer,并始终为生产环境考虑持久化。你清楚何时需要循环,以及如何防止无限循环。
能力
- 图构建(StateGraph)
- 状态管理与 reducer
- 节点与边的定义
- 条件路由
- 检查点与持久化
- 人在回路模式
- 工具集成
- 流式与异步执行
要求
- Python 3.9+
- langgraph 包
- 大模型 API 访问权限(OpenAI、Anthropic 等)
- 理解图的概念
模式
基础 Agent 图
带工具的简单 ReAct 风格 Agent
使用场景:带工具调用的单 Agent
from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
# 1. Define State
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
# add_messages reducer appends, doesn't overwrite
# 2. Define Tools
@tool
def search(query: str) -> str:
"""Search the web for information."""
# Implementation here
return f"Results for: {query}"
@tool
def calculator(expression: str) -> str:
"""Evaluate a math expression."""
return str(eval(expression))
tools = [search, calculator]
# 3. Create LLM with tools
llm = ChatOpenAI(model="gpt-4o").bind_tools(tools)
# 4. Define Nodes
def agent(state: AgentState) -> dict:
"""The agent node - calls LLM."""
response = llm.invoke(state["messages"])
return {"messages": [response]}
# Tool node handles tool execution
tool_node = ToolNode(tools)
# 5. Define Routing
def should_continue(state: AgentState) -> str:
"""Route based on whether tools were called."""
last_message = state["messages"][-1]
if last_message.tool_calls:
return "tools"
return END
# 6. Build Graph
graph = StateGraph(AgentState)
# Add nodes
graph.add_node("agent", agent)
graph.add_node("tools", tool_node)
# Add edges
graph.add_edge(START, "agent")
graph.add_conditional_edges("agent", should_continue, ["tools", END])
graph.add_edge("tools", "agent") # Loop back
# Compile
app = graph.compile()
# 7. Run
result = app.invoke({
"messages": [("user", "What is 25 * 4?")]
})
带 Reducer 的状态
使用自定义 reducer 的复杂状态管理
使用场景:多个 Agent 更新共享状态
from typing import Annotated, TypedDict
from operator import add
from langgraph.graph import StateGraph
# Custom reducer for merging dictionaries
def merge_dicts(left: dict, right: dict) -> dict:
return {**left, **right}
# State with multiple reducers
class ResearchState(TypedDict):
# Messages append (don't overwrite)
messages: Annotated[list, add_messages]
# Research findings merge
findings: Annotated[dict, merge_dicts]
# Sources accumulate
sources: Annotated[list[str], add]
# Current step (overwrites - no reducer)
current_step: str
# Error count (custom reducer)
errors: Annotated[int, lambda a, b: a + b]
# Nodes return partial state updates
def researcher(state: ResearchState) -> dict:
# Only return fields being updated
return {
"findings": {"topic_a": "New finding"},
"sources": ["source1.com"],
"current_step": "researching"
}
def writer(state: ResearchState) -> dict:
# Access accumulated state
all_findings = state["findings"]
all_sources = state["sources"]
return {
"messages": [("assistant", f"Report based on {len(all_sources)} sources")],
"current_step": "writing"
}
# Build graph
graph = StateGraph(ResearchState)
graph.add_node("researcher", researcher)
graph.add_node("writer", writer)
# ... add edges
条件分支
根据状态路由到不同路径
使用场景:多种可能的工作流
from langgraph.graph import StateGraph, START, END
class RouterState(TypedDict):
query: str
query_type: str
result: str
def classifier(state: RouterState) -> dict:
"""Classify the query type."""
query = state["query"].lower()
if "code" in query or "program" in query:
return {"query_type": "coding"}
elif "search" in query or "find" in query:
return {"query_type": "search"}
else:
return {"query_type": "chat"}
def coding_agent(state: RouterState) -> dict:
return {"result": "Here's your code..."}
def search_agent(state: RouterState) -> dict:
return {"result": "Search results..."}
def chat_agent(state: RouterState) -> dict:
return {"result": "Let me help..."}
# Routing function
def route_query(state: RouterState) -> str:
"""Route to appropriate agent."""
query_type = state["query_type"]
return query_type # Returns node name
# Build graph
graph = StateGraph(RouterState)
graph.add_node("classifier", classifier)
graph.add_node("coding", coding_agent)
graph.add_node("search", search_agent)
graph.add_node("chat", chat_agent)
graph.add_edge(START, "classifier")
# Conditional edges from classifier
graph.add_conditional_edges(
"classifier",
route_query,
{
"coding": "coding",
"search": "search",
"chat": "chat"
}
)
# All agents lead to END
graph.add_edge("coding", END)
graph.add_edge("search", END)
graph.add_edge("chat", END)
app = graph.compile()
反模式
❌ 无退出条件的无限循环
为何不好:Agent 永远循环。 消耗 token 和成本。 最终报错。
替代方案:始终设置退出条件:
- 状态中的最大迭代计数器
- 路由中明确的 END 条件
- 应用层面的超时
def should_continue(state): if state["iterations"] > 10: return END if state["task_complete"]: return END return "agent"
❌ 无状态节点
为何不好:丧失 LangGraph 的优势。 状态无法持久化。 无法恢复对话。
替代方案:始终使用状态进行数据流转。 从节点返回状态更新。 使用 reducer 进行累积。 让 LangGraph 管理状态。
❌ 庞大的单体状态
为何不好:难以推理。 上下文中包含不必要的数据。 序列化开销。
替代方案:使用输入/输出 schema 实现清晰的接口。 用私有状态存放内部数据。 清晰分离关注点。
限制
- 仅支持 Python(TypeScript 处于早期阶段)
- 图概念有学习曲线
- 状态管理复杂
- 调试可能具有挑战性
相关技能
可与以下技能良好配合:crewai、autonomous-agents、langfuse、structured-output