跳到主要内容

内容阅读

从 LangGraph 迁去 Temporal 的人在想什么:框架选型的真实账

Agent阿新聊ai

TL;DR: Grid Dynamics 把一个 LangGraph 深度研究 agent 整体迁到了 Temporal,删掉数千行自建的重试和恢复代码。这个案例的答案不是「LangGraph 不行」,而是他们的系统真正需要的是 durable execution,checkpoint 给不了。选型的正确姿势由此推出:先分清你要的是编排语义还是执行保障,再谈框架;可靠性横评证明各框架差异不大,真正该比的是开发体验、运维成本和退出成本。

选型文的问题是没有迁出样本

市面上的框架选型文有一个共同的盲区:它们都在回答「第一次选该选谁」,很少回答「选完之后后悔的人在想什么」。前者只需要参数表,后者才暴露每个框架的真实边界。这一篇以一次有完整公开记录的迁出案例做解剖样本,把「为什么迁、迁走了什么、留下了什么」拆开看,再回到选型方法本身。

这也是本系列的收尾逻辑:第 01 篇给了「要不要用 LangGraph」的判断线,第 18 篇讲了「确定要迁 1.x」的路径,这一篇补上中间缺的一块:如果复核之后发现该走的不是 LangGraph,该走去哪、怎么判断。三篇合起来,选型闭环才算完整。

一个迁出案例的完整拆解

Grid Dynamics 给一家财富 500 制造商做深度研究 agent(多步检索、交叉验证、长流程),技术栈是 LangGraph 加 Redis 做状态、Kafka 做分发。上线过程中撞到三个问题,每一个都值得单独拆开看,因为它们代表的不是「三个 bug」,而是三类结构性的错位。

第一个:状态过期 bug 难以复现。 agent 拿着 Redis 里的状态继续执行时,外部世界的状态(工单、数据快照)已经变了,bug 出现的时机随机,复现要重建当时的全部环境。

拆开看错位在哪:checkpoint 存的是你的 state,快照边界、恢复语义都做得没问题(第 03 篇拆过它存了什么)。但这个 agent 的流程横跨外部系统,一次深度研究要读工单、查供应商数据、交叉验证,中间隔着人审和长等待。流程走到一半,工单系统里那张单子被人改了,agent 手里的快照还是旧的,接下来的每一步都建立在过期事实上。这不能怪 checkpoint:它承诺的是「你的状态我帮你存取」,从来不承诺「全世界随你的快照一起暂停」。外部世界没有快照功能,这是所有编排框架共同的边界,只是流程越长、跨系统越多,这个边界就越常被撞到。

这类 bug 有个识别特征:复盘时当事人总会说「当时拿到的数据明明是对的」。出现这句话,问题多半不在代码而在时间线:你的状态和外部世界的时间线脱钩了。排查思路也不是盯着代码看,而是把「状态写入的时刻」和「外部数据变更的时刻」摆到同一条时间线上对,脱钩点就藏在两次时间戳之间。预防手段是业务层的:外部数据带版本或时间戳进 state,消费前校验,过期就重新拉取。框架不会替你做这件事,因为「什么算过期」只有业务知道。

第二个:人审等待靠自建重试硬扛。 深度研究流程里有人审环节,等待几小时是常态。LangGraph 的 interrupt 语义是「存档后停」,恢复靠外部再调一次;谁来调、调不到怎么办(服务重启、任务丢失),全部自己写,结果是一套手写的重试与补偿代码。

这个问题的本质要说准:interrupt 本身工作正常,存档、暂停、从断点继续,语义都对。缺的是另一层:在「人批准了」和「恢复被触发」之间,需要一个可靠的等待管理者。审批通过的时刻,得有东西记得「有一个 thread 在等这个事件」,然后发起那次恢复调用;这个管理者自己不能丢任务、不能因服务重启失忆、不能在人批准后重复触发两次恢复。这些是执行保障问题,不是编排问题,LangGraph 的能力清单里本来就没有这一项,用它的团队需要在图外面自己搭。Grid Dynamics 搭了,搭出来的就是后来删掉数千行的那套东西。第 06 篇讲的「人一直不批谁来兜底」是这个问题的另一个侧面,当时给的答案是超时扫描,而超时扫描本身就是这套自建代码的一部分。

