雨天小六

读懂 Codex(10.7):多层持久化权威的收益与成本

· 更新于 2026-08-03 · 专栏:读懂 Codex

#Codex#Agent Runtime#软件架构#系统设计

具体问题与边界

如果只保存聊天消息,Runtime 无法恢复 Compact、工具配对和 Turn 设置;如果把 UI Delta、全文索引、 Agent 拓扑和规范历史全塞进同一日志,任何查询或格式升级都会触碰恢复主链。Codex 将 Context History、 Rollout、ThreadStore、State DB 与 AgentGraph 分开,各自回答不同问题。

本节评估多权威边界,不暗示这些存储具有跨系统事务,也不把 Rollback 解释为文件系统回滚。

权威与派生关系

权威问题写入频率/生命周期可否由其他层重建
Context History当前模型下一次应看什么内存、Step/Turn 高频可从有效 Rollout 重建
Rollout JSONL本地会话语义怎样重放追加、跨进程规范恢复输入
ThreadStore如何分页/物化线程历史查询导向可追赶 Rollout/底层存储
State DB线程元数据、索引和查询异步投影部分可从 Rollout 重建
AgentGraphStore父子边、开放/关闭拓扑Agent 生命周期不能从聊天文本可靠推断
外部副作用文件、进程、远端服务事实工具执行时不由会话 Rollback 撤销

正常写入与恢复

规范 Rollout 先写入而查询投影和 AgentGraph 分别更新的持久化流程
图 10.7-1:语义日志、查询投影和拓扑存储按不同一致性推进;恢复时按问题选择权威来源。
  1. Turn 把完整 ResponseItem、上下文变化和 checkpoint 交给 Recorder,而不是持久化 UI Delta。
  2. 专用 Writer Task 按顺序写完整 JSONL 行,Flush/Persist 明确形成可恢复屏障。
  3. State/ThreadStore 在规范写入之后更新元数据和分页投影,允许短暂落后但不能反向改写 Rollout。
  4. Spawn/Fork 同时维护独立 AgentGraph 边;线程内容与拓扑生命周期并不相同。
  5. Resume 读取有效 Rollout,应用 Compact/Rollback replacement,再重建内存 History。
  6. 查询投影落后时可以追赶;规范日志坏尾则按已证明的解析/修复规则处理。

写入“先后”不是全局原子事务。JSONL 已确认而 SQLite 未更新时,系统应把后者视为可修复落后, 而不是重复执行前一条工具副作用。

Python 风格伪代码

async def commit_semantic_records(records: tuple[RolloutRecord, ...], stores: Stores) -> None:
    confirmed = await stores.rollout.append_and_flush(records)
    assert confirmed == len(records)
    await stores.state.project(records)       # may lag; never rewrites rollout

async def restore_thread(thread_id: str, stores: Stores) -> RestoredThread:
    records = await stores.rollout.read_tolerant(thread_id)
    effective = apply_replacement_checkpoints(records)
    history = normalize_prompt_pairs(rebuild_history(effective))
    metadata = await stores.state.read_or_repair(thread_id, records)
    graph = await stores.agent_graph.read_edges(thread_id)
    return RestoredThread(history, metadata, graph)

async def rollback_conversation(turns: int, stores: Stores) -> None:
    replacement = stores.history.without_last_turns(turns)
    await stores.rollout.append_and_flush((RolledBack(replacement),))
    stores.history.replace(replacement)
    # Files and remote effects are deliberately untouched.

伪代码保留规范先写、派生可追赶和 replacement checkpoint;它没有虚构跨 JSONL/SQLite/文件系统事务。

崩溃和不一致

JSONL、State 投影和 AgentGraph 在不同崩溃点留下不一致状态的恢复图
图 10.7-2:先识别哪一层是该问题的权威,再选择追赶、修尾或停止;不能让派生索引覆盖规范历史。
崩溃点已确认事实可能落后恢复
JSONL 行写一半前缀行尾行忽略/修复坏尾,不重放外部工具
Rollout flush 后、State 前新语义记录元数据/索引从 Rollout 追赶投影
Tool 副作用后、Result 前外部世界已变化会话配对重建失败 Result,禁止盲目重跑
Graph 边写入失败子 Thread 可能存在拓扑报告孤立/补边,不从文本猜测
Rollback checkpoint 后新 effective history文件系统恢复新历史,明确外部改动仍在
压缩物化中断原引用/压缩文件之一有效新物化根据 reference index 保留祖先

设计判断

多层存储的收益是让追加恢复、全文查询、压缩归档和 Agent 拓扑独立演进;成本是可观察到的短暂不一致、 迁移工具、保留约束和更复杂的故障诊断。每增加一层都必须写清权威问题和重建方向,否则只是重复状态。

单用户教学 Runtime 可以只用 JSONL,但仍应区分内存 History 和耐久 Rollout;当需要分页、搜索或多 Agent 恢复时,再增加派生层,而不是预先复制 Codex 的全部存储矩阵。

证据与 Mini Codex

生产锚点为 rollout/src/recorder.rsthread-store/src/store.rsstate/src/lib.rsagent-graph-store/src/store.rs 和 reconstruction;8.1—8.34 已覆盖写入、恢复、压缩、Rollback/Fork。

Mini Codex 验证 Writer Task、confirmed prefix、坏尾、Resume 和 replacement checkpoint:

cd examples/mini-codex
uv run pytest -q -k 'writer or resume or rollback or fork'

它没有 SQLite、跨进程锁、压缩引用或 AgentGraph,因此只能证明单 JSONL 权威链。

本节边界

持久化可以恢复 Agent 的语义状态,却不能消除多 Agent 自身的容量与协调成本。下一节讨论这部分代价。 详细源码映射由研究仓库中的配套索引维护。

阅读导航

上一节:10.6 · 下一节:10.8

评论


← 返回文章列表