版本参考:LangGraph v0.3.x(2026年4月)
适用读者:有 Python 经验、理解 DAG/状态机概念、希望构建生产级 AI Agent 的资深工程师 当前github地址:github.com/langchain-a…
目录
- 框架概述与设计哲学
- 仓库结构与包架构
- 核心执行引擎:Pregel 模型
- Graph API:StateGraph 深度解析
- Functional API:@entrypoint 与 @task
- 状态管理与 Reducers
- 持久化与 Checkpointing 系统
- Human-in-the-Loop 工作流
- 流式输出(Streaming)
- 高级控制流:Send / Command / 条件边
- 多 Agent 系统深度指南
- 11.1 架构模式全景(决策树)
- 11.2 Supervisor 集中调度模式
- 11.3 Hierarchical 层级树模式
- 11.4 Swarm 蜂群去中心化模式
- 11.5 Reflection 反思质检模式
- 11.6 Debate 对抗辩论模式
- 11.7 子图状态映射机制(共享键 vs 包装器)
- 11.8 跨 Agent 共享内存:BaseStore
- 11.9 生产并发控制、Double-Texting、可观测性
- 预构建组件:ReAct Agent & 工具调用
- 部署:langgraph-cli 与 LangGraph Platform
- 生产最佳实践
- 调试与可观测性
- API 快速参考
1. 框架概述与设计哲学
1.1 LangGraph 是什么
LangGraph 是 LangChain Inc. 推出的低级 Agent 编排框架,核心使命是:
将 AI Agent 的执行流程建模为有状态的有向图(Stateful Directed Graph),并提供持久化、容错、人工干预等生产级基础设施。
它不是 RAG 框架,不是 LLM 封装层,而是专注于Agent 的编排与生命周期管理。
1.2 设计哲学
| 设计原则 | 说明 |
|---|---|
| 低级可控 | 不隐藏执行细节,开发者完全掌控节点、边、状态 |
| 图即状态机 | 每个 superstep 都是一次状态快照,支持时间旅行 |
| 持久性优先 | Checkpointing 是一等公民,而非事后加的功能 |
| 框架无关 | 不强依赖 LangChain,可独立使用任何 LLM SDK |
| 可组合性 | 图可以嵌套为子图,两套 API 可以混用 |
1.3 适合 LangGraph 的场景
- 多步骤 Agent 工作流(ReAct、Plan-and-Execute、反思循环)
- 需要人工审批/干预的半自动化流程
- 需要跨会话记忆的长期运行 Agent
- 多 Agent 协作系统(supervisor + workers)
- 需要故障恢复、状态回放的关键业务流程
2. 仓库结构与包架构
2.1 Monorepo 组织
LangGraph 采用 Monorepo 结构,所有包位于 libs/ 目录下,各包独立版本发布到 PyPI:
langchain-ai/langgraph/
├── libs/
│ ├── langgraph/ # 核心包:执行引擎 + Graph API
│ ├── langgraph-checkpoint/ # 基础 Checkpointer 接口 + 序列化
│ ├── langgraph-prebuilt/ # ReAct Agent、ToolNode 等预构建组件
│ ├── langgraph-sdk/ # Python & JS 客户端 SDK
│ ├── langgraph-cli/ # CLI 工具:dev server、部署
│ ├── checkpoint-sqlite/ # SQLite Checkpointer 实现
│ └── checkpoint-postgres/ # PostgreSQL Checkpointer 实现
├── docs/
└── examples/
2.2 包职责与依赖关系
langgraph-cli
└── depends on → langgraph-sdk
langgraph
├── depends on → langgraph-checkpoint (基础接口)
└── depends on → langgraph-prebuilt>=1.0.2,<1.1.0
langgraph-checkpoint
└── 提供 BaseCheckpointSaver、JsonPlusSerializer
2.3 命名空间包设计(重要!)
langgraph 和 langgraph-checkpoint 使用同一顶级命名空间,通过 Python 命名空间包机制合并:
langgraph/
├── graph/ ← 来自 langgraph 包
├── pregel/ ← 来自 langgraph 包(执行引擎)
├── prebuilt/ ← 来自 langgraph-prebuilt 包
├── checkpoint/ ← 来自 langgraph-checkpoint 包
│ ├── base.py (BaseCheckpointSaver 抽象类)
│ ├── memory.py (MemorySaver)
│ └── serde/ (JsonPlusSerializer)
└── store/ ← 来自 langgraph-checkpoint 包(跨线程存储)
注意:安装时务必同时安装所需的 checkpointer 包,否则只有内存版
MemorySaver。
3. 核心执行引擎:Pregel 模型
3.1 BSP 执行模型
LangGraph 的底层执行引擎基于 Google Pregel 论文的 Bulk Synchronous Parallel(BSP)模型,其执行循环为:
┌─────────────────────────────────────────┐
│ Pregel Execution Loop │
│ │
│ 1. PLAN → 确定本 superstep 要运行的节点 │
│ 2. EXECUTE → 并行执行所有节点 │
│ 3. UPDATE → 通过 reducer 合并写入到 channel│
│ 4. CHECKPOINT → 持久化当前状态快照 │
│ 5. 检查终止条件 → 若未结束,回到步骤 1 │
└─────────────────────────────────────────┘
3.2 Superstep 概念
Superstep 是 Pregel 的基本执行单位:
- 一个 superstep 内所有被调度的节点并行执行
- 每个 superstep 结束时保存一个 checkpoint
- 对于线性图
START → A → B → END,有 3 个 superstep(input, A, B),产生 3 个 checkpoint
# 理解 superstep 对时间旅行调试至关重要
# 只能从 checkpoint 边界恢复执行,不能从节点内部恢复
3.3 Channel 系统
状态的每个字段对应一个 Channel,Channel 决定如何处理并发写入:
| Channel 类型 | 行为 | 典型用途 |
|---|---|---|
LastValue | 后写覆盖前写 | 单值状态字段 |
Topic (Append) | 累加到列表 | 消息历史、日志 |
EphemeralValue | 每个 superstep 后清空 | 临时传递数据 |
4. Graph API:StateGraph 深度解析
4.1 基础构建流程
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.graph.message import add_messages
from langchain_core.messages import BaseMessage
# Step 1: 定义 State Schema
class AgentState(TypedDict):
messages: Annotated[list[BaseMessage], add_messages] # reducer
next_step: str # last-value
iteration: int
# Step 2: 定义节点(纯函数:State -> Partial State)
def llm_node(state: AgentState) -> dict:
# 只返回需要更新的字段
response = llm.invoke(state["messages"])
return {"messages": [response]}
def router(state: AgentState) -> str:
# 条件边的路由函数,返回节点名称字符串
last_msg = state["messages"][-1]
if last_msg.tool_calls:
return "tools"
return END
# Step 3: 构建图
builder = StateGraph(AgentState)
builder.add_node("llm", llm_node)
builder.add_node("tools", tool_node)
# Step 4: 定义边
builder.add_edge(START, "llm")
builder.add_conditional_edges("llm", router, ["tools", END])
builder.add_edge("tools", "llm") # 工具执行后回到 LLM
# Step 5: 编译(可选传入 checkpointer)
from langgraph.checkpoint.memory import MemorySaver
graph = builder.compile(checkpointer=MemorySaver())
4.2 节点设计规范
节点是纯函数,遵循以下契约:
# 输入:完整的 State 快照(只读)
# 输出:Partial State(只包含需要修改的字段)
def node_function(state: MyState) -> dict:
...
return {"field_to_update": new_value}
# 异步节点(推荐用于 I/O 密集型操作)
async def async_node(state: MyState) -> dict:
result = await some_async_operation()
return {"result": result}
关键约束:节点不应有副作用(除了调用外部服务),不应直接修改 state 对象。
4.3 条件边(Conditional Edges)的三种模式
# 模式 1:简单路由函数(返回节点名字符串)
def simple_router(state: State) -> str:
return "node_a" if condition else "node_b"
graph.add_conditional_edges("source", simple_router)
# 模式 2:带映射的路由(枚举值 -> 节点名)
def enum_router(state: State) -> Literal["continue", "end"]:
return "continue" if state["should_continue"] else "end"
graph.add_conditional_edges(
"source",
enum_router,
{"continue": "node_a", "end": END}
)
# 模式 3:从 START 设置条件入口
graph.add_conditional_edges(START, initial_router)
4.4 图编译选项
graph = builder.compile(
checkpointer=checkpointer, # 持久化后端
interrupt_before=["tool_node"], # 在该节点前自动中断
interrupt_after=["llm_node"], # 在该节点后自动中断
debug=True, # 开启详细日志
)
5. Functional API:@entrypoint 与 @task
5.1 设计动机
Functional API 允许用标准 Python 控制流(if/for/while)编写工作流,无需将逻辑拆分为显式节点和边,适合将现有代码快速接入 LangGraph 的持久化与 HIL 能力。
from langgraph.func import entrypoint, task
from langgraph.checkpoint.memory import MemorySaver
# @task:可异步执行的离散工作单元
@task
def fetch_data(query: str) -> dict:
return expensive_api_call(query)
@task
def process_data(data: dict) -> str:
return llm.invoke(str(data)).content
# @entrypoint:工作流入口,等价于一个可持久化的函数
@entrypoint(checkpointer=MemorySaver())
def my_workflow(inputs: dict, *, previous=None) -> str:
# previous:同一 thread_id 上次执行的返回值
# 并行派发两个 task(返回 future)
fut1 = fetch_data("query_1")
fut2 = fetch_data("query_2")
# 等待结果
data1 = fut1.result()
data2 = fut2.result()
# 使用标准 Python 控制流
if data1["score"] > data2["score"]:
return process_data(data1).result()
else:
return process_data(data2).result()
5.2 Functional API vs StateGraph 选型矩阵
| 维度 | Functional API | StateGraph |
|---|---|---|
| 控制流表达 | 标准 Python(if/for/while) | 显式节点 + 条件边 |
| 状态可见性 | 隐式(局部变量) | 显式 State 类 |
| 代码量 | 较少 | 较多(结构化) |
| 可视化调试 | 不支持图形化 | LangGraph Studio 全支持 |
| 时间旅行调试 | ⚠️ 有限支持 | ✅ 完全支持 |
| 并行执行 | @task futures | 同一 superstep 多节点 |
| 与现有代码集成 | ✅ 极易 | 需要重构 |
| 推荐场景 | 快速原型、过程式逻辑 | 复杂分支、生产级 Agent |
5.3 entrypoint.final:控制 checkpoint 保存内容
from langgraph.func import entrypoint
from langgraph.types import Command
@entrypoint(checkpointer=checkpointer)
def workflow(inputs: dict) -> entrypoint.final:
result = do_work(inputs)
# 返回给调用者的值 vs 存入 checkpoint 的值可以不同
return entrypoint.final(
value=result["output"], # 调用者拿到的
save=result["checkpoint_data"] # 下次 previous 看到的
)
6. 状态管理与 Reducers
6.1 State Schema 定义方式
LangGraph 支持三种 Schema 定义方式:
# 方式 1:TypedDict(推荐,轻量)
from typing import Annotated
from typing_extensions import TypedDict
class State(TypedDict):
messages: Annotated[list, add_messages]
counter: int # 无 annotation = LastValue reducer
# 方式 2:Pydantic BaseModel(运行时验证)
from pydantic import BaseModel, Field
class State(BaseModel):
messages: list = Field(default_factory=list)
user_id: str
# 方式 3:dataclass
from dataclasses import dataclass, field
@dataclass
class State:
messages: list = field(default_factory=list)
step: int = 0
6.2 Reducer 详解
Reducer 定义了当多个节点在同一 superstep 写入同一字段时如何合并:
from langgraph.graph.message import add_messages
import operator
# 内置 reducer:追加消息(自动去重、处理 tool messages)
messages: Annotated[list[BaseMessage], add_messages]
# 内置 reducer:使用 operator.add(列表追加)
items: Annotated[list[str], operator.add]
# 自定义 reducer
def merge_dicts(left: dict, right: dict) -> dict:
return {**left, **right}
metadata: Annotated[dict, merge_dicts]
# 使用 reducer 类(支持类型注解)
from langgraph.graph import add_messages
6.3 MessagesState 内置 State
from langgraph.graph import MessagesState
# 等价于:
class MessagesState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
# add_messages reducer 特性:
# - 自动追加新消息
# - 通过 message.id 去重(相同 id 的消息会被覆盖,用于更新)
# - 正确处理 ToolMessage 与 AIMessage 的 tool_call_id 关联
7. 持久化与 Checkpointing 系统
7.1 架构概览
Pregel Loop
│
├── 每个 superstep 结束 ──→ BaseCheckpointSaver.put(checkpoint)
│
└── 恢复执行时 ──────────→ BaseCheckpointSaver.get_tuple(config)
BaseCheckpointSaver(抽象接口)
├── MemorySaver # 开发用,进程内存
├── SqliteSaver # 单机持久化(langgraph-checkpoint-sqlite)
└── PostgresSaver # 生产用,分布式(langgraph-checkpoint-postgres)
7.2 Checkpoint 数据模型
# checkpoint 的核心数据结构
@dataclass
class Checkpoint:
id: str # UUID v6(嵌入时间戳,可按时间排序)
v: int # 版本号
ts: str # ISO 时间戳
channel_values: dict # 当前所有 channel 的值(即完整 state)
channel_versions: dict # 每个 channel 的版本号
versions_seen: dict # 已处理的写入版本(用于幂等性)
pending_sends: list # 待处理的 Send 消息
@dataclass
class CheckpointMetadata:
source: Literal["input", "loop", "update", "fork"]
step: int # superstep 编号(-1 为 input checkpoint)
writes: dict # 本 superstep 的写入记录
parents: dict # 父 checkpoint 引用
7.3 Thread 与 Checkpoint 管理
from langgraph.checkpoint.postgres import PostgresSaver
from psycopg import Connection
# 初始化 PostgreSQL checkpointer
conn = Connection.connect("postgresql://user:pass@host/db")
checkpointer = PostgresSaver(conn)
checkpointer.setup() # 创建必要的表结构
graph = builder.compile(checkpointer=checkpointer)
# 每次调用必须传入 thread_id(隔离不同会话)
config = {"configurable": {"thread_id": "user_123_session_456"}}
result = graph.invoke({"messages": [HumanMessage("Hello")]}, config)
# 获取当前状态快照
snapshot = graph.get_state(config)
print(snapshot.values) # 当前 state 值
print(snapshot.next) # 下一个要执行的节点
print(snapshot.metadata) # step、source 等元数据
# 列出所有历史 checkpoint(时间旅行调试)
history = list(graph.get_state_history(config))
for state in history:
print(f"Step {state.metadata['step']}: {state.values}")
7.4 跨线程记忆:BaseStore
Checkpointer 是线程(thread)级别的持久化,若需要跨线程共享信息(如用户偏好),使用 BaseStore:
from langgraph.store.memory import InMemoryStore
from langgraph.store.postgres import PostgresStore
store = InMemoryStore() # 或 PostgresStore(...)
graph = builder.compile(
checkpointer=checkpointer,
store=store, # 跨线程共享存储
)
# 在节点中访问 store
def personalized_node(state: State, *, store: BaseStore) -> dict:
# 读取用户长期记忆
user_prefs = store.get(("users", state["user_id"]), "preferences")
# 写入
store.put(
("users", state["user_id"]), # namespace
"preferences", # key
{"language": "zh-CN"} # value
)
return {}
7.5 时间旅行(Time Travel)
# 回滚到某个历史 checkpoint 并从那里重新执行
history = list(graph.get_state_history(config))
target_checkpoint = history[2] # 选择某个历史状态
# 从该 checkpoint 分叉执行(不影响原来的 thread)
fork_config = graph.update_state(
target_checkpoint.config,
{"messages": [HumanMessage("用不同的方式重试")]},
)
new_result = graph.invoke(None, fork_config)
8. Human-in-the-Loop 工作流
8.1 静态中断(Static Interrupts)
在编译时指定中断点,适用于调试和固定审批流程:
# 在 tool_node 执行前自动暂停
graph = builder.compile(
checkpointer=checkpointer,
interrupt_before=["tool_node"],
)
config = {"configurable": {"thread_id": "t1"}}
# 第一次调用:执行到 interrupt_before 节点前暂停
result = graph.invoke(input_data, config)
print("Graph paused. Current state:")
print(graph.get_state(config).values)
# 人工审查后,以 None 输入恢复执行
final_result = graph.invoke(None, config)
8.2 动态中断(Dynamic Interrupts)— 生产推荐
使用 interrupt() 函数在节点内部按条件中断,更灵活:
from langgraph.types import interrupt, Command
def review_node(state: AgentState) -> dict:
tool_call = state["messages"][-1].tool_calls[0]
# 暂停并向用户展示信息,等待回应
# interrupt() 会保存当前状态,抛出中断信号
user_decision = interrupt({
"action": tool_call["name"],
"args": tool_call["args"],
"message": "是否允许执行此工具调用?",
})
if user_decision["approved"]:
return {"approved": True}
else:
return Command(goto=END) # 拒绝则终止
# 恢复执行时传入用户决策
graph.invoke(
Command(resume={"approved": True}),
config
)
8.3 状态修改后恢复
# 中断后,可以修改状态再继续
graph.update_state(
config,
{"messages": [AIMessage("修改后的响应")]},
as_node="llm_node" # 假装是从该节点写入的
)
# 继续执行
graph.invoke(None, config)
9. 流式输出(Streaming)
9.1 流式模式对比
| 模式 | 触发时机 | 数据内容 | 适用场景 |
|---|---|---|---|
values | 每个 superstep 后 | 完整 state 快照 | 状态追踪 |
updates | 每个节点完成后 | 节点输出的 delta | 仪表板、进度显示 |
messages | 每个 LLM token | (message_chunk, metadata) | 聊天 UI |
debug | 各执行阶段 | 详细调试信息 | 开发调试 |
custom | 手动推送 | 任意自定义数据 | 特殊业务需求 |
9.2 使用示例
# 模式 1:values - 每步完整状态
for chunk in graph.stream(inputs, config, stream_mode="values"):
print(chunk) # 完整 state dict
# 模式 2:updates - 增量更新(推荐生产)
for node_name, updates in graph.stream(inputs, config, stream_mode="updates"):
print(f"Node '{node_name}' output: {updates}")
# 模式 3:messages - token 级流式(聊天应用)
for msg_chunk, metadata in graph.stream(inputs, config, stream_mode="messages"):
if hasattr(msg_chunk, "content"):
print(msg_chunk.content, end="", flush=True)
# 混合模式(同时获取多种)
for stream_type, data in graph.stream(
inputs, config, stream_mode=["updates", "messages"]
):
if stream_type == "messages":
token, meta = data
print(token.content, end="")
elif stream_type == "updates":
print(f"\n[Node: {list(data.keys())[0]}]")
# 自定义流(在节点内 push 自定义数据)
from langgraph.types import StreamWriter
def my_node(state: State, writer: StreamWriter) -> dict:
writer({"progress": "Starting step 1..."})
# do work
writer({"progress": "Step 1 done"})
return {}
9.3 异步流式(生产推荐)
import asyncio
async def stream_agent():
async for chunk in graph.astream(inputs, config, stream_mode="updates"):
node_name, data = list(chunk.items())[0]
yield f"data: {json.dumps({'node': node_name, 'data': data})}\n\n"
# 在 FastAPI 中使用 Server-Sent Events
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
@app.post("/chat")
async def chat(request: ChatRequest):
return StreamingResponse(
stream_agent(),
media_type="text/event-stream"
)
10. 高级控制流:Send / Command / 条件边
10.1 Send API:动态并行(Map-Reduce 模式)
当需要在运行时动态生成可变数量的并行任务时,使用 Send:
from langgraph.types import Send
# 场景:对用户提交的 N 个文档并行处理
def dispatch_documents(state: State) -> list[Send]:
# 从条件边返回 Send 列表,动态创建节点实例
return [
Send("process_document", {"doc_id": doc_id, "content": content})
for doc_id, content in state["documents"].items()
]
def process_document(state: dict) -> dict:
# 每个 Send 实例独立的 state
result = summarize(state["content"])
return {"summaries": [result]}
builder.add_conditional_edges("router", dispatch_documents, ["process_document"])
builder.add_node("process_document", process_document)
builder.add_edge("process_document", "aggregate")
10.2 Command 对象:状态更新 + 路由合一
Command 允许节点同时更新状态和决定下一跳,消除对条件边的依赖:
from langgraph.types import Command
from typing import Literal
def smart_node(state: State) -> Command[Literal["node_a", "node_b", "__end__"]]:
result = process(state)
# 同时更新状态 + 路由
if result["confidence"] > 0.9:
return Command(
update={"result": result["value"], "status": "done"},
goto=END
)
elif result["need_tools"]:
return Command(
update={"pending_tool": result["tool_call"]},
goto="tool_executor"
)
else:
return Command(goto="retry_node")
# 在子图中导航到父图
def subgraph_node(state: SubState) -> Command:
return Command(
update={"sub_result": "done"},
goto="parent_node",
graph=Command.PARENT # 关键:导航到父图
)
陷阱:
Command.goto是叠加的,不是替代。若同时存在add_edge("node", "next"),两个目标节点都会执行。
10.3 条件边高级用法
# 带类型提示的路由(IDE 友好,运行时检查)
from typing import Literal
def router(state: State) -> Literal["tools", "respond", "__end__"]:
last = state["messages"][-1]
if hasattr(last, "tool_calls") and last.tool_calls:
return "tools"
elif state["iteration"] >= 5:
return "__end__"
else:
return "respond"
# 使用字符串 "__end__" 等价于 END 常量
graph.add_conditional_edges("llm", router)
11. 多 Agent 系统深度指南
11.1 架构模式全景
LangGraph 原生支持 7 种多 Agent 架构模式,选型决策树如下:
任务是否可分解为独立子域?
├── 否 → 单 Agent + 工具调用
└── 是 → 子域间关系如何?
├── 严格顺序依赖 → Pipeline(流水线)模式
├── 有中央调度需求 → Supervisor(监督者)模式
├── 需要多层级管理 → Hierarchical(层级树)模式
├── Agent 自主协商 → Swarm(蜂群)模式
├── 点对点通信 → Network(网络)模式
├── 需要质量自检 → Reflection(反思)模式
└── 需要对抗验证 → Debate(辩论)模式
11.2 Supervisor 模式(集中调度)
适用场景:结构化任务、需要统一审查、worker 不能直接回复用户。
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.prebuilt import create_react_agent
from langgraph.types import Command
from typing import Literal
# 创建专职 Worker Agent
researcher = create_react_agent(llm, tools=[web_search, read_docs], name="researcher")
coder = create_react_agent(llm, tools=[write_code, run_tests], name="coder")
class SupervisorState(MessagesState):
next_agent: str
SYSTEM_PROMPT = """你是一个任务协调员。根据当前任务决定派发给:
- researcher:需要搜索信息时
- coder:需要编写或执行代码时
- FINISH:任务已完成时
只输出一个词:researcher / coder / FINISH"""
def supervisor_node(state: SupervisorState) -> Command[Literal["researcher", "coder", "__end__"]]:
messages = [{"role": "system", "content": SYSTEM_PROMPT}] + state["messages"]
response = supervisor_llm.invoke(messages)
decision = response.content.strip().lower()
if decision == "finish":
return Command(goto=END)
return Command(goto=decision, update={"next_agent": decision})
builder = StateGraph(SupervisorState)
builder.add_node("supervisor", supervisor_node)
builder.add_node("researcher", researcher)
builder.add_node("coder", coder)
builder.add_edge(START, "supervisor")
# worker 完成后都回到 supervisor
builder.add_edge("researcher", "supervisor")
builder.add_edge("coder", "supervisor")
graph = builder.compile(checkpointer=checkpointer)
Token 成本注意:Supervisor 模式因存在"翻译层"(所有 worker 输出必须经过 supervisor 二次处理),Token 消耗显著高于 Swarm 模式。
11.3 Hierarchical 层级树模式
适用于大规模系统(百级 Agent),将 Agent 组织为多层级团队:
总 Supervisor
├── 研究团队 Supervisor
│ ├── Web 搜索 Agent
│ ├── 文献检索 Agent
│ └── 数据分析 Agent
└── 工程团队 Supervisor
├── 代码编写 Agent
├── 测试 Agent
└── 部署 Agent
from langgraph_supervisor import create_supervisor
# 安装:pip install langgraph-supervisor
# 构建子团队 Supervisor
research_team = create_supervisor(
agents=[web_search_agent, literature_agent, data_analyst_agent],
model=llm,
prompt="你是研究团队主管,协调信息收集与分析工作。",
).compile()
engineering_team = create_supervisor(
agents=[coder_agent, tester_agent, deployer_agent],
model=llm,
prompt="你是工程团队主管,协调代码开发与部署工作。",
).compile()
# 顶层总 Supervisor(子团队作为节点)
top_supervisor = create_supervisor(
agents=[research_team, engineering_team],
model=llm,
prompt="你是总协调员,根据任务类型派发给研究团队或工程团队。",
).compile(checkpointer=checkpointer)
11.4 Swarm 蜂群模式(去中心化)
适用场景:探索性任务、Agent 自主判断移交、减少 Token 消耗。
pip install langgraph-swarm
from langgraph_swarm import create_swarm, create_handoff_tool
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import InMemorySaver
# 每个 Agent 配备"移交工具",自主决定何时将控制权传递给谁
researcher = create_react_agent(
llm,
tools=[
web_search,
create_handoff_tool(
agent_name="coder",
description="当需要编写或执行代码时,移交给 coder"
),
],
prompt="你是研究专家,负责信息收集和分析。",
name="researcher",
)
coder = create_react_agent(
llm,
tools=[
write_code,
run_tests,
create_handoff_tool(
agent_name="researcher",
description="当需要更多背景信息时,移交给 researcher"
),
],
prompt="你是代码专家,负责编写和测试代码。",
name="coder",
)
# 编译 Swarm(系统会记住最后活跃的 Agent)
swarm = create_swarm(
agents=[researcher, coder],
default_active_agent="researcher", # 默认入口 Agent
).compile(checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "session_001"}}
result = swarm.invoke(
{"messages": [HumanMessage("帮我研究 LangGraph 并写一个示例")]},
config
)
Supervisor vs Swarm 核心对比:
| 维度 | Supervisor | Swarm |
|---|---|---|
| 协调方式 | 集中式(中央 LLM 决策) | 去中心化(Agent 自主移交) |
| Token 消耗 | 高(翻译层开销) | 低(直接移交) |
| 可控性 | 强(审计清晰) | 弱(行为涌现) |
| 适合任务 | 结构化、合规敏感 | 探索性、流体任务 |
| 用户可见 | 只有 Supervisor 回复 | 当前 Agent 直接回复 |
11.5 Reflection 反思模式(质量自检循环)
from langgraph.graph import StateGraph, START, END
from typing import Annotated
from operator import add
class ReflectionState(TypedDict):
task: str
draft: str
critiques: Annotated[list[str], add]
iteration: int
final_output: str
def generate_node(state: ReflectionState) -> dict:
"""生成或改进草稿"""
if state.get("critiques"):
prompt = f"原草稿:{state['draft']}\n批评意见:{state['critiques'][-1]}\n请改进:"
else:
prompt = f"任务:{state['task']}\n请生成初稿:"
result = llm.invoke(prompt)
return {"draft": result.content}
def reflect_node(state: ReflectionState) -> dict:
"""批评并提出改进意见"""
prompt = f"请严格审查以下内容并指出问题:\n{state['draft']}"
critique = llm.invoke(prompt)
return {"critiques": [critique.content], "iteration": state.get("iteration", 0) + 1}
def should_continue(state: ReflectionState) -> str:
"""质量门控:超过3轮或质量达标则结束"""
if state.get("iteration", 0) >= 3:
return "finalize"
if "无明显问题" in (state.get("critiques") or [""])[-1]:
return "finalize"
return "reflect"
builder = StateGraph(ReflectionState)
builder.add_node("generate", generate_node)
builder.add_node("reflect", reflect_node)
builder.add_node("finalize", lambda s: {"final_output": s["draft"]})
builder.add_edge(START, "generate")
builder.add_conditional_edges("generate", should_continue, ["reflect", "finalize"])
builder.add_edge("reflect", "generate") # 反思后重新生成
builder.add_edge("finalize", END)
11.6 Debate 辩论模式(对抗验证)
研究表明,对抗式多 Agent 辩论可将事实准确率提升约 23%。
class DebateState(TypedDict):
topic: str
messages: Annotated[list[BaseMessage], add_messages]
round: int
verdict: str
def advocate_node(state: DebateState) -> dict:
"""支持方:论证正面观点"""
last_msg = state["messages"][-1].content if state["messages"] else ""
prompt = f"议题:{state['topic']}\n对方论点:{last_msg}\n请提出有力的支持论据:"
response = advocate_llm.invoke(prompt)
return {"messages": [AIMessage(content=response.content, name="advocate")]}
def critic_node(state: DebateState) -> dict:
"""反对方:质疑并反驳"""
last_msg = state["messages"][-1].content
prompt = f"议题:{state['topic']}\n对方论点:{last_msg}\n请提出有力的反驳意见:"
response = critic_llm.invoke(prompt)
return {
"messages": [AIMessage(content=response.content, name="critic")],
"round": state.get("round", 0) + 1,
}
def judge_node(state: DebateState) -> dict:
"""裁判:总结辩论并得出结论"""
debate_text = "\n".join([f"{m.name}: {m.content}" for m in state["messages"]])
prompt = f"以下是关于「{state['topic']}」的辩论记录:\n{debate_text}\n请总结并给出结论:"
verdict = judge_llm.invoke(prompt)
return {"verdict": verdict.content}
def debate_router(state: DebateState) -> str:
return "judge" if state.get("round", 0) >= 3 else "critic"
builder = StateGraph(DebateState)
builder.add_node("advocate", advocate_node)
builder.add_node("critic", critic_node)
builder.add_node("judge", judge_node)
builder.add_edge(START, "advocate")
builder.add_conditional_edges("critic", debate_router, ["advocate", "judge"])
builder.add_edge("advocate", "critic")
builder.add_edge("judge", END)
11.7 子图状态映射机制(深度解析)
策略 A:共享状态键(直接挂载)
当父图与子图存在相同的状态字段时,LangGraph 自动同步这些共享键:
class ParentState(TypedDict):
messages: Annotated[list, add_messages]
task: str # 共享键
result: str # 共享键
class SubgraphState(TypedDict):
messages: Annotated[list, add_messages]
task: str # 与父图相同 → 自动同步
result: str # 与父图相同 → 自动同步
internal_memo: str # 子图内部键 → 不会泄漏到父图
sub_graph = builder_sub.compile()
# 直接挂载:LangGraph 自动处理共享键的双向同步
parent_builder.add_node("worker", sub_graph)
策略 B:不同 Schema(包装器函数转换)
当父子图 Schema 完全不兼容时,必须使用包装函数手动转换:
class ParentState(TypedDict):
user_query: str
final_answer: str
class SubgraphState(TypedDict):
input_text: str # 与父图无重叠键
output_text: str
confidence: float
sub_graph = sub_builder.compile()
# 包装函数:纯适配器,只做转换不含业务逻辑
def call_subgraph(state: ParentState) -> dict:
# Step 1:父图 State → 子图 State
sub_input = SubgraphState(
input_text=state["user_query"],
output_text="",
confidence=0.0,
)
# Step 2:调用子图
sub_result = sub_graph.invoke(sub_input)
# Step 3:子图 State → 父图 State
return {
"final_answer": sub_result["output_text"],
}
parent_builder.add_node("worker", call_subgraph)
关键规则:
- 无共享键时不能直接挂载,LangGraph 会抛出运行时错误
- 包装函数只应做转换,不应包含业务逻辑(保持适配器纯粹性)
- 子图的内部键(如
internal_memo)不会自动泄漏到父图
三层嵌套(祖父 → 父 → 子)
# 每层都需要独立的状态转换
def call_child_graph(parent_state: ParentState) -> dict:
child_input = transform_to_child(parent_state)
# child 内部会再调用 grandchild
child_result = child_graph.invoke(child_input)
return transform_from_child(child_result)
# child 内部的节点:
def call_grandchild_graph(child_state: ChildState) -> dict:
grandchild_input = transform_to_grandchild(child_state)
grandchild_result = grandchild_graph.invoke(grandchild_input)
return transform_from_grandchild(grandchild_result)
子图持久化配置
# 重要:checkpointer 只需在父图编译时传入
# 子图会自动继承父图的持久化能力
parent_graph = parent_builder.compile(checkpointer=PostgresSaver(conn))
# 访问子图的状态历史(使用父图 config + 子图命名空间)
parent_config = {"configurable": {"thread_id": "t1"}}
# 子图的 checkpoint 以 (thread_id, subgraph_name) 为命名空间存储
11.8 跨 Agent 共享内存:BaseStore
Checkpointer 只在单个 thread_id 内持久化。若要在多个 Agent、多个会话间共享信息,使用 BaseStore。
核心概念:Namespace 体系
BaseStore
└── namespace: ("users", "alice")
├── key: "preferences" → {"language": "zh-CN", "style": "concise"}
├── key: "history" → {"topics": ["LangGraph", "Python"]}
└── ...
└── namespace: ("agent_instructions",)
├── key: "researcher" → {"instructions": "优先使用学术来源"}
└── key: "coder" → {"instructions": "代码需包含类型注解"}
└── namespace: ("shared_context", "project_001")
└── key: "brief" → {"goal": "...", "constraints": [...]}
基本 CRUD 操作
from langgraph.store.memory import InMemoryStore
from langgraph.store.postgres import PostgresStore # 生产用
import uuid
store = InMemoryStore() # 或 PostgresStore(conn_string)
# 在节点中注入 store(LangGraph 自动注入)
def personalized_agent(state: AgentState, *, store: BaseStore) -> dict:
user_id = state["user_id"]
namespace = ("users", user_id)
# 读取用户偏好
pref_item = store.get(namespace, "preferences")
prefs = pref_item.value if pref_item else {}
# 基于偏好构造系统提示
system = f"用户偏好语言:{prefs.get('language', 'zh-CN')}"
response = llm.invoke([SystemMessage(system)] + state["messages"])
# 更新用户交互记录
store.put(namespace, "last_interaction", {
"timestamp": datetime.now().isoformat(),
"topic": extract_topic(response.content),
})
return {"messages": [response]}
# 编译时传入 store
graph = builder.compile(checkpointer=checkpointer, store=store)
语义搜索(向量检索)
# 使用支持向量搜索的后端(如 Redis、MongoDB)
from langgraph.store.redis import RedisStore
store = RedisStore(redis_url="redis://localhost:6379", embedding=embeddings_model)
def memory_aware_agent(state: AgentState, *, store: BaseStore) -> dict:
user_id = state["user_id"]
query = state["messages"][-1].content
# 语义搜索:找出与当前问题最相关的历史记忆
relevant_memories = store.search(
namespace_prefix=("users", user_id),
query=query, # 向量相似度搜索
limit=5,
)
memory_context = "\n".join([
f"- {item.value['content']}" for item in relevant_memories
])
system = f"以下是用户的相关历史信息:\n{memory_context}"
response = llm.invoke([SystemMessage(system)] + state["messages"])
# 将新信息存入记忆
store.put(
("users", user_id, "memories"),
str(uuid.uuid4()),
{"content": response.content, "timestamp": datetime.now().isoformat()},
)
return {"messages": [response]}
多 Agent 共享指令(Procedural Memory)
# Agent 团队共享操作规范,可在运行时动态更新
def update_agent_instructions(agent_name: str, instructions: str, store: BaseStore):
store.put(
("agent_instructions",),
agent_name,
{"instructions": instructions, "updated_at": datetime.now().isoformat()},
)
def agent_with_shared_instructions(state: State, *, store: BaseStore) -> dict:
# 读取团队共享的操作规范
instr_item = store.get(("agent_instructions",), "researcher")
instructions = instr_item.value["instructions"] if instr_item else ""
system = f"操作规范:{instructions}"
response = llm.invoke([SystemMessage(system)] + state["messages"])
return {"messages": [response]}
11.9 生产级多 Agent 系统:并发控制与可观测性
并发隔离原则
# 多租户:thread_id 必须包含租户标识,防止状态污染
def make_thread_id(tenant_id: str, user_id: str, session_id: str) -> str:
return f"t:{tenant_id}:u:{user_id}:s:{session_id}"
# store 的 namespace 同样需要租户隔离
def get_user_namespace(tenant_id: str, user_id: str) -> tuple:
return ("tenants", tenant_id, "users", user_id)
Double-Texting 防护(LangGraph Platform 特性)
当用户在 Agent 仍在运行时再次发送消息(double-texting),可能导致状态冲突。LangGraph Platform 提供四种处理策略:
| 策略 | 行为 | 适用场景 |
|---|---|---|
reject | 拒绝新请求,返回错误 | 严格单路对话 |
enqueue | 排队等待当前运行完成 | 顺序处理 |
interrupt | 中断当前运行,处理新消息 | 聊天机器人 |
rollback | 回滚到上一个 checkpoint 再处理 | 需要干净状态 |
# 通过 SDK 指定策略
result = await client.runs.create(
thread_id=thread_id,
assistant_id="agent",
input={"messages": [...]},
multitask_strategy="interrupt", # 指定 double-texting 策略
)
后台运行(Background Runs)
# 创建异步后台运行(不阻塞客户端)
run = await client.runs.create(
thread_id=thread_id,
assistant_id="agent",
input={"messages": [...]},
# 不传 stream_mode,即为后台运行
)
run_id = run["run_id"]
# 客户端稍后轮询或通过 webhook 获取结果
run_status = await client.runs.get(thread_id, run_id)
if run_status["status"] == "success":
final_state = await client.threads.get_state(thread_id)
可观测性:关键指标与追踪
import os
# LangSmith 全链路追踪(节点级别)
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your_key"
os.environ["LANGCHAIN_PROJECT"] = "multi-agent-prod"
# 在节点中添加自定义 metadata(便于后续筛选)
from langchain_core.callbacks import get_callback_manager
def instrumented_node(state: State) -> dict:
# LangSmith 自动捕获输入/输出、延迟、Token 消耗
with tracing_context(tags=["agent:researcher", f"user:{state['user_id']}"]):
result = llm.invoke(state["messages"])
return {"messages": [result]}
生产监控核心指标:
| 指标 | 说明 | 告警阈值参考 |
|---|---|---|
task_success_rate | 任务完成率 | < 95% 告警 |
avg_token_per_run | 平均 Token 消耗 | 超预算 120% 告警 |
p95_latency | P95 延迟 | > 30s 告警(长任务除外) |
handoff_rate | Swarm 中 Agent 移交频率 | 异常高说明 Agent 能力边界不清 |
human_escalation_rate | 人工干预触发率 | > 10% 需重新评估 Agent 能力 |
checkpoint_failure_rate | Checkpoint 写入失败率 | > 0.1% 立即告警 |
生产就绪检查清单
多 Agent 系统上线前检查:
□ State Schema 使用 Pydantic 做运行时验证
□ 所有 Agent 节点配置 RetryPolicy(网络错误重试)
□ thread_id 包含租户隔离标识
□ BaseStore namespace 按租户分区
□ LangSmith 追踪已启用,关键节点打 tag
□ PostgresSaver 已配置连接池(推荐 psycopg3 async pool)
□ 实现 double-texting 防护策略
□ 长任务使用 background runs + webhook 回调
□ 已对 20+ 并发 ainvoke 做过压测
□ 旧 checkpoint 清理策略已配置(防止 DB 膨胀)
□ 敏感字段(PII)在写入 checkpoint 前已脱敏
12. 预构建组件:ReAct Agent & 工具调用
12.1 create_react_agent
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
@tool
def search(query: str) -> str:
"""搜索互联网"""
return search_api(query)
@tool
def calculate(expression: str) -> float:
"""计算数学表达式"""
return eval(expression) # 注意:生产环境需沙箱
llm = ChatAnthropic(model="claude-opus-4-7")
# 最简用法
agent = create_react_agent(llm, tools=[search, calculate])
# 高级配置
agent = create_react_agent(
llm,
tools=[search, calculate],
state_schema=CustomState, # 自定义 state schema
checkpointer=PostgresSaver(conn), # 持久化
state_modifier="你是一个专业助手...", # 系统提示(注入到每轮消息)
interrupt_before=["tools"], # HIL
)
result = agent.invoke({
"messages": [HumanMessage("今天的天气如何,以及 25 * 4 等于多少?")]
})
12.2 ToolNode
from langgraph.prebuilt import ToolNode
# ToolNode 自动处理工具调用结果
tool_node = ToolNode([search, calculate])
# ToolNode 内部逻辑:
# 1. 读取最后一条 AIMessage 的 tool_calls
# 2. 并行执行所有工具
# 3. 将结果包装成 ToolMessage 写回 state
12.3 工具错误处理
# ToolNode 默认会捕获工具异常并写入 ToolMessage
tool_node = ToolNode(
tools=[search],
handle_tool_errors=True, # 默认 True:将异常转为 ToolMessage
)
# 自定义错误处理
def handle_error(error: Exception, tool_call: dict) -> str:
return f"工具调用失败: {error}. 请换一种方式尝试。"
tool_node = ToolNode(tools, handle_tool_errors=handle_error)
13. 部署:langgraph-cli 与 LangGraph Platform
13.1 项目文件结构
my_agent/
├── langgraph.json # LangGraph 项目配置(必需)
├── .env # 环境变量(API keys 等)
├── requirements.txt
└── src/
└── agent.py # 图定义
langgraph.json 配置示例:
{
"dependencies": ["."],
"graphs": {
"agent": "./src/agent.py:graph",
"researcher": "./src/researcher.py:researcher_graph"
},
"env": ".env",
"python_version": "3.11",
"pip_config_file": "pyproject.toml"
}
13.2 本地开发服务器
# 安装 CLI
pip install langgraph-cli
# 启动本地开发服务器(in-memory 模式)
langgraph dev
# 指定端口和配置
langgraph dev --port 2024 --config langgraph.json
# 输出:
# 🚀 API: http://localhost:2024
# 🎨 Studio: https://smith.langchain.com/studio/?baseUrl=http://localhost:2024
13.3 REST API 调用
LangGraph Server 暴露标准 REST API:
# 创建 assistant(基于已定义的 graph)
curl -X POST http://localhost:2024/assistants \
-H "Content-Type: application/json" \
-d '{"graph_id": "agent", "config": {}}'
# 创建 thread
curl -X POST http://localhost:2024/threads \
-H "Content-Type: application/json" \
-d '{}'
# 流式运行
curl -X POST http://localhost:2024/threads/{thread_id}/runs/stream \
-H "Content-Type: application/json" \
-d '{
"assistant_id": "agent",
"input": {"messages": [{"role": "human", "content": "Hello"}]},
"stream_mode": "messages-tuple"
}'
13.4 Python SDK 客户端
from langgraph_sdk import get_client
client = get_client(url="http://localhost:2024")
# 创建 thread 并运行
thread = await client.threads.create()
async for chunk in client.runs.stream(
thread["thread_id"],
"agent",
input={"messages": [{"role": "human", "content": "Hello"}]},
stream_mode="messages",
):
if chunk.event == "messages/partial":
print(chunk.data[0]["content"], end="")
13.5 部署选项对比
| 方案 | 适用场景 | 持久化 | 扩展性 |
|---|---|---|---|
langgraph dev | 本地开发 | 内存(重启丢失) | 单进程 |
| LangGraph Cloud (LangSmith) | 生产托管,一键部署 | 自动管理 | 自动扩缩容 |
| 自托管 + PostgresSaver | 私有部署,数据合规 | PostgreSQL | 手动水平扩展 |
| BentoML/BentoCloud | 开源模型部署 | 自定义 | 容器化 |
14. 生产最佳实践
14.1 状态设计原则
# ✅ 好的实践:最小化、明确类型、合理使用 Reducer
class AgentState(TypedDict):
messages: Annotated[list[BaseMessage], add_messages] # 明确 reducer
task_id: str # 不可变 ID
status: Literal["running", "done", "failed"] # 枚举值
# ❌ 避免:在 state 中存储临时变量或大型二进制数据
class BadState(TypedDict):
messages: list
temp_result: Any # 应该通过函数作用域传递
raw_pdf_bytes: bytes # 不应存在 state 中
everything: dict # 避免无结构的大 dict
14.2 节点设计规范
# ✅ 节点应该是幂等的(相同输入产生相同输出)
# ✅ 节点应该是纯函数(输出只依赖输入 state)
# ✅ 适当的超时和重试
from langgraph.types import RetryPolicy
# 为节点配置重试策略(网络错误、rate limit 等)
builder.add_node(
"llm_call",
llm_node,
retry=RetryPolicy(
max_attempts=3,
initial_interval=1.0,
backoff_factor=2.0,
jitter=True,
)
)
14.3 并发与隔离
# 多租户部署:用 user_id + session_id 组合作为 thread_id
def get_thread_id(user_id: str, session_id: str) -> str:
return f"user_{user_id}::session_{session_id}"
# 避免 thread_id 碰撞导致状态污染
config = {
"configurable": {
"thread_id": get_thread_id(user_id, session_id),
"user_id": user_id, # 可用于 store 的 namespace
}
}
14.4 Checkpoint 管理
# 定期清理旧 checkpoint,避免数据库膨胀
# PostgresSaver 示例:按时间策略清理
# 生产环境建议配置 checkpoint TTL(在数据库层面)
# 或实现定时清理任务:
async def cleanup_old_threads():
cutoff = datetime.now() - timedelta(days=30)
await checkpointer.delete_thread(
config={"configurable": {"thread_id": old_thread_id}}
)
14.5 错误处理与容错
# LangGraph 故障恢复机制:
# - 某节点失败时,已完成节点的 checkpoint 不会丢失
# - 重新调用 invoke/stream 时,从失败前的最后 checkpoint 恢复
# 自定义错误处理节点
def error_handler_node(state: State) -> dict:
error = state.get("error")
if error:
# 记录错误、通知用户、决定是否重试
log_error(error)
return {"status": "failed", "error_message": str(error)}
return {}
# 在图中添加错误路由
builder.add_conditional_edges(
"risky_node",
lambda s: "error_handler" if s.get("error") else "next_node"
)
14.6 安全规范
# 工具调用安全:使用白名单而非通配符
ALLOWED_TOOLS = {"web_search", "calculate", "read_file"}
def secure_tool_router(state: State) -> str:
tool_name = state["messages"][-1].tool_calls[0]["name"]
if tool_name not in ALLOWED_TOOLS:
raise ValueError(f"未授权的工具调用: {tool_name}")
return "tool_node"
# 状态中的 PII 处理:在写入 checkpoint 前脱敏
def sanitize_state(state: State) -> State:
# 脱敏敏感字段后再存储
...
15. 调试与可观测性
15.1 LangSmith 集成
# 设置环境变量
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=your_api_key
export LANGCHAIN_PROJECT=my_langgraph_project
# 所有 graph.invoke/stream 调用自动上报到 LangSmith
# 包含完整的节点执行树、state 变化、LLM 调用详情
result = graph.invoke(inputs, config)
# → 在 LangSmith UI 中可查看完整执行轨迹
15.2 本地调试技巧
# 方式 1:开启 debug 模式
graph = builder.compile(debug=True)
# 输出每个 superstep 的详细信息
# 方式 2:遍历执行历史
config = {"configurable": {"thread_id": "debug_001"}}
result = graph.invoke(inputs, config)
for state in graph.get_state_history(config):
print(f"Step {state.metadata['step']} ({state.metadata['source']})")
print(f" Messages: {len(state.values.get('messages', []))}")
print(f" Next: {state.next}")
print("---")
# 方式 3:stream with debug mode
for event in graph.stream(inputs, config, stream_mode="debug"):
print(event)
15.3 LangGraph Studio
访问本地 Studio(需先运行 langgraph dev):
https://smith.langchain.com/studio/?baseUrl=http://localhost:2024
功能:
- 图形化执行流程:实时可视化节点执行路径
- 状态检查器:每个 superstep 查看完整 state
- 时间旅行:选择任意历史 checkpoint 重新执行
- 人工干预:在中断点直接修改 state
16. API 快速参考
16.1 核心导入
# 图构建
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.graph.message import add_messages
# 控制流
from langgraph.types import Send, Command, interrupt, StreamWriter
from langgraph.types import RetryPolicy, CachePolicy, Durability
# Checkpointing
from langgraph.checkpoint.memory import MemorySaver
from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.checkpoint.postgres import PostgresSaver
# 跨线程存储
from langgraph.store.memory import InMemoryStore
# 预构建组件
from langgraph.prebuilt import create_react_agent, ToolNode
# Functional API
from langgraph.func import entrypoint, task
16.2 StateGraph 方法速查
| 方法 | 说明 |
|---|---|
add_node(name, fn, retry=...) | 添加节点 |
add_edge(from, to) | 添加固定边 |
add_conditional_edges(from, fn, mapping?) | 添加条件边 |
set_entry_point(node) | 等价于 add_edge(START, node) |
set_finish_point(node) | 等价于 add_edge(node, END) |
compile(checkpointer?, interrupt_before?, ...) | 编译为可执行图 |
16.3 CompiledGraph 方法速查
| 方法 | 说明 |
|---|---|
invoke(input, config?) | 同步执行 |
ainvoke(input, config?) | 异步执行 |
stream(input, config?, stream_mode?) | 同步流式 |
astream(input, config?, stream_mode?) | 异步流式 |
get_state(config) | 获取当前状态快照 |
get_state_history(config) | 获取历史快照列表 |
update_state(config, values, as_node?) | 修改状态(HIL) |
16.4 关键类型定义
# 运行配置
config = {
"configurable": {
"thread_id": "unique_thread_id", # 必需(有 checkpointer 时)
"checkpoint_id": "specific_ckpt", # 可选:指定恢复点
},
"recursion_limit": 25, # 最大递归深度(默认 25)
"tags": ["production", "user_123"], # LangSmith 标签
"metadata": {"user_id": "123"}, # 自定义元数据
}
# 流式模式类型
stream_mode: Literal["values", "updates", "messages", "debug", "custom"]