LangGraph 分支串数据
LangGraph 编辑历史 checkpoint 后,旧分支也出现编辑值。核对 DeltaChannel 祖先写入与 1.2.15 分支快照隔离,保留已污染历史。
用 LangGraph 的 update_state 编辑历史 checkpoint 后,新的分支已经生成,原来没有接受这次编辑的旧分支却也读出了编辑内容。如果状态字段使用 DeltaChannel,应检查写入是不是落到了两个分支共享的祖先上。
这个问题有 1.2.9 环境反馈,涉及对已被 thread 继续推进过的 checkpoint 做更新。已核对的正式版 1.2.15 包含相应隔离修复;普通完整快照 channel 与 DeltaChannel 的重建路径不同,不能把所有历史编辑异常都归到这里。
固定分支标识再比较
先保存编辑前的旧分支 checkpoint 配置,编辑后仍用这份明确配置重新读取,比较其中是否多了本次编辑的值。只用裸 thread_id 读取,可能拿到最新分支,无法证明旧分支被污染。
同时保留更新入口、checkpoint_id、namespace、channel 定义和应用本身的消息合并规则。检查的是没有沿编辑分支继续运行的旧分支,而不是误选了同一份最新状态。
thread 标识仍需要由应用正确传递并做权限检查,但它不能单独保证同一 thread 内历史分支的写入隔离。若首先缺少运行配置,可按checkpointer 的 thread_id 检查处理。
更新写在共享祖先,其他子分支也会重放
旧 update_state 把相应写入保存在它寻址的 checkpoint 上。DeltaChannel 通过重放祖先写入恢复状态;这个 checkpoint 一旦已有其他子分支,新的编辑就可能被那个分支一起读到。
这与恢复中断时重复保存已加载写入不同。这里即使没有新的 interrupt,也可能在“历史编辑 → 重新读取旧分支”时串入内容,不能只改恢复请求或给列表做事后去重。
也不能简单把写入移到新 checkpoint 就结束。如果新 checkpoint 没有可用快照,祖先重建路径可能看不到它自己的更新。修复需要同时处理写入所属分支与新分支的状态保存。
新分支保存自己的快照
已核对的正式实现会判断所寻址的 checkpoint 是否已不是 thread 的最新位置。对这种历史更新,新 checkpoint 为本次写到的 DeltaChannel 保存快照,不再把这次更新的写入存回已被其他分支引用的祖先。
这样新分支从自己的快照读取编辑,旧分支则没有新增祖先写入可重放。更新最新 checkpoint 的路径保持原有处理;这项修复并不要求每次普通更新都保存全部历史。
旧部署应选择包含隔离修复、与 saver 和应用兼容的正式版本。切换前保留原 checkpoint 数据与应用配置,核对同步 update_state、异步 aupdate_state 和实际批量更新入口;不能只更新 Web 编辑界面就认为持久化路径已变。
历史更新会为被写到的 delta channel 增加一份常规快照,存储成本也要按自己的状态规模核对。不要用删除 checkpoint 或修改私有写入表的方式消除表面重复,这会丢掉判断分支归属所需的记录。
已污染的历史不会自动恢复
隔离修复避免新的错误写入,不会自动清除旧祖先上已经保存的编辑。需要恢复时,应结合可信备份、原始业务记录和明确的分支历史判断;不能因为两个值相同,就把其中一份随意删掉。
消息 reducer 还有自己的限制。使用 _messages_delta_reducer 配合 RemoveMessage(id=REMOVE_ALL_MESSAGES) 的删除表现,不属于这项隔离修复已经解决的范围;不能把“旧分支串入编辑”与“新分支删消息没有生效”合成一个升级保证。
在获准的测试环境中保留原旧分支,编辑历史 checkpoint 后分别读取新分支与旧分支:新分支应包含编辑,旧分支的内容和后续运行不应被改变。还要检查更新最新 checkpoint 的原有流程,不能只以返回了一个新 checkpoint_id 作为隔离通过。


