LangGraph 子图为空
LangGraph 根图消息正常,子图 DeltaChannel 却为空。检查继承的 saver、明确 namespace 与 1.2.15 修复,避免空读取覆盖旧快照。
LangGraph 的根图已经读到完整消息,查询子图 namespace 却得到空列表;同一个子图里的普通列表字段又正常。如果空的是 DeltaChannel,先检查读取快照时有没有使用父图传入的 checkpointer,不要把空响应直接当成没有对话。
这一问题涉及旧 1.2.x 的子图状态与历史读取,已有 1.2.1、1.2.10 路径的反馈。已核对的正式 1.2.15 会把读取入口解析出的 saver 传给状态重建,也修正相关状态更新路径。
根图与子图需要分开观察
DeltaChannel 不一定在每个 checkpoint 的 channel_values 里保存完整值。它可能需要 saver 沿祖先查找快照和写入,再重建当前状态。普通聚合列表已有完整值时,不需要经过同样的重放路径。
因此,同一次运行中可能出现根图消息正常、子图 DeltaChannel 为空、子图普通字段正常的组合。HTTP 200 和合法 JSON 只能说明接口返回成功,不能证明消息历史完整。
核对实际 thread、子图 checkpoint_ns、checkpoint 标识及 channel 定义。优先使用运行或历史状态给出的子图配置,避免按节点名称猜一个 namespace。配置首先缺少 thread 时,应先处理checkpointer 的运行标识,不能用新 thread 掩盖旧历史读取失败。
读取入口拿到了 saver,重建却没用它
子图可以继承父图的 checkpointer。运行与公共状态入口能从配置解析出这份 saver,子图对象自身却可能没有独立的 saver,或只是用 checkpointer=True 表示按 thread 持久化。
旧重建代码重新查看子图自己的 self.checkpointer,没有使用入口已经解析出的实例。没有 saver,DeltaChannel 的祖先重放被跳过,字段便可能从缺失值初始化为空。
这也影响 get_state(subgraphs=True) 在中断期间附带的子图状态,以及同步、异步的状态历史。不能因为只查一次根图正常,就认为运行检查界面已经覆盖所有子图。
先避免把空读取写成新快照
只读为空不一定意味着磁盘数据已丢失,但在旧路径上继续 update_state,可能把这个空状态带入新的持久化快照。到达 DeltaChannel 的快照频率时,新快照可能只剩本次手动更新,先前消息不再出现在重建结果中。
发现这种组合后,先保留 checkpoint 数据与运行配置,在受控副本核对,再安排包含修复的版本。不要通过多写一次消息、降低快照频率或反复编辑子图来碰运气;快照尚未触发,只是没有暴露这一步的影响。
正式 1.2.15 让公共读取和更新入口使用一致的 saver 解析与 namespace 规则。需要重放的 channel 没有 saver 或配置时,会明确报错,而不静默伪装成空历史。升级仍需与实际 saver、框架和持久化配置兼容。
哪些空状态本来就合理
checkpointer=False 的子图没有这份持久化历史。子图已经完成后,subgraphs=True 也可能没有待运行任务可附带状态。这些情况与“仍有子图历史,却只把 DeltaChannel 读空”不同,不能承诺升级后每个任务都出现状态对象。
验收要覆盖明确 namespace 的同步、异步状态与历史读取,以及中断中的递归子图状态。确认 DeltaChannel 与相同更新的普通字段都符合实际历史,再在受控环境检查子图更新没有覆盖此前内容。已经写下的错误快照需要结合可信备份和业务记录恢复;升级不会自动猜出被覆盖的消息。


