学习笔记 · Obsidian
TypeScript 生产化、SDK、测试与迁移
生产应用结构
一个可由 Agent Server 加载的 TypeScript LangGraph 应用通常包含:
my-app/ ├── src/ │ ├── state.ts │ ├── nodes.ts │ ├── tools.ts │ └── agent.ts ├── package.json ├── .env └── langgraph.json
职责建议:
- state.ts:StateSchema、input/output/context schema;
- nodes.ts:无框架副作用的 node 逻辑;
- tools.ts:工具 schema、权限包装与 adapter;
- agent.ts:组图、compile、导出;
- langgraph.json:部署加载入口;
- package.json:锁定运行依赖和 Node engine;
- .env:仅本地开发,不能提交真实 secret。
langgraph.json 关键字段:
- dependencies:通常是当前项目;
- graphs:唯一 graph ID 到导出对象或 factory 的路径;
- env:本地环境变量文件或映射;
- node_version:本地生成器可写入目标 Node 版本;
- dockerfile_lines:需要额外系统库时使用。
graphs 目标可以是已 compiled graph,也可以是构造 graph 的函数。createAgent 返回已编译 LangGraph graph,可直接导出。
生产环境变量由平台 secret 管理注入,不把 API key 直接写进 langgraph.json。
本地 Agent Server
官方 JavaScript 流程:
- 安装 dev dependency
@langchain/langgraph-cli; npm create langgraph创建模板,或对已有项目运行 config 生成器;- 确认 graph 已 export;
- 安装依赖并创建 .env;
npx @langchain/langgraph-cli dev;- 用 Studio、SDK 或 REST 测试。
默认地址:
- API:127.0.0.1:2024;
- API docs:127.0.0.1:2024/docs;
- Studio:带 baseUrl 参数的 smith.langchain.com/studio。
dev server 是内存模式,只适合开发测试。它成功不能证明:
- checkpoint 在重启后恢复;
- 生产数据库 migration 正确;
- 并发 thread 隔离;
- 队列、后台 run 与弹性伸缩;
- 真实网络、代理和超时;
- 密钥与租户授权。
Safari 对 Studio 访问 localhost 有限制,可用 --tunnel。隧道扩大网络暴露面,应只在受控环境使用,并配置 allowed origins。
TypeScript SDK 与协议边界
安装 @langchain/langgraph-sdk 后,Client 可以针对 graph ID 发起 threadless 或 thread run。远程 API 的 SDK stream chunk 是网络协议事件,不等同于进程内 graph.streamEvents 对象。
文档不同页面展示了 messages 与 messages-tuple streamMode。原因是进程内 runtime mode、Agent Streaming Protocol 和 SDK 版本演进并不完全同名。项目要按当前 server 与 SDK 的兼容矩阵锁定:
- server 版本;
- SDK 版本;
- stream mode;
- event/chunk shape;
- resume/interrupt 行为。
不要依据单页示例硬编码 parser。至少用契约测试覆盖 messages、updates、tools、interrupt、error 和 reconnect。
部署选择
LangSmith Cloud 提供托管的持久化、长任务、扩缩容和 Agent Server;快速路径从 GitHub repository 创建 deployment,再通过 Studio 和 API URL 验证。
LangSmith 还提供 hybrid、standalone server、self-hosted control plane 等方案。JavaScript graph 也可以在 Next.js、SvelteKit、Nuxt、Cloudflare Workers 与 Deno Deploy 等平台上使用 Agent Streaming Protocol。
部署选择要评估:
- 数据驻留、合规与加密;
- Node runtime、原生依赖与 edge runtime 限制;
- 持久化 backend 与 retention;
- 长连接、SSE、代理缓冲与 serverless 超时;
- 后台 run、队列和并发隔离;
- 网络出口和模型 provider 限额;
- 观测数据是否允许离开环境;
- 灰度、回滚和 checkpoint 兼容性。
Cloudflare Workers、Deno 和传统 Node 并不是可无差别互换的运行时。文件系统、原生模块、TCP 数据库驱动、process signal 与持续连接能力都要逐平台验证。
Studio 与 Agent Chat UI
Studio
Studio 是连接 Agent Server 的开发和调试界面,可以查看:
- graph node 与中间 State;
- 模型 prompt、tool call 和结果;
- exception 与周围状态;
- token、延迟与 trace;
- thread、assistant 与历史 checkpoint;
- 从历史步骤重跑;
- hot reload 后快速迭代。
Studio 适合诊断,不替代自动化测试。若不允许把本地数据作为 trace 发送到 LangSmith,显式 LANGSMITH_TRACING=false。Studio 连接本地 server 与 trace 上传是两个独立问题。
Agent Chat UI
Agent Chat UI 是开源 Next.js 客户端,提供聊天、tool visualization、interrupt thread、time travel 与 State fork。它可以连接本地或部署后的 Agent Server。
连接参数包括:
- graph ID,即 langgraph.json 的 graphs key;
- Agent Server URL;
- 远程服务所需认证。
hosted UI 适合验证协议。生产产品要自建用户认证、租户隔离、CORS、内容安全、审计与密钥代理;LangSmith API key 不能作为公共浏览器长期 secret。
观测
LangSmith trace 由一系列 run 组成,可用于调试、评价和监控。常见配置:
- LANGSMITH_TRACING;
- LANGSMITH_API_KEY;
- LANGSMITH_PROJECT;
- per-invocation callbacks;
- tags 与 metadata。
metadata 应放稳定但非敏感的排障维度,例如:
- environment;
- applicationVersion;
- featureFlag;
- tenant 的不可逆/受控标识;
- business workflow type。
不要把 access token、密码、完整身份证号、银行卡、模型密钥或未授权正文写入 tag/metadata。
官方展示了使用 langsmith anonymizer 在上传 trace 前对 SSN 格式做替换。实际生产还需要覆盖:
- email、phone、address、payment data;
- message content 和 tool args/results;
- custom stream 与 error stack;
- 结构化字段而非只靠正则;
- 脱敏失败时 fail-closed 或禁用上传的策略。
测试策略
官方 TypeScript 示例使用 Vitest。推荐测试金字塔:
node 单元测试
compiledGraph.nodes[name].invoke 可以直接调用单 node,但会绕过 compile 时的 checkpointer。它适合验证纯 State update、schema、router 和错误分支,不证明 checkpoint/retry/interrupt。
graph 测试
每个 test 创建新 builder、新 MemorySaver 和唯一 thread_id,避免测试互相污染。覆盖:
- happy path;
- conditional edge;
- parallel reducer;
- tool call/ToolMessage 配对;
- timeout/retry/handler;
- interrupt/resume;
- replay 与 checkpoint history。
partial execution
可以用 updateState 预置 checkpoint,并指定 asNode,让执行从某个 successor 开始;再用 interruptAfter 在目标节点后暂停。这适合验证一段大图而不重构 topology。
官方 partial-execution 片段存在 API 形态漂移:正文描述 options.asNode,代码又展示位置参数;还残留 Python None 表述。应以当前 TypeScript 类型为准并让 Vitest 编译。
集成与故障测试
必须补充:
- 真实数据库 checkpointer migration;
- 进程 kill/restart 后恢复;
- 同一 thread 并发写与多个 thread 隔离;
- SSE 断线、重连、代理缓冲;
- provider 429/5xx/timeout;
- SIGTERM drain;
- 旧 checkpoint 在新 graph 上恢复;
- 浏览器端 node 卡片、interrupt 和 custom channel。
checkpoint 是生产兼容 API
LangGraph 不把 in-flight run 固定到启动时的代码版本。部署新 graph 后,旧 thread 恢复时立即运行最新代码。因此 graph code 与已持久化 State 之间存在长期 API 合同。
技术兼容
高风险改动:
- 删除或重命名仍可能作为恢复点的 node;
- 删除或重命名旧 checkpoint 中的 State key;
- 把 optional 字段改 required;
- 缩窄字段类型;
- 新增没有 default 的 required 字段。
edge topology 本身通常不持久化。只要节点名仍存在,新增、删除或重路由 edge 通常可作用于恢复后的最新路径;真正会让 interrupted thread 无法找到入口的是 node rename/removal。
推荐迁移:
- 新字段先 optional/default;
- rename 使用 add -> dual-read/dual-write -> drain -> remove;
- deprecated node 保留一个完整 drain 周期;
- staging 用真实旧 checkpoint getState/time travel 验证;
- 观察 busy/interrupted/error thread 和 node trace;
- 没有活跃旧 thread 后再删除。
LangGraph 本身不维护任意部署环境下的 thread State 搜索索引。在 LangSmith Deployment 可用 thread search;其他环境需依靠自己的索引与 trace。
业务兼容
技术能加载不代表业务语义应该改变。若新流程只应应用于新 thread,在 thread 启动时写入 flowVersion,后续 conditional edge 按版本分支。旧 checkpoint 缺字段时显式落入旧版本默认。
flowVersion 必须在可能分支之前写入。所有旧 thread 完成后再移除兼容路径。
Functional API 的确定性兼容
Functional entrypoint 恢复时从开头 replay,并按调用位置复用 task 与 interrupt 结果。对 in-flight run,以下改动危险:
- 在 resume point 之前插入、删除或重排 task;
- 插入、删除或重排 interrupt;
- 把时间、随机数、网络调用放在 task 外;
- 修改会改变此前控制流的非确定性条件。
安全策略:等待旧 run drain;把新逻辑封装为新 task;或在 langgraph.json 注册新 graph ID,让新 thread 使用新入口。
TypeScript 文档部分段落仍使用 Python @task、@entrypoint 表述。实际兼容单位是 task/entrypoint 函数工厂调用位置,而非 TypeScript 装饰器。
版本演进要点
/oss/javascript/langgraph/changelog-js 会 307 跳转到全 JavaScript/TypeScript changelog。与 LangGraph 直接相关的节点:
- 2025-10:LangGraph v1.0 发布,并提供 v1 migration guide;
- 2026-01:v1.1 引入 StateSchema、Standard Schema、ReducedValue、UntrackedValue、MessagesValue 与类型 helper;旧 Annotation/Zod API 保持兼容;
- 之后的 fault tolerance 与 frontend/event streaming 能力还有各自最低小版本要求,不能只看 “v1”。
升级流程:
- 锁定所有
@langchain/*包,而不是只升一个; - 阅读 changelog 和 migration guide;
- 跑 TypeScript、Vitest、SDK contract test;
- 用旧 checkpoint 做 replay;
- 灰度观察 error、latency、token 与 interrupted thread;
- 保留可回滚 artifact 和兼容 schema。
案例页应该如何使用
官方案例页是从公开资料汇总的使用者索引,不是统一方法论或经过同一标准审计的基准。列出的场景覆盖:
- browser automation:AirTop;
- research/search:Athena、Exa、Harmonic、Morningstar;
- customer support:Cisco、Minimal、Prosper;
- coding/developer productivity:GitLab、Qodo、Replit、Uber、Vodafone;
- finance/legal/healthcare copilot:BlackRock、J.P. Morgan、Definely、Komodo、Vizient 等;
- data extraction:Captide、WebToon;
- logistics/enterprise automation:C.H. Robinson 等。
可提炼的共性是“有状态、多步骤、可观测、需要人工或工具边界”,而不是某公司名称自动证明某种架构适合自己的合规、成本和规模。
上线门禁
- 锁定 Node 与所有 LangChain/LangGraph/SDK 版本。
- langgraph.json 的 graph ID、导出路径和环境变量可在干净环境加载。
- 生产 secret 不进代码、config 或浏览器。
- 真实 checkpointer 完成 migration、备份、恢复和 retention 测试。
- SDK/server stream contract 与 reconnect 通过。
- node、graph、partial、HITL、fault 和旧 checkpoint 测试通过。
- trace 做最小化与脱敏,敏感数据策略经过安全审查。
- node/State rename 走兼容窗口和 in-flight thread 审计。
- serverless/edge 目标验证连接、原生模块、长任务与信号差异。
- Studio/hosted UI 验证不被当成生产认证和性能结论。