LangGraph 工程化架构:类型、状态、流式通信与可观测性

Agent Demo 能调用模型,并不意味着系统已经具备可维护性。到了第三个功能、第二位开发者加入时,真正拖慢迭代的,往往是隐含的路由规则、漂移的消息格式和缺乏证据的失败现场。
原文提出的核心原则很明确:把 AI 系统的结构声明出来。流程是图,工具输入输出是 Schema,消息有契约,执行有 Trace,模型变化有评测。本文按这条主线整理工程架构,而不是把某一组框架当成唯一答案。
1. 先区分执行图与知识图谱
这里讨论的图是执行图:节点负责处理任务,边负责决定下一步,状态记录执行进展。Graph RAG 和知识图谱则主要描述检索数据之间的关系。知识图谱可以成为某个工具节点的数据源,两者不是同一个层面的设计。
一个支持工单助手可能这样运行:分类工单、选择直接回答或检索、生成草稿、等待人工批准,然后发送。将这些分支声明成图后,开发者可以查看路由和节点输入,而不必从多个处理函数中猜出完整流程。

2. 每一层都有自己的职责
| 层次 | 原文选型 | 主要职责 |
|---|---|---|
| Agent | Pydantic AI | 工具参数、结构化输出、依赖对象与模型适配 |
| 编排 | LangGraph | 状态、节点、条件路由与检查点 |
| 通信 | chanx | 类型化 WebSocket 消息及契约生成 |
| 追踪 | OpenTelemetry | 连接请求、图节点与模型调用 |
| 确定性测试 | pytest 与模拟模型响应 | 检查解析、路由、工具和流式处理 |
| 行为回归 | 真实模型评测 | 检查提示词和模型升级后的行为 |
| 业务后端 | 独立模块或服务 | 用户、权限、工单、业务记录 |
| 任务执行 | Worker | 驱动长任务并处理进程生命周期 |
这是原作者的技术组合。chanx 也是原作者维护的项目,应视作一种可选实现;Python 的生态优势不代表其他语言无法完成同类架构。
3. 类型约束能把一部分错误挡在边界
工具参数声明为模型以后,错误类型可以在执行前被验证。例如检索工具要求 ticket_id 和查询文本,服务端就不应接受模型随意生成的任意对象。
结构化输出也让路由更清楚:读取 decision="search",比判断文本里是否含有"搜索"可靠。但字段符合类型,只能证明格式可接受,不能证明决策正确。权限、资源归属和业务规则仍由服务端验证。
依赖对象也应显式传入,例如当前用户可访问的知识库、工具客户端和请求上下文,减少从全局变量读取配置造成的隐式耦合。
4. 检查点与 Worker 解决不同问题
检查点保存执行状态,支持暂停和恢复。Worker 则决定运行由哪个进程驱动。把任务交给队列,并不自动保证图状态持久;保存图状态,也不自动保证失败任务有人重新调度。
需要一起设计的内容包括:持久化存储、线程或运行标识、任务重投递、超时与取消,以及工具副作用的幂等性。进程在发信之后、保存检查点之前退出时,恢复节点可能重做同一个动作。
"可恢复"应通过故障场景验证,而不只是看到一次成功的本地运行。
5. 流式消息也需要契约
前端至少可能收到进度、答案片段、工具提案、待审批通知、完成和失败等消息。如果两端分别维护 JSON 字段,接口很容易漂移。
原文通过 AsyncAPI 描述 WebSocket 消息,并生成客户端;REST 边界使用 OpenAPI。具体生成工具可以替换,目标是让消息变更能在类型检查或契约测试中被发现。
给用户展示的进度可以是"正在检索知识库""草稿等待审核"等任务状态。它不需要公开模型的内部推理文本。网络重连后还应能从业务记录恢复已完成结果和待审批卡片。
6. 可观测性要连接到同一条请求
OpenTelemetry 的上下文传播机制允许跨服务传递 Trace 信息。实际接入时仍需要配置插桩、导出器和上下文传播,不能假设所有框架天然组成完整链路。
可以从请求、路由、检索、工具和模型调用几个层级建立 Span。每条记录附带模型标识、提示词版本、部署版本和索引版本,方便回答"这次运行与上次有什么不同"。
原文使用自有 Trace 存储并允许向 OTLP 后端导出。自托管便于控制数据,但仍需要考虑保留期限、访问权限和容量。默认采集完整私有提示词通常不是排障的必要条件。

7. 测试与评测各自证明什么
在模型 HTTP 边界返回固定响应,可以让真实解析、工具拼装和路由逻辑继续执行。这类测试适合验证确定性的软件行为。
真实模型评测则检查"模型是否选对工具""是否保留关键条件"等行为。原文选择按需执行,以控制成本;团队也可以把小规模评测放进有预算的发布流程。关键是记录数据集、模型、提示词和判定口径。
建设顺序可以从声明工具和路由开始,再增加检查点、契约、追踪和行为评测。对一个单用户原型,不必一次部署多个服务;当业务规则、扩容和长任务生命周期开始冲突时,再落实服务边界。