设置
安装langgraph:
定义和更新状态
在此我们展示如何在 LangGraph 中定义和更新 状态。我们将演示:定义状态
LangGraph 中的 状态 可以是TypedDict、Pydantic 模型或 dataclass。下面我们将使用 TypedDict。有关使用 Pydantic 的详细信息,请参阅 为图状态使用 Pydantic 模型。
默认情况下,图将具有相同的输入和输出模式,状态决定了该模式。有关如何定义不同的输入和输出模式,请参阅 定义输入和输出模式。
让我们考虑一个使用 消息 的简单示例。这代表了适用于许多 LLM 应用的通用状态表述。有关更多详细信息,请参阅我们的 概念页面。
更新状态
让我们构建一个包含单个节点的示例图。我们的 节点 只是一个读取图的 state 并对其进行更新的 Python 函数。此函数的第一个参数始终是 state:StateGraph 来定义一个在此状态下操作的图。然后我们使用 add_node 来填充我们的图。

- 我们通过更新状态的单个键来启动调用。
- 我们在调用结果中接收整个状态。
使用归约器处理状态更新
状态中的每个键都可以有自己的独立 归约器 函数,它控制如何应用来自节点的更新。如果没有显式指定归约器函数,则假设对该键的所有更新都应覆盖它。 对于TypedDict 状态模式,我们可以通过使用归约器函数注释状态的相应字段来定义归约器。
在之前的示例中,我们的节点通过在消息列表中追加一条消息来更新状态中的 "messages" 键。下面,我们为此键添加一个归约器,以便自动追加更新:
MessagesState
在实践中,更新消息列表还有其他注意事项: LangGraph 包含一个内置归约器add_messages,可处理这些注意事项:
MessagesState 以供方便使用,因此我们可以拥有:
使用 Overwrite 绕过归约器
在某些情况下,您可能想要绕过归约器并直接覆盖状态值。LangGraph 为此目的提供了 Overwrite 类型。当节点返回用 Overwrite 包装的值时,归约器将被绕过,通道将直接设置为该值。
当您想要重置或替换累积的状态而不是将其与现有值合并时,这很有用。
"__overwrite__" 的 JSON 格式:
定义输入和输出模式
默认情况下,StateGraph 使用单一模式运行,所有节点都预期使用该模式进行通信。但是,也可以为图定义不同的输入和输出模式。
当指定不同的模式时,内部仍将使用模式用于节点之间的通信。输入模式确保提供的输入符合预期的结构,而输出模式过滤内部数据,仅根据定义的模式返回相关信息。
下面,我们将看到如何定义不同的输入和输出模式。
在节点之间传递私有状态
在某些情况下,您可能希望节点交换对中间逻辑至关重要但不需要成为图主模式一部分的信息。这种私有数据与图的整体输入/输出无关,应仅在特定节点之间共享。 下面,我们将创建一个由三个节点(node_1、node_2 和 node_3)组成的示例顺序图,其中私有数据在前两个步骤(node_1 和 node_2)之间传递,而第三个步骤(node_3)只能访问公共整体状态。为图状态使用 Pydantic 模型
StateGraph 在初始化时接受state_schema 参数,指定图中节点可以访问和更新的 state 的“形状”。
在我们的示例中,我们通常使用 Python 原生的 TypedDict 或 dataclass 作为 state_schema,但 state_schema 可以是任何 类型。
在这里,我们将看到如何使用 Pydantic BaseModel 作为 state_schema 来为 输入 添加运行时验证。
已知限制
- 目前,图的输出 不会 是 pydantic 模型的实例。
- 运行时验证仅发生在图中第一个节点的输入上,而不发生在后续节点或输出上。
- pydantic 的验证错误跟踪不显示错误出现在哪个节点。
- Pydantic 的递归验证可能很慢。对于性能敏感的应用程序,您可能需要考虑使用
dataclass。
序列化行为
序列化行为
当使用 Pydantic 模型作为状态模式时,了解序列化如何工作非常重要,特别是在以下情况:
- 将 Pydantic 对象作为输入传递
- 接收来自图的输出
- 处理嵌套的 Pydantic 模型
运行时类型强制转换
运行时类型强制转换
Pydantic 会对某些数据类型执行运行时类型强制转换。这可能很有帮助,但如果不知道这一点,也可能导致意外行为。
处理消息模型
处理消息模型
当在状态模式中使用 LangChain 消息类型时,序列化方面有重要的注意事项。在使用消息对象通过网络传输时,您应该使用
AnyMessage(而不是 BaseMessage)来进行正确的序列化/反序列化。添加运行时配置
有时您希望在调用图时能够配置它。例如,您可能希望在运行时指定要使用什么 LLM 或系统提示,而 无需将这些参数污染到图状态中。 要添加运行时配置:- 指定配置的 schema
- 将配置添加到节点或条件边的函数签名中
- 将配置传递给图。
扩展示例:在运行时指定 LLM
扩展示例:在运行时指定 LLM
下面我们演示一个实际示例,在其中配置在运行时使用什么 LLM。我们将同时使用 OpenAI 和 Anthropic 模型。
扩展示例:在运行时指定模型和系统消息
扩展示例:在运行时指定模型和系统消息
下面我们演示一个实际示例,在其中配置两个参数:在运行时使用的 LLM 和系统消息。
添加重试策略
有许多用例可能需要您的节点具有自定义重试策略,例如如果您正在调用 API、查询数据库或调用 LLM 等。LangGraph 允许您将重试策略添加到节点。 要配置重试策略,请将retry_policy 参数传递给 add_node。retry_policy 参数接受 RetryPolicy 命名元组对象。下面我们使用默认参数实例化 RetryPolicy 对象并将其与节点关联:
retry_on 参数使用 default_retry_on 函数,它在除以下之外的任何异常上重试:
ValueErrorTypeErrorArithmeticErrorImportErrorLookupErrorNameErrorSyntaxErrorRuntimeErrorReferenceErrorStopIterationStopAsyncIterationOSError
requests 和 httpx)的异常,它仅在 5xx 状态码上重试。
扩展示例:自定义重试策略
扩展示例:自定义重试策略
考虑一个我们从 SQL 数据库读取的示例。下面我们将两个不同的重试策略传递给节点:
在节点内访问执行信息
需要langgraph>=1.1.3。当节点具有重试策略时,您可以通过 runtime.execution_info 检查当前尝试次数和第一次尝试的时间。这对于根据重试状态调整行为非常有用(例如,在第一次尝试失败后切换到备用提供商)。
execution_info 也可用于 Runtime 对象——node_attempt 默认为 1,node_first_attempt_time 设置为节点开始执行的时间。
添加节点缓存
节点缓存在您希望避免重复操作的情况下非常有用,例如在执行昂贵操作时(无论是时间还是成本方面)。LangGraph 允许您在图中的节点中添加个性化的缓存策略。 要配置缓存策略,请将cache_policy 参数传递给 add_node 函数。在下面的示例中,使用 120 秒的生存时间和默认 key_func 生成器实例化 CachePolicy 对象。然后将其与节点关联:
cache 参数。下面的示例使用 InMemoryCache 来设置具有内存缓存的图,但也提供 SqliteCache。
创建步骤序列
先决条件
本指南假设您熟悉上面关于 状态 的部分。
- 如何构建顺序图
- 构建类似图的内置简写。
add_node 和 add_edge 方法:
.add_sequence:
为什么使用 LangGraph 将应用程序步骤拆分为序列?
为什么使用 LangGraph 将应用程序步骤拆分为序列?
LangGraph 使为您的应用程序添加底层持久层变得容易。
这允许在节点执行之间对状态进行检查点,因此您的 LangGraph 节点管理:它们还决定执行步骤如何 流式传输,以及如何使用 Studio 可视化和调试您的应用程序。让我们演示一个端到端示例。我们将创建三个步骤的序列:我们的 节点 只是读取图的 state 并对其进行更新的 Python 函数。此函数的第一个参数始终是 state:最后,我们定义图。我们使用 StateGraph 来定义一个在此状态下操作的图。然后我们将使用 请注意:我们接下来 编译 我们的图。这提供了对图结构的几个基本检查(例如,识别孤立节点)。如果我们通过 检查点器 为我们的应用程序添加持久性,它也将在此处传递。LangGraph 提供了用于可视化您的图的内置实用程序。让我们检查我们的序列。有关可视化的详细信息,请参阅 可视化您的图。
让我们继续进行简单的调用:请注意:
- 在状态的键中填充值
- 更新相同的值
- 填充不同的值
请注意,在向状态发出更新时,每个节点只需指定其希望更新的键的值。默认情况下,这将 覆盖 相应键的值。您还可以使用 归约器 来控制如何处理更新——例如,您可以将连续更新附加到键。有关更多详细信息,请参阅 使用归约器处理状态更新。
add_node 和 add_edge 来填充我们的图并定义其控制流。
- 我们通过为单个状态键提供值来启动调用。我们必须始终至少提供一个键的值。
- 我们传入的值被第一个节点覆盖。
- 第二个节点更新了该值。
- 第三个节点填充了不同的值。
创建分支
节点的并行执行对于加快整体图操作至关重要。LangGraph 原生支持节点的并行执行,可以显著提高基于图的工作流的性能。这种并行化是通过扇出和扇入机制实现的,利用标准边和 条件边。以下是一些示例,展示如何添加适合您的分支数据流。并行运行图节点
在此示例中,我们从Node A 扇出到 B 和 C,然后扇入到 D。使用我们的状态,我们指定归约器 add 操作。这将组合或累积特定键的值,而不是简单地覆盖现有值。对于列表,这意味着将新列表与现有列表连接。有关使用归约器更新状态的更多详细信息,请参阅上面的 状态归约器 部分。

在上述示例中,节点
"b" 和 "c" 在同一个 超级步骤 中并发执行。因为它们在同一步骤中,所以节点 "d" 在 "b" 和 "c" 完成后执行。重要的是,来自并行超级步骤的更新可能不会按一致的顺序排列。如果您需要来自并行超级步骤的一致、预定顺序的更新,您应该将输出写入状态中的单独字段,并附带用于排序的值。异常处理?
异常处理?
LangGraph 在 超级步骤 内执行节点,这意味着虽然并行分支并行执行,但整个超级步骤是 事务性 的。如果这些分支中的任何一个抛出异常,没有任何 更新应用于状态(整个超级步骤出错)。重要的是,当使用 检查点器 时,超级步骤内成功节点的結果会被保存,并且在恢复时不会重复。如果您有容易出错的(也许想处理不稳定的 API 调用)节点,LangGraph 提供两种解决方法:
- 您可以在节点内编写常规 Python 代码来捕获和处理异常。
- 您可以设置 retry_policy 以指导图重试抛出某些类型异常的节点。只有失败的分支会被重试,因此您无需担心执行冗余工作。
延迟节点执行
延迟节点执行在您希望延迟节点执行直到所有其他待处理任务完成时非常有用。这在分支长度不同的情况下特别相关,这在 map-reduce 流等工作流中很常见。 上面的示例展示了当每条路径只有一步时如何扇出和扇入。但是如果一个分支有多步怎么办?让我们在"b" 分支中添加一个节点 "b_2":

"b" 和 "c" 在同一个超级步骤中并发执行。我们在节点 d 上设置了 defer=True,因此它不会执行直到所有待处理任务完成。在这种情况下,这意味着 "d" 等待执行直到整个 "b" 分支完成。
条件分支
如果您的扇出应根据状态在运行时变化,您可以使用add_conditional_edges 使用图状态选择一个或多个路径。见下方示例,其中节点 a 生成确定下一个节点的状态更新。

Map-Reduce 和 Send API
LangGraph 支持使用 Send API 进行 map-reduce 和其他高级分支模式。以下是如何使用它的示例:
创建和控制循环
在创建带有循环的图时,我们需要一种终止执行的机制。这通常是通过添加 条件边 来实现的,一旦达到某些终止条件,该边就会路由到 END 节点。 您也可以在调用或流式传输图时设置图递归限制。递归限制设置图在抛出错误之前允许执行的 超级步骤 数量。有关 递归限制概念 的更多信息。 让我们考虑一个简单的带有循环的图,以更好地了解这些机制如何工作。 创建循环时,您可以包含指定终止条件的条件边:"recursionLimit"。这将抛出 GraphRecursionError,您可以捕获并处理:

"a" 是调用工具的模型,节点 "b" 代表工具。
在我们的 route 条件边中,我们指定在状态中的 "aggregate" 列表超过阈值长度后我们应该结束。
调用图时,我们看到我们在达到终止条件之前在节点 "a" 和 "b" 之间交替。
施加递归限制
在某些应用中,我们无法保证将达到给定的终止条件。在这些情况下,我们可以设置图的 递归限制。这将在给定数量的 超级步骤 后抛出GraphRecursionError。然后我们可以捕获并处理此异常:
扩展示例:在达到递归限制时返回状态
扩展示例:在达到递归限制时返回状态
与其抛出
GraphRecursionError,我们可以向状态引入一个新键来跟踪到达递归限制所需的剩余步骤数。然后我们可以使用此键来确定是否应该结束运行。LangGraph 实现了特殊的 RemainingSteps 注解。在底层,它创建一个 ManagedValue 通道——一个在我们图运行期间存在且不再存在的状态通道。扩展示例:带有分支的循环
扩展示例:带有分支的循环
为了更好地理解递归限制如何工作,让我们考虑一个更复杂的示例。下面我们实现一个循环,但一步扇出到两个节点:
此图看起来很复杂,但可以概念化为 超级步骤 的循环:但是,如果我们将递归限制设置为四,我们只完成一圈,因为每圈是四个超级步骤:

- 节点 A
- 节点 B
- 节点 C 和 D
- 节点 A
- …
异步
使用异步编程范式可以在并发运行 IO 绑定 代码时产生显著的性能提升(例如,并发 API 请求到聊天模型提供商)。 要将图的sync 实现转换为 async 实现,您需要:
- 更新
nodes使用async def而不是def。 - 更新代码内部以适当使用
await。 - 根据需要调用图使用
.ainvoke或.astream。
sync 方法的 async 变体,因此将 sync 图升级为 async 图通常很快。
见下方示例。为了演示底层 LLM 的异步调用,我们将包含一个聊天模型:
- OpenAI
- Anthropic
- Azure
- Google Gemini
- AWS Bedrock
- HuggingFace
使用 Command 结合控制流和状态更新
结合控制流(边)和状态更新(节点)可能很有用。例如,您可能希望 同时 执行状态更新 并 决定下一个节点去哪里。LangGraph 提供了一种方法,即从节点函数返回 Command 对象:
StateGraph。请注意,图没有 条件边 用于路由!这是因为控制流是在 node_a 中使用 Command 定义的。

导航到父图中的节点
如果您正在使用 子图,您可能希望从子图中的节点导航到不同的子图(即父图中的不同节点)。为此,您可以在Command 中指定 graph=Command.PARENT:
nodeA 更改为我们将其作为子图添加到父图中的单节点图。
在工具中使用
一个常见的用例是从工具内部更新图状态。例如,在客户支持应用中,您可能希望在对话开始时根据账户号或 ID 查找客户信息。要从工具更新图状态,您可以从工具返回Command(update={"my_custom_key": "foo", "messages": [...]}):
Command 更新状态的工具,我们建议使用预构建的 ToolNode,它自动处理工具返回 Command 对象并将它们传播到图状态。如果您正在编写调用工具的自定义节点,则需要手动传播工具返回的 Command 对象作为节点的更新。
可视化您的图
在此我们演示如何可视化您创建的图。 您可以可视化任何任意 Graph,包括 StateGraph。 让我们画分形图吧 :)。Mermaid
我们还可以将图类转换为 Mermaid 语法。PNG
如果更喜欢,我们可以将图渲染为.png。这里有三种选择:
- 使用 Mermaid.ink API(不需要额外的包)
- 使用 Mermaid + Pyppeteer(需要
pip install pyppeteer) - 使用 graphviz(需要
pip install graphviz)
draw_mermaid_png() 使用 Mermaid.Ink 的 API 生成图表。

Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

