Documentation Index
Fetch the complete documentation index at: https://nvd-54.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
图
LangGraph 的核心是将智能体工作流建模为图。你使用三个关键组件来定义智能体的行为:-
状态:一个共享的数据结构,表示应用程序的当前快照。它可以是任何数据类型,但通常使用共享状态模式来定义。 -
节点:编码智能体逻辑的函数。它们接收当前状态作为输入,执行某些计算或副作用,并返回更新后的状态。 -
边:根据当前状态确定下一个要执行的节点的函数。它们可以是条件分支或固定转换。
节点和边,你可以创建复杂的、带循环的工作流,随着时间推移演化状态。然而,真正的力量来自于 LangGraph 管理状态的方式。
需要强调的是:节点和边只不过是函数——它们可以包含大语言模型(LLM)或仅仅是普通代码。
简而言之:节点执行工作,边告诉接下来做什么。
LangGraph 的底层图算法使用消息传递来定义通用程序。当一个节点完成其操作时,它沿着一条或多条边向其他节点发送消息。这些接收节点随后执行它们的函数,将结果消息传递给下一组节点,如此持续。受 Google 的 Pregel 系统的启发,程序以离散的”超级步骤”进行。
超级步骤可以被视为对图节点的单次迭代。并行运行的节点属于同一超级步骤,而顺序运行的节点属于不同的超级步骤。在图执行开始时,所有节点处于 inactive 状态。当节点在其任何传入边(或”通道”)上接收到新消息(状态)时,它变为 active。活跃节点随后运行其函数并返回更新。在每个超级步骤结束时,没有传入消息的节点通过将自己标记为 inactive 来投票 halt。当所有节点都处于 inactive 状态且没有消息在传输中时,图执行终止。
StateGraph
StateGraph 类是要使用的主要图类。它由用户定义的 State 对象参数化。
编译你的图
要构建图,首先定义状态,然后添加节点和边,最后编译它。编译图到底是什么,为什么需要它? 编译是一个相当简单的步骤。它对图的结构提供一些基本检查(没有孤立节点等)。这也是你可以指定运行时参数(如检查点器和断点)的地方。你只需调用.compile 方法来编译图:
状态
定义图时的第一件事是定义图的状态。状态由图的模式以及归约器函数组成,归约器指定如何将更新应用到状态。状态的模式将是图中所有节点和边的输入模式。你使用 StateSchema 类定义状态,它接受任何标准模式(如 Zod)用于单个字段,以及特殊值类型如 ReducedValue 和 MessagesValue。所有节点将发出对状态的更新,然后使用指定的归约器函数来应用这些更新。
模式
指定图模式的主要方式是使用StateSchema 类。模式中的每个字段可以是:
- 标准模式用于简单字段(成为更新时覆盖的”最后值”通道)
ReducedValue用于需要自定义归约器函数的字段(当节点并行运行时)MessagesValue用于聊天消息列表(预构建了消息感知的归约器)UntrackedValue用于不应被检查点化的瞬态状态
多模式
通常,所有图节点使用单一模式通信。这意味着它们将读取和写入相同的状态通道。但在某些情况下,我们需要更多控制:- 内部节点可以传递不需要在图的输入/输出中的信息。
- 我们可能还想为图使用不同的输入/输出模式。例如,输出可能只包含一个相关的输出键。
PrivateState。
也可以为图定义显式的输入和输出模式。在这些情况下,我们定义一个包含_所有_与图操作相关的键的”内部”模式。但是,我们还定义了input和output模式,它们是”内部”模式的子集,用于约束图的输入和输出。有关更多详细信息,请参阅定义输入和输出模式。
让我们看一个例子:
-
We pass
stateas the input schema tonode1. But, we write out tofoo, a channel inOverallState. How can we write out to a state channel that is not included in the input schema? This is because a node can write to any state channel in the graph state. The graph state is the union of the state channels defined at initialization, which includesOverallStateand the filtersInputStateandOutputState. -
We initialize the graph with
StateGraph({ state: OverallState, input: InputState, output: OutputState }). How can we write toPrivateStateinnode2? How does the graph gain access to this schema if it was not passed in theStateGraphinitialization? We can do this because nodes can also declare additional state channels as long as the state schema definition exists. In this case, thePrivateStateschema is defined, so we can addbaras a new state channel in the graph and write to it.
归约器
归约器是理解节点更新如何应用到状态的关键。状态中的每个键都有自己独立的归约器函数。如果没有显式指定归约器函数,则假定对该键的所有更新都应覆盖它。有几种不同类型的归约器,从默认类型的归约器开始:
默认归约器
以下两个示例展示如何使用默认归约器:Example A
{ foo: 1, bar: ["hi"] }. Let’s then assume the first Node returns { foo: 2 }. This is treated as an update to the state. Notice that the Node does not need to return the whole State schema - just an update. After applying this update, the State would then be { foo: 2, bar: ["hi"] }. If the second node returns { bar: ["bye"] } then the State would then be { foo: 2, bar: ["bye"] }
Example B
ReducedValue to specify a reducer function for the second key (bar). Note that the first key remains unchanged. Let’s assume the input to the graph is { foo: 1, bar: ["hi"] }. Let’s then assume the first Node returns { foo: 2 }. This is treated as an update to the state. Notice that the Node does not need to return the whole State schema - just an update. After applying this update, the State would then be { foo: 2, bar: ["hi"] }. If the second node returns { bar: ["bye"] } then the State would then be { foo: 2, bar: ["hi", "bye"] }. Notice here that the bar key is updated by concatenating the two arrays together.
Untracked values
UntrackedValue is used for state fields that should exist during graph execution but should never be checkpointed. When a graph resumes from a checkpoint, untracked values will be reset to their initial state (or be unavailable).
This is useful for:
- Database connections that can’t be serialized
- Temporary caches that should be rebuilt on resume
- Large objects you don’t want to persist
- Runtime-only configuration that should be passed fresh each time
- During execution: Values are stored and accessible like normal state
- On checkpoint: Untracked values are excluded from the checkpoint data
- On resume: Untracked values start fresh (empty or with their default value)
- With
guard: true(default): Throws error if multiple nodes write in the same step - With
guard: false: Multiple writes allowed, last value wins
Type utilities
LangGraph provides several type utilities for better TypeScript type safety when defining nodes and conditional edges.GraphNode
Use GraphNode to type node functions defined outside the graph builder:
State.Node shorthand
Each StateSchema instance has a Node property that provides a shorthand for typing nodes:
ConditionalEdgeRouter
Use ConditionalEdgeRouter for routing functions in conditional edges (no state updates, just routing):
StateSchema.State and StateSchema.Update
Extract the state and update types from a schema for use in custom type definitions:
Working with messages in graph state
Why use messages?
Most modern LLM providers have a chat model interface that accepts a list of messages as input. LangChain’s chat model interface in particular accepts a list of message objects as inputs. These messages come in a variety of forms such asHumanMessage (user input) or AIMessage (LLM response).
To read more about what message objects are, please refer to the Messages conceptual guide.
Using messages in your graph
In many cases, it is helpful to store prior conversation history as a list of messages in your graph state. To do so, you can use the prebuiltMessagesValue which provides a message-aware reducer that handles message IDs, updates, and deletions automatically.
The MessagesValue reducer is vital to telling the graph how to update the list of Message objects in the state with each state update. If you don’t specify a reducer, every state update will overwrite the list of messages with the most recently provided value. MessagesValue handles this correctly: for brand new messages, it appends to the existing list, and for existing messages (matched by ID), it updates them in place.
Serialization
In addition to keeping track of message IDs,MessagesValue will also try to deserialize messages into LangChain Message objects whenever a state update is received on the messages channel. This allows sending graph inputs / state updates in the following format:
Messages when using MessagesValue, you should use dot notation to access message attributes, like state.messages.at(-1).content. Below is an example of a graph that uses MessagesValue:
messages field is defined as a MessagesValue which is a list of BaseMessage objects with a built-in reducer. Typically, there is more state to track than just messages, so we see people extend this state and add more fields, like:
节点
在 LangGraph 中,节点通常是接受以下参数的函数(同步或异步):state——图的状态config——一个RunnableConfig对象,包含thread_id等配置信息和tags等追踪信息
addNode method. For better type safety, use the GraphNode type utility or State.Node to type your node functions:
RunnableLambda, which add batch and async support to your function, along with native tracing and debugging.
If you add a node to a graph without specifying a name, it will be given a default name equivalent to the function name.
START node
The START Node is a special node that represents the node that sends user input to the graph. The main purpose for referencing this node is to determine which nodes should be called first.
END node
The END Node is a special node that represents a terminal node. This node is referenced when you want to denote which edges have no actions after they are done.
Node caching
LangGraph supports caching of tasks/nodes based on the input to the node. To use caching:- Specify a cache when compiling a graph (or specifying an entrypoint)
- Specify a cache policy for nodes. Each cache policy supports:
keyFunc, which is used to generate a cache key based on the input to a node.ttl, the time to live for the cache in seconds. If not specified, the cache will never expire.
边
边定义了逻辑如何路由以及图如何决定停止。这是智能体工作方式和不同节点之间通信方式的重要组成部分。有几种关键类型的边:- 普通边:直接从一个节点到下一个节点。
- 条件边:调用函数来确定接下来去哪个节点。
- 入口点:当用户输入到达时,首先调用哪个节点。
- 条件入口点:调用函数来确定用户输入到达时首先调用哪个节点。
Normal edges
If you always want to go from node A to node B, you can use theaddEdge method directly.
Conditional edges
If you want to optionally route to one or more edges (or optionally terminate), you can use theaddConditionalEdges method. This method accepts the name of a node and a “routing function” to call after that node is executed:
routingFunction accepts the current state of the graph and returns a value.
By default, the return value routingFunction is used as the name of the node (or list of nodes) to send the state to next. All those nodes will be run in parallel as a part of the next superstep.
You can optionally provide an object that maps the routingFunction’s output to the name of the next node.
Entry point
The entry point is the first node(s) that are run when the graph starts. You can use theaddEdge method from the virtual START node to the first node to execute to specify where to enter the graph.
Conditional entry point
A conditional entry point lets you start at different nodes depending on custom logic. You can useaddConditionalEdges from the virtual START node to accomplish this.
routingFunction’s output to the name of the next node.
Send
By default, Nodes and Edges are defined ahead of time and operate on the same shared state. However, there can be cases where the exact edges are not known ahead of time and/or you may want different versions of State to exist at the same time. A common example of this is with map-reduce design patterns. In this design pattern, a first node may generate a list of objects, and you may want to apply some other node to all those objects. The number of objects may be unknown ahead of time (meaning the number of edges may not be known) and the input State to the downstream Node should be different (one for each generated object).
To support this design pattern, LangGraph supports returning Send objects from conditional edges. Send takes two arguments: first is the name of the node, and second is the state to pass to that node.
Command
Command is a versatile primitive for controlling graph execution. It accepts four parameters:
update: Apply state updates (similar to returning updates from a node).goto: Navigate to specific nodes (similar to conditional edges).graph: Target a parent graph when navigating from subgraphs.resume: Provide a value to resume execution after an interrupt.
Command is used in three contexts:
- Return from nodes: Use
update,goto, andgraphto combine state updates with control flow. - Input to
invokeorstream: Useresumeto continue execution after an interrupt. - Return from tools: Similar to return from nodes, combine state updates and control flow from inside a tool.
Return from nodes
update and goto
Return Command from node functions to update state and route to the next node in a single step:
Command you can also achieve dynamic control flow behavior (identical to conditional edges):
Command when you need to both update state and route to a different node. If you only need to route without updating state, use conditional edges instead.
When using Command in your node functions, you must add the ends parameter when adding the node to specify which nodes it can route to:
Command.
graph
If you are using subgraphs, you can navigate from a node within a subgraph to a different node in the parent graph by specifying graph: Command.PARENT in Command:
Setting
graph to Command.PARENT will navigate to the closest parent graph.When you send updates from a subgraph node to a parent graph node for a key that’s shared by both parent and subgraph state schemas, you must define a reducer for the key you’re updating in the parent graph state.Input to invoke or stream
resume
Use new Command({ resume: ... }) to provide a value and resume graph execution after an interrupt. The value passed to resume becomes the return value of the interrupt() call inside the paused node:
Return from tools
You can returnCommand from tools to update graph state and control flow. Use update to modify state (e.g., saving customer information looked up during a conversation) and goto to route to a specific node after the tool completes.
Refer to Use inside tools for detail.
Graph migrations
LangGraph can easily handle migrations of graph definitions (nodes, edges, and state) even when using a checkpointer to track state.- For threads at the end of the graph (i.e. not interrupted) you can change the entire topology of the graph (i.e. all nodes and edges, remove, add, rename, etc)
- For threads currently interrupted, we support all topology changes other than renaming / removing nodes (as that thread could now be about to enter a node that no longer exists) — if this is a blocker please reach out and we can prioritize a solution.
- For modifying state, we have full backwards and forwards compatibility for adding and removing keys
- State keys that are renamed lose their saved state in existing threads
- State keys whose types change in incompatible ways could currently cause issues in threads with state from before the change — if this is a blocker please reach out and we can prioritize a solution.
Runtime context
When creating a graph, you can specify acontextSchema for runtime context passed to nodes. This is useful for passing
information to nodes that is not part of the graph state. For example, you might want to pass dependencies such as model name or a database connection.
context property.
Recursion limit
The recursion limit sets the maximum number of super-steps the graph can execute during a single execution. Once the limit is reached, LangGraph will raiseGraphRecursionError. By default this value is set to 25 steps. The recursion limit can be set on any graph at runtime, and is passed to invoke/stream via the config object. Importantly, recursionLimit is a standalone config key and should not be passed inside the configurable key as all other user-defined configuration. See the example below:
Accessing and handling the recursion counter
The current step counter is accessible inconfig.metadata.langgraph_step within any node, allowing for proactive recursion handling before hitting the recursion limit. This enables you to implement graceful degradation strategies within your graph logic.
How it works
The step counter is stored inconfig.metadata.langgraph_step. The recursion limit check follows the logic: step > stop where stop = step + recursionLimit + 1. When the limit is exceeded, LangGraph raises a GraphRecursionError.
Accessing the current step counter
You can access the current step counter within any node to monitor execution progress.GraphRecursionError as a safety net:
Proactive vs reactive approaches
There are two main approaches to handling recursion limits: proactive (monitoring within the graph) and reactive (catching errors externally).GraphRecursionError after the limit is exceeded. Design your graph with explicit termination conditions to avoid hitting the limit in the first place.
| Approach | Detection | Handling | Control Flow |
|---|---|---|---|
Reactive (catching GraphRecursionError) | After limit exceeded | Outside graph in try/catch | Graph execution terminated |
- Simple implementation
- No need to modify graph logic
- Centralized error handling
Other available metadata
Along withlanggraph_step, the following metadata is also available in config.metadata:
可视化
能够可视化图通常非常有用,尤其是当图变得更复杂时。LangGraph 附带了几种内置的图可视化方式。有关更多信息,请参阅可视化你的图。可观测性和追踪
要追踪、调试和评估你的智能体,请使用 LangSmith。了解更多
将这些文档连接到 Claude、VSCode 等,通过 MCP 获取实时答案。

