当您使用 LangGraph 构建 Agent 时,首先将其分解为称为节点的离散步骤。然后,您描述每个节点的 不同决策和转换。最后,通过所有节点可以读取和写入的共享状态将节点连接在一起。 在本演练中,我们将引导您了解使用 LangGraph 构建客户支持电子邮件 Agent 的思维过程。

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

想象您需要构建一个处理客户支持电子邮件的 AI Agent。您的产品团队给您提出了以下要求:
Agent 应该:

- 阅读收到的客户电子邮件
- 按紧急程度和主题分类
- 搜索相关文档以回答问题
- 起草适当的回复
- 将复杂问题升级给人工 Agent
- 在需要时安排后续跟进

需要处理的示例场景:

1. 简单产品问题:"如何重置密码?"
2. 缺陷报告:"导出功能在选择 PDF 格式时崩溃"
3. 紧急计费问题:"我的订阅被收费了两次!"
4. 功能请求:"您能为移动应用添加深色模式吗?"
5. 复杂技术问题:"我们的 API 集成间歇性地出现 504 错误"
要在 LangGraph 中实现 Agent,您通常会遵循相同的五个步骤。

步骤 1:将您的工作流映射为离散步骤

首先识别流程中的不同步骤。每个步骤将成为一个节点(一个执行特定操作的函数)。然后勾勒这些步骤如何相互连接。 此图中的箭头显示了可能的路径,但实际选择哪条路径发生在每个节点内部。 现在我们已经确定了工作流中的组件,让我们了解每个节点需要做什么:
  • 阅读邮件:提取和解析邮件内容
  • 分类意图:使用 LLM 对紧急程度和主题进行分类,然后路由到适当的操作
  • 文档搜索:查询您的知识库以获取相关信息
  • 缺陷跟踪:在跟踪系统中创建或更新问题
  • 起草回复:生成适当的响应
  • 人工审查:升级给人工 Agent 进行批准或处理
  • 发送回复:发送电子邮件回复
请注意,某些节点会决定下一步去哪里(分类意图起草回复人工审查),而其他节点总是进入同一步(阅读邮件 总是进入 分类意图文档搜索 总是进入 起草回复)。

步骤 2:识别每个步骤需要做什么

对于图中的每个节点,确定它代表什么类型的操作以及它需要什么上下文才能正常工作。

LLM 步骤

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

数据步骤

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

操作步骤

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

用户输入步骤

当您需要人工介入时使用

LLM 步骤

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

数据步骤

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

操作步骤

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

用户输入步骤

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

步骤 3:设计您的状态

状态是 Agent 中所有节点可访问的共享记忆。可以将其视为 Agent 在处理过程中用来跟踪所有学习和决策的笔记本。

什么应该放在状态中?

问问自己关于每条数据的这些问题:

包含在状态中

它需要跨步骤持久化吗?如果是,它进入状态。

不要存储

您可以从其他数据派生它吗?如果是,在需要时计算它,而不是将其存储在状态中。
对于我们的邮件 Agent,我们需要跟踪:
  • 原始邮件和发件人信息(以后无法重建这些)
  • 分类结果(多个后续/下游节点需要)
  • 搜索结果和客户数据(重新获取成本很高)
  • 回复草稿(需要通过审查持续存在)
  • 执行元数据(用于调试和恢复)

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

一个关键原则:您的状态应该存储原始数据,而不是格式化文本。在需要时在节点内格式化提示词。
这种分离意味着:
  • 不同的节点可以根据其需求以不同方式格式化相同的数据
  • 您可以更改提示词模板而无需修改状态模式
  • 调试更清晰——您可以看到每个节点收到的确切数据
  • 您的 Agent 可以发展而不会破坏现有状态