第三个:Kafka 扩容竞态。 分发层的扩容让同一任务可能被重复投递,下游没有幂等保护,偶发重复执行。

这个坑严格说和 LangGraph 无关,是自拼技术栈的隐性责任面:你自己选了 Redis 存状态、Kafka 做分发,那么「投递语义」就归你管。Kafka 在扩容触发分区再均衡时,同一条消息可能被重复投递,这是消息系统的正常行为,默认假设就是消费者要幂等。agent 的下游操作没有幂等键,重复执行就这么发生了。它的教训比案例本身更值钱:用编排框架时,你只对图负责;自己拼基础设施时,你对整条链路负责,包括那些你以为「平台会兜住」的部分。三种问题里有两种(第二种的一半和第三种)其实都来自「自拼」这个决定,而不是来自 LangGraph。

迁移到 Temporal 后发生了什么。 工作流代码变成声明式的(RetryPolicy 配置化),worker 无状态可随意扩缩,人审等待用运行时原生的定时器表达,上面那套手写重试删掉数千行。三个问题对着看:第一个没被 Temporal「修好」,外部世界照样不暂停,但恢复时重新拉取外部数据在 Temporal 的活动模型里是自然写法;第二个被定时器和信号原语直接接管,等一周不占任何资源,也不需要自建等待管理者;第三个由平台的投递保障和幂等键接住。他们的结论值得原样记住:要的不是「图编排」,是长流程的执行保障。

checkpoint 和 durable execution 的边界

这两个词经常被混着用,语义差异是这次选型问题的根,逐行过一遍这张表:

能力 LangGraph checkpoint Temporal 类 durable execution
状态存取 每 superstep 快照,可回放 每活动步骤持久化,可恢复
重试 节点内 RetryPolicy,进程内 平台级,进程崩了换机器续跑
等待/定时 interrupt 挂起,靠外部恢复恢复 定时器是运行时原语,等一周不占资源
失败语义 图内处理,图外自建 自动重投、幂等键、事件历史可查
心智模型 编排:流程是图 执行:流程是函数

第一行是粒度和着眼点的差别:checkpoint 以 superstep 为边界为「回放」服务,回放是给调试和追责用的;durable execution 以活动步骤为边界为「恢复」服务,恢复是给业务连续性用的。看起来都是「存下来」,服务对象不同。

第二行是重试的责任层级。LangGraph 的 RetryPolicy 挂在节点上,重试发生在同一个进程里:进程活着,它就有用;进程本身没了,它跟进程一起没了。Temporal 的重试是平台级的,执行某一步的机器崩了,平台在另一台机器上接着跑,重试策略是工作流代码外的配置。区分这两层的试金石很简单:你需要重试对抗的是「模型抽风」,进程内的就够了;需要对抗的是「机器没了」,那必须平台级。

第三行就是 Grid Dynamics 第二个问题的机制解释。interrupt 挂起后不占资源,这点和定时器一样,但它不会自己醒,醒来靠外部调用;定时器是运行时原语,到点自己触发。等待几小时几天的流程,要的就是「到点自己动」。

第四行是失败语义的完整度。图内错误(节点抛异常)LangGraph 有 RetryPolicy 和错误处理(第 12 篇),图外的投递、重复、机器故障,就要自己接平台或自己写。durable execution 引擎的卖点正是把这些收进平台:自动重投、幂等键、完整事件历史,每一步谁在什么时候执行过、失败过几次,平台有账。

第五行是心智模型的差别,也解释了为什么两边团队互相看对方都觉得别扭:把流程想成图的人,关心节点、边、状态怎么合并;把流程想成函数的人,关心函数从哪断的、从哪续上。两种模型都自洽,但它们优化的方向不同。

选型判断浓缩成一句话:流程的结构复杂度决定要不要图,流程的执行保障要求决定要不要 durable execution 引擎。 两个维度各自独立,于是有四种组合。结构和保障要求都低:手写循环。结构复杂、保障要求低(纯线上的短流程编排):LangGraph 或同类。结构简单、保障要求高(固定步骤但跨天跨机器):Temporal 这类,此时上图是浪费。两者都要(多角色决策加跨天恢复):两者不互斥,LangGraph 嵌进 Temporal activity 里用,图管「决策怎么走」,平台管「执行不丢不重」,而不是二选一。

其余替代品的真实定位

社区讨论里反复出现的分工,去掉了厂商宣传的部分。每一条都给两个信号:什么时候该看它,什么时候不该。

先说这张清单的用法:它不是「六选一」的单选题。清单里的大多数条目可以和执行平台组合,比如轻量封装的 agent 加 Temporal 管执行保障,就是 Grid Dynamics 案例推出来的另一种合理答案;组合的判断依据仍然是那两个维度,维度定档之后,每一档内部的「选哪个壳」再按下面的信号筛。

  • CrewAI:角色抽象和上手速度是真实优势,规模化后控制粒度不足。原型期好用,精细流程会被迫下沉。该看它的信号:几天内要一个能跑的多角色演示,验证想法值不值得做。不该看的信号:你已经知道流程要精细控制,原型直接用会做的框架,省一次重写。
  • AutoGen / AG2:多 agent 对话的交互设计最好,0.2 到 0.4 的重写加社区分裂让长期投入者犹豫。该看它的信号:核心需求就是多个 agent 之间来回对话达成结果。不该看的信号:你要长期维护的生产系统,社区分裂期的框架要当风险计价。
  • OpenAI Agents SDK:极简,单 agent 快速交付利器,生态绑定 OpenAI,缺持久化与人审。该看它的信号:单 agent、交付周期以天计、模型生态已经锁定。不该看的信号:需求清单里有断点恢复、人审、多模型切换任何一项,它都缺位。
  • Claude Agent SDK:agentic coding 场景天生契合,循环是黑盒,可见性是交换来的代价。该看它的信号:做的是编码类、计算机操作类任务,Anthropic 的模型栈就是你的选择。不该看的信号:你需要审查和定制 agent 的内部循环,黑盒换来的省事会变成排障时的墙。
  • smolagents / Pydantic AI:反抽象路线,核心小、行为可预测,适合「要 agent 语义但不想扛框架」的团队。该看它的信号:团队有很强的手写能力和调试文化,想要 agent 语义但拒绝黑魔法。不该看的信号:指望框架替你解决持久化、人审这些工程问题,反抽象路线意味着这些都要自己来。
  • 手写循环:50 行起步毫无负担,重试、恢复、并发的复杂度会随需求逐步还回来,Grid Dynamics 迁移前的状态就是终点形态。该看它的信号:第 01 篇四个问题全答否。不该看的信号:四个问题答了两个以上,手写的终点是自研一个不如成熟框架的框架。

把案例翻译成你的检查动作

读完别人的迁移案例,最有价值的产出不是「他们迁了」,而是三个能对着自己项目问的问题。答案不会告诉你该用哪个框架,但会告诉你你的流程长什么样,而流程形状决定框架适配。

第一问:你的流程跨几个外部系统,跨多深? 只读一个数据库、写一个内部表,和「读工单系统、查供应商接口、交叉验证第三方数据」是两种流程。跨系统越多越深,「状态和外部世界的时间线脱钩」的暴露面就越大,Grid Dynamics 第一个问题在你这发生的概率就越高。这和框架无关,和流程有关:跨系统深的流程,不管用什么框架,都要自己设计外部数据的新鲜度校验。

第二问:人审等待的最长时长是多少? 分钟级,interrupt 加个前端轮询就够了;小时到天级,你需要一个可靠的「等待管理者」,要么自建(准备好付出数千行的代价),要么用平台原语。这个问题是编排框架和执行平台分界的最直观判据:等待时长每上一个数量级,「谁来触发恢复」的分量就重一分。

第三问:分发和状态层是谁在管? 用平台,这些是平台的责任;自拼 Redis 加 Kafka,这些是你的责任,包括再均衡时的重复投递。自拼不是错,很多团队有自己的理由,错的是自拼时还按「平台会兜底」的心智假设安全边界。

三个问题都指向同一种组合的必要性:结构复杂(需要图)且等待长、保障要求高(需要执行平台)。真落到这一格,嵌套方案的边界怎么划值得提前想:放进图里的是「决策」,哪些分支、要不要重试、结果怎么合并;放进 activity 里的是「一段确定的执行」,调一次模型、查一次库、发一次通知。判断一个东西该放哪边的试金石:它失败之后「换个方式再试」是不是业务语义的一部分?是,放图里;失败后只存在「重试还是告警」,放 activity 里。

一个操作化的选型流程

前面所有分析可以收成一套五步流程,一次选型半天到一天能走完:

  1. 列流程特征。 就是上面三问加上第 01 篇的四个判断线问题,全部写成一句话答案。不写「大概」「可能」,答案模糊说明还没到选型阶段,先补运行数据。
  2. 按两个维度定位。 结构复杂度(要不要图)和保障要求(要不要平台)各自落档,四种组合里找到自己那格。多数项目走到这一步,答案已经收敛到一两个候选。
  3. 候选进短名单,最多三个。 用上面的替代品定位清单排除明显不适配的,注意组合形态也算候选:轻量封装加执行平台,本身就是一个合法答案。
  4. 每个候选做一次下午级验证。 拿同一个真实的小流程(含一次人为中断、一次人为崩溃),分别立起来。验证的不是功能清单,是卡点:团队在哪一步卡住、报错能不能看懂、恢复流程顺不顺。第 01 篇说过,一下午暴露的问题比两周会议多。
  5. 按三件事打分,写进文档。 开发体验、运维账单、退出成本,各给一段结论,把「为什么选它」和「将来怎么退出」一起写下。退出方案写在选型文档里听起来多余,它是唯一能在半年后救你的部分。

这套流程刻意没有「看排行榜」这一步。横评结论已经说明成功率比不出高下,排行榜比的是功能勾选框,而功能勾选框的差别远小于三件事的差别。

社区有团队做过大量同任务跨框架的可靠性对比,一个稳定结论是:任务成功率在成熟框架之间没有显著差异。这很反直觉,但想通了就释然:框架的执行核心都是「模型加工具循环」,任务成败的瓶颈在模型能力和任务难度,框架只是把循环跑起来的壳,壳与壳之间的成功率差异被模型侧的方差淹没了。所以「哪个框架成功率高」是个伪问题,横评表里这一列可以忽略。

真正拉开长期成本的是三件事,每一件都能变成具体问题问出来:

  1. 开发体验。 改一个分支逻辑要动几处?调试要看几层数据?新人几天能产出?这三个问题的答案在不同框架间能差几倍,而且天天都在付。量法也简单:拿一个真实的小需求,让团队里最不熟这个框架的人做一遍,记下时间。
  2. 运维账单。 自托管要养哪些组件?SaaS 的席位和用量怎么涨?LangGraph 的账在第 17 篇算过:checkpointer 要真数据库、表要清理、要有人懂这套栈;Temporal 自托管更重,SaaS 则按用量计价。把「一年后这套系统需要几个人维护」想清楚,比比功能清单有用。
  3. 退出成本。 业务代码和框架 API 的耦合面积有多大?checkpoint 数据迁得走吗?这是最常被忽略的一项,Grid Dynamics 案例的反面教材价值在这里:他们的业务逻辑和自建的 Redis/Kafka 层耦合极深,任何方向的迁移都是大手术。降低退出成本的办法是老办法:业务逻辑写在框架外的普通函数里,框架只管编排,换编排器时业务函数原样搬走。

如果决定换引擎:迁法之争

选型流程走到「换」这个结论后,还有一个工程决策:原地迁,还是旁边重写。Grid Dynamics 选的是整体迁移,一次换到位,删掉数千行自建代码。这个选择的成立条件是「已经确定不回头」:技术方向在团队内已经有共识,评估期结束,旧路径继续投入只会加深耦合。

评估还没收敛时的更稳做法是并行重写:旧系统继续服务线上,新引擎旁路立一个最小实现,跑影子流量或历史数据回放,两边结果对照。多花的机器钱买的是「决策证据」:对照跑两周攒下的差异清单,比任何评估会议都接近真相。代价要想清楚是双份的:两套代码都要维护,影子链路的故障也要人管,所以并行期要有截止日期,无限期的「再跑跑看」是决策瘫痪的技术伪装。

迁移顺序上,无论原地迁还是重写,都和第 18 篇的逐子图策略同构:先迁没有人审、没有长等待的短路径(验证基本的连通和部署),再迁长流程(验证恢复语义),最后切流量。每一步都有可验证的完成标志,避免「迁了三个月还在双跑」的悬置状态。

两个方向都是真的

公平地收尾:迁出 LangGraph 的故事是真的,迁进去的故事也是真的。Octomind 因为「需求变具体后框架崩」离开了 LangChain 系;同样多的团队在手写重试和恢复写到第三个月时回到了框架。这两类故事不矛盾,把它们放在一起看,结论自然出来:前者是「要保障的人误入了编排框架」,后者是「硬扛执行保障的人最终承认这层该买不该造」。方向相反,错误同源:没有先分清自己缺的是编排语义还是执行保障。

顺便给一个读这类案例的方法:别盯着结论看,看三样东西。看删掉了什么(删掉的自建代码就是那层「不该造」的执行保障);看留下了什么(留下来的部分说明框架那层本来就没坏);看他们没换什么(模型、业务逻辑、数据层都没动,动的只有编排与保障的分界)。会看这三样,任何一篇迁移文都能读出选型信息;只会看结论,每篇迁移文都只是一句站队。

Klarna 的案例则提醒第三种失败:框架选对了,把「能自动化」当成「该自动化」照样翻车。它是选型问题吗?不是,它是边界划分问题,但它和选型共享同一个教训:工具解决「能不能」,判断解决「该不该」,两个问题别互相冒充。

所以这篇的收尾不是推荐谁,而是把成本类型摆平:工具选型决定不了项目成败,它只决定你付成本的方式。用编排框架,付抽象税(概念学习加调试复杂度);用执行平台,付运维税(组件和账单);手写,付手写税(重试恢复并发的代码随需求增长)。三种税都合法,逃不掉,能选的只是税种和税率。选型的全部要领,是照着你的任务形状交税,别照着别人的账单交。

三种常见误读

这个案例在社区里流传时,产生了三种偏离原意的读法,值得提前消毒。

误读一:「LangGraph 做不了生产。」 Grid Dynamics 的迁出被当成质量判决书转发时,丢掉了最重要的上下文:他们的问题是保障层缺位,而不是编排层失效;图本身跑了几个月,最后删掉的数千行代码也是「他们自己写的保障层」,不是 LangGraph 的代码。同一个案例里,第 01 篇引的 Uber 用同款框架在生产跑了大量专用 agent。同一个工具在两个案例里命运相反,变量是任务形状,这恰好证明选型要看流程,不要看案例结论。

误读二:「Temporal 是 LangGraph 的替代品。」 这是维度混淆:Temporal 不提供 agent 编排语义,没有图、没有 reducer、没有人审的 interrupt 原语;LangGraph 不提供执行保障,没有进程级重投、没有原生定时器。两个产品的能力集合交集很小,所谓「迁移」迁的不是功能,是关注点:Grid Dynamics 迁走之后,多 agent 决策编排那部分需求要么变简单了,要么用别的方式补。把「替代品」这个词用在它们身上,会诱导出「选一个就行」的错误心智。

误读三:「所以新项目都该直接上 Temporal。」 这是从一个极端摆到另一个极端。多数 agent 项目的真实形态是:流程几步到十几步、人审分钟级、失败重跑一遍的成本可接受。这个形态落在「结构复杂、保障要求低」的格子里,上图框架刚好,上执行平台是把重运维税提前预支给一个还不存在的需求。执行平台的运维成本从第一天就在交,收益却要等流程真的长到跨天跨机器才出现,这个结构和第 01 篇批评的「第一天就上 LangGraph」完全对称,只是方向相反。

延伸阅读


原文出处:91ai / LangGraph 生产实战系列

评论

0
登录后可以参与评论和讨论。

还没有评论

欢迎留下第一条评论,帮助这篇内容更快形成讨论。