Skip to main content
当你使用 LangGraph 构建智能体时,首先需要将其分解为离散的步骤,这些步骤称为 节点。然后,你需要描述每个节点之间的不同决策和转换。最后,通过一个共享的 状态 将节点连接起来,每个节点都可以从中读取和写入。 在这个快速入门指南中,我们将引导你了解使用 LangGraph 构建客户支持邮件智能体的思考过程。

从你想要自动化的流程开始

想象一下,你需要构建一个处理客户支持邮件的 AI 智能体。你的产品团队给你提出了以下需求:
要在 LangGraph 中实现智能体,你通常会遵循五个相同的步骤。

第 1 步:将你的工作流程分解为离散的步骤

首先,识别你流程中的不同步骤。每个步骤将是一个 节点(执行特定任务的函数)。然后,勾勒出这些步骤如何相互连接。 此图中的箭头显示了可能的路径,但实际选择哪条路径的决定发生在每个节点内部。 现在我们已经确定了工作流程中的组件,让我们了解每个节点需要做什么:
  • Read Email:提取和解析邮件内容
  • Classify Intent:使用 LLM 对紧急程度和主题进行分类,然后路由到适当的操作
  • Doc Search:查询你的知识库以获取相关信息
  • Bug Track:在跟踪系统中创建或更新问题
  • Draft Reply:生成适当的回复
  • Human Review:升级到人类智能体以获得批准或处理
  • Send Reply:发送邮件回复
注意,一些节点会做出关于下一步去哪里的决策(Classify Intent、Draft Reply、Human Review),而另一些节点总是执行相同的下一步(Read Email 总是转到 Classify Intent,Doc Search 总是转到 Draft Reply)。

第 2 步:确定每个步骤需要做什么

对于图中的每个节点,确定它代表哪种类型的操作以及它需要哪些上下文才能正常运行。

LLM steps

当你需要理解、分析、生成文本或做出推理决策时使用

Data steps

当你需要从外部来源检索信息时使用

Action steps

当你需要执行外部操作时使用

User input steps

当你需要人工干预时使用

LLM 步骤

当一个步骤需要理解、分析、生成文本或做出推理决策时:
  • 静态上下文(提示词):分类类别、紧急程度定义、响应格式
  • 动态上下文(来自状态):邮件内容、发件人信息
  • 期望结果:结构化分类以确定路由
  • 静态上下文(提示词):语气指南、公司政策、响应模板
  • 动态上下文(来自状态):分类结果、搜索结果、客户历史
  • 期望结果:准备审核的专业邮件响应

数据步骤

当某个步骤需要从外部源检索信息时:
  • 参数:基于意图和主题构建的查询
  • 重试策略:是,对暂时性故障使用指数退避
  • 缓存:可以缓存常见查询以减少 API 调用
  • 参数:来自状态的用户邮件或 ID
  • 重试策略:是,如果不可用则回退到基本信息
  • 缓存:是,带有时效性以平衡新鲜度和性能

操作步骤

当某个步骤需要执行外部操作时:
  • 执行节点时机:批准后(人工或自动)
  • 重试策略:是,对网络问题使用指数退避
  • 不应缓存:每次发送都是唯一操作
  • 执行节点时机:意图为 “bug” 时始终执行
  • 重试策略:是,关键不能丢失 bug 报告
  • 返回:包含在响应中的工单 ID

用户输入步骤

当某个步骤需要人工干预时:
  • 决策上下文:原始邮件、草稿响应、紧急程度、分类
  • 期望输入格式:批准布尔值加上可选的编辑后响应
  • 触发时机:高紧急程度、复杂问题或质量问题

第 3 步:设计你的状态

状态是所有智能体节点可访问的共享 记忆。将其视为智能体在处理过程中记录所有学习和决策的笔记本。

状态中应包含什么?

关于每份数据,问自己以下问题:

Include in state

是否需要跨步骤持久化?如果是,则放入状态。

Don't store

是否可以从其他数据推导出?如果是,按需计算而不是存储在状态中。
为我们的电子邮件智能体,我们需要跟踪:
  • 原始邮件和发件人信息(后期无法重建)
  • 分类结果(多个后续节点需要)
  • 搜索结果和客户数据(重新获取成本高)
  • 草稿回复(需要贯穿审核过程)
  • 执行元数据(用于调试和恢复)

保持状态原始,按需格式化提示词

一个关键原则:你的状态应存储原始数据,而不是格式化文本。在需要时在节点内部格式化提示词。
这种分离意味着:
  • 不同的节点可以根据需要以不同的方式格式化相同的数据
  • 你可以更改提示词模板,而无需修改你的状态模式
  • 调试更清晰——你能确切看到每个节点接收到的数据
  • 你的智能体可以演进,而不会破坏现有状态
让我们定义我们的状态: :::python
::: :::js
::: 注意状态只包含原始数据——没有提示词模板,没有格式化字符串,没有指令。分类输出作为来自 LLM 的单个字典存储。

第 4 步:构建你的节点

:::python 现在我们将每一步实现为一个函数。LangGraph 中的节点只是一个接受当前状态并返回其更新的 Python 函数。 ::: :::js 现在我们将每一步实现为一个函数。LangGraph 中的节点只是一个接受当前状态并返回其更新的 JavaScript 函数。 :::

合理处理错误

不同的错误需要不同的处理策略:
添加重试策略以自动重试网络问题和速率限制。:::python结合 timeout= 以限制每次尝试。参见 容错 的完整生命周期。
::::::js
:::

实现我们的电子邮件智能体节点

我们将每个节点实现为一个简单的函数。记住:节点接收状态、执行工作并返回更新。
:::python
::::::js
:::
:::python
::::::js
:::
:::python
::::::js
:::

第 5 步:连接起来

现在我们将节点连接成一个可工作的图。由于节点自行处理路由决策,我们只需要几个基本边。 要启用 人机协作 与 interrupt(),我们需要使用 检查点 在运行之间保存状态:

Graph compilation code

:::python
::::::js
:::
:::python 图结构很简单,因为路由通过 @[Command] 对象在节点内部发生。每个节点使用类型提示(如 Command[Literal["node1", "node2"]])声明它可以去哪里,使流程显式且可追踪。 ::: :::js 图结构很简单,因为路由通过 Command 对象在节点内部发生。每个节点声明它可以去哪里,使流程显式且可追踪。 :::

尝试运行你的智能体

让我们用需要人工审核的紧急账单问题来运行我们的智能体:
:::python

View example trace

为此示例打开一个公开的 LangSmith 运行。
::::::js
:::
图在遇到 interrupt() 时暂停,将所有内容保存到检查点,然后等待。它可以几天后继续,从上次停止的地方恢复。thread_id 确保此对话的所有状态都一起保存。

总结和下一步

核心洞察

构建这个邮件智能体让我们领悟了 LangGraph 的思维方式:

Break into discrete steps

每个节点专注于做一件事。这种解构使得可以流式输出进度更新、具有可暂停和恢复的持久化执行,以及清晰的调试,因为可以在步骤之间检查状态。

State is shared memory

存储原始数据,而非格式化文本。这允许不同的节点以不同方式使用相同信息。

Nodes are functions

它们接收状态、执行工作并返回更新。当需要做出路由决策时,它们会指定状态更新和下一个目的地。

Errors are part of the flow

持久性故障会重试,LLM 可恢复的错误会带上下文回环,用户可解决的问题会暂停等待输入,意外错误会冒泡用于调试。

Human input is first-class

interrupt() 函数会无限期暂停执行、保存所有状态,并在提供输入时从停止处精确恢复。当与其他节点操作结合时,它必须最先执行。

Graph structure emerges naturally

你定义核心连接,节点自行处理路由逻辑。这使控制流显式且可追踪——通过查看当前节点,你总能理解智能体下一步会做什么。

高级考量

本节探讨了节点粒度设计的权衡。大多数应用可以跳过本节,直接使用上述模式。
你可能会疑惑:为什么不让 Read Email 和 Classify Intent 合并成一个节点?或者为什么将文档搜索与草拟回复分开?答案涉及在弹性和可观测性之间的权衡。弹性考量: LangGraph 的 持久化层 在节点边界创建检查点。当工作流在中断或故障后恢复时,它会从停止执行的节点开头开始。更小的节点意味着更频繁的检查点,这意味着如果出问题,需要重复的工作更少。如果你将多个操作合并到一个大节点中,末尾附近的失败意味着需要从头开始重新执行该节点。我们选择为邮件智能体采用这种拆分的原因:
  • 外部服务的隔离: 文档搜索和 Bug Track 是独立的节点,因为它们调用外部 API。如果搜索服务缓慢或失败,我们希望将其与 LLM 调用隔离。我们可以为这些特定节点添加重试策略,而不会影响其他节点。
  • 中间可见性:将 Classify Intent 作为独立节点,使我们能够检查智能体在采取行动之前 LLM 的决策。这对于调试和监控非常有价值——您可以精确看到何时以及为何智能体路由到人工审核。
  • 不同的故障模式:LLM 调用、数据库查找和发送电子邮件具有不同的重试策略。分离节点允许您独立配置这些策略。
  • 可重用性和测试:更小的节点更容易独立测试并在其他工作流中重用。
另一种有效的方案:您可以将 Read Email 和 Classify Intent 合并成一个节点。这将失去在分类之前检查原始电子邮件的能力,并且在该节点中的任何失败都会重复执行这两个操作。对于大多数应用程序,分离节点的可观察性和调试优势是值得权衡的。应用级考虑:步骤 2 中关于是否缓存搜索结果的讨论是一个应用级决策,而不是 LangGraph 框架功能。您根据特定需求在节点函数中实现缓存——LangGraph 并不规定这一点。性能考虑:更多节点并不意味着执行更慢。LangGraph 默认在后台写入检查点(异步持久化模式),因此您的图可以继续运行而无需等待检查点完成。这意味着您可以频繁地获取检查点,且性能影响最小。如果需要,您可以调整此行为——使用 "exit" 模式仅在完成时检查点,或使用 "sync" 模式阻塞执行直到每个检查点写入完毕。

下一步该怎么做

这是关于使用 LangGraph 构建智能体的入门介绍。您可以在此基础上扩展:

Human-in-the-loop patterns

学习如何在执行前添加工具审批、批量审批和其他模式

Subgraphs

创建子图以处理复杂的多步骤操作

Streaming

添加流式输出以向用户展示实时进度

Observability

使用 LangSmith 添加可观察性以进行调试和监控

Tool Integration

集成更多工具以进行网络搜索、数据库查询和 API 调用

Retry Logic

为失败操作实现具有指数退避的重试逻辑

官方原文:src/oss/langgraph/thinking-in-langgraph.mdx · 非官方翻译,译文由 AI 生成,以英文原文为准。
Last modified on November 3, 2026