mcpField
L
langgraph

langgraph

github.com/davila7Agent 工作流33.0k445 次安装今天更新
代码仓库

关于 langgraph

面向图式工作流开发者的 LangGraph Agent 设计技能,帮助构建结构化 AI Agent。内容涵盖状态、路由、持久化、人工参与、工具、流式处理及异步执行。

主要功能

  1. 01构建 StateGraph
  2. 02设计状态与 reducer
  3. 03条件路由
  4. 04检查点与持久化
  5. 05人工参与模式
  6. 06工具集成与流式处理

适用场景

  1. 01构建 ReAct 风格的 Agent 图
  2. 02在多种工作流间路由
  3. 03持久化状态以恢复对话
  4. 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

评论

支持 Markdown