Skip to content

图 API

LangGraph 的核心是将 Agent 工作流建模为图(Graph)。你可以使用三个关键组件来定义 Agent 的行为:

  1. State(状态):一个共享的数据结构,代表应用的当前快照。可以是一个 TypedDict 或 Pydantic 模型。
  2. Nodes(节点):编码 Agent 逻辑的函数。它们接收当前状态作为输入,执行计算或副作用,并返回更新后的状态。
  3. Edges(边):根据当前状态确定下一步执行哪个节点的函数。可以是条件分支或固定转换。

通过组合 NodesEdges,你可以创建复杂的、循环的工作流,随时间演进状态。Nodes 和 Edges 本质上就是函数——它们可以包含 LLM,也可以是纯代码。

简而言之:节点负责执行工作,边负责告诉下一步做什么

StateGraph

StateGraph 是主要的图类,由用户定义的 State 对象参数化。

定义状态

状态的模式可以是 TypedDictdataclass 或 Pydantic BaseModel。每个键可以指定一个 reducer 函数,定义如何应用对该键的更新。如果未指定 reducer,则默认是覆盖(override)。

python
from typing import Annotated
from typing_extensions import TypedDict
from operator import add
from langgraph.graph.message import add_messages
from langchain.messages import AnyMessage


class AgentState(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]
    next_agent: str
    input_files: Annotated[list[str], add]

添加节点

节点是普通的 Python 函数,接收当前状态并返回状态更新:

python
from langgraph.graph import StateGraph


def collect_input(state: AgentState) -> AgentState:
    """收集用户输入。"""
    return {"input_files": state.get("input_files", [])}


def process_with_llm(state: AgentState) -> AgentState:
    """将消息发送给 LLM 处理。"""
    # LLM 调用逻辑
    return state

添加边

边定义了图中节点之间的连接。有两种类型:

普通边:固定路径,从源节点到目标节点。

python
builder = StateGraph(AgentState)

builder.add_node("collect", collect_input)
builder.add_node("process", process_with_llm)

builder.add_edge("collect", "process")

条件边:根据当前状态动态选择目标节点。

python
from langgraph.graph import START, END


def router(state: AgentState) -> str:
    """根据状态决定下一步去哪个节点。"""
    if state.get("next_agent") == "researcher":
        return "research_node"
    elif state.get("next_agent") == "writer":
        return "write_node"
    return END


builder.add_conditional_edges(
    "process",
    router,
    {
        "research_node": "research",
        "write_node": "write",
        END: END,
    },
)

编译图

编译图会验证结构(没有孤立节点等),并允许指定运行时参数,如 checkpointers 和断点:

python
from langgraph.checkpoint.memory import InMemorySaver

checkpointer = InMemorySaver()
graph = builder.compile(checkpointer=checkpointer)

必须先编译图,然后才能使用它。

完整示例

以下是一个完整的图 API 示例,实现了一个简单的 Agent 循环:

python
from typing import Annotated, Literal
from typing_extensions import TypedDict
from operator import add
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import InMemorySaver
from langchain.messages import AnyMessage
from langchain.agents import create_agent


class AgentState(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]
    next_steps: Annotated[list[str], add]


def call_model(state: AgentState) -> dict:
    """调用 LLM 生成响应。"""
    # 这里是模型调用逻辑的简化占位符
    messages = state["messages"]
    return {
        "messages": [{"role": "assistant", "content": f"Processed: {messages[-1].content}"}],
    }


def check_needs_tool(state: AgentState) -> Literal["tools", END]:
    """检查是否需要调用工具。"""
    last_message = state["messages"][-1]
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "tools"
    return END


def run_tools(state: AgentState) -> dict:
    """执行工具调用。"""
    return {"next_steps": ["tool_executed"]}


builder = StateGraph(AgentState)

# 添加节点
builder.add_node("call_model", call_model)
builder.add_node("tools", run_tools)

# 添加边
builder.add_edge(START, "call_model")
builder.add_conditional_edges(
    "call_model",
    check_needs_tool,
    {"tools": "tools", END: END},
)
builder.add_edge("tools", "call_model")

# 编译
checkpointer = InMemorySaver()
graph = builder.compile(checkpointer=checkpointer)

# 使用
result = graph.invoke(
    {"messages": [{"role": "user", "content": "Hello!"}]},
    config={"configurable": {"thread_id": "1"}},
)

Reducer 详解

Reducer 是理解节点更新如何应用到状态的关键。状态中的每个键都有自己的 reducer 函数。

默认 reducer(覆盖)

python
class State(TypedDict):
    foo: int
    bar: list[str]

# 初始: {"foo": 1, "bar": ["hi"]}
# 节点返回: {"foo": 2}
# 结果: {"foo": 2, "bar": ["hi"]}
# 节点返回: {"bar": ["bye"]}
# 结果: {"foo": 2, "bar": ["bye"]}

使用 operator.add reducer

python
from typing import Annotated
from operator import add

class State(TypedDict):
    foo: int
    bar: Annotated[list[str], add]

# 初始: {"foo": 1, "bar": ["hi"]}
# 节点返回: {"foo": 2}
# 结果: {"foo": 2, "bar": ["hi"]}
# 节点返回: {"bar": ["bye"]}
# 结果: {"foo": 2, "bar": ["hi", "bye"]}

使用 create_agent 构建图

顶层 create_agent 工厂函数内部也是基于图 API 构建的:

python
from langchain.agents import create_agent
from langchain.tools import tool
from langgraph.checkpoint.memory import InMemorySaver


@tool
def search(query: str) -> str:
    """搜索信息。"""
    return f"Results for: {query}"


agent = create_agent(
    model="claude-sonnet-4-6",
    tools=[search],
    system_prompt="You are a helpful assistant.",
    checkpointer=InMemorySaver(),
)

# agent 本身就是一个已编译的图
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Search for AI news"}]},
    config={"configurable": {"thread_id": str(uuid7())}},
)

下一步

本站为非官方中文学习站点,不代表 LangChain 官方。部分内容参考官方文档并重新整理为中文学习笔记。