Appearance
哪些信息能用于恢复:Memory、RAG、Event Log 与 Crash Recovery
前置:一条 Memory 还能不能信:Provenance、Freshness、Conflict 与 Isolation
核心问题:Crash 之后恢复 Run 时,哪些事实能从 Memory/RAG 找,哪些必须来自 Event Log 或 Runtime durable state?
服务 crash 前已经成功发送一封邮件,但聊天摘要没有记录;Memory 里存着过去用户的偏好,RAG 又检索到邮件模板。恢复时只有 execution record/event log 能回答“邮件是否已经发送”,Memory/RAG 都不能作为强一致事实源。
Mental Model
text
┌─ Memory Store ── learned cross-run guidance ─┐
│ │
Model Context ◀──┼─ Retriever ───── external knowledge evidence ┤
│ │
└──────────────────────────────────────────────┘
Runtime Decision ◀─ RunState / Checkpoint / Event / Execution Record
│
└─ authoritative execution facts把三类数据源放到不同的信任平面最容易理解:
Memory/RAG 主要提高模型“知道什么”;State/Checkpoint/Execution Record 决定程序“已经做了什么”。 前两者可以影响下一步语义决策,但不能替代后者证明副作用是否发生。
Memory vs RAG
Memory 通常来自系统在过去交互中学到、并经过写入策略筛选的跨 Run 信息:
text
user correction
prior run outcome
project-specific learned procedure
agent experience consolidationRAG knowledge base 通常来自独立的外部知识源,例如文档、代码仓库、规范、工单或其他经过 ingestion/index 的语料。两者都可能参与下一轮 Context,但 provenance、更新方式和权限边界不同。
Event Log 与 State Reconstruction
Event Log 记录不可变的执行事实,例如:
text
RUN_STARTED
PLAN_COMPILED
NODE_STARTED
TOOL_CALL_COMMITTED
NODE_SUCCEEDED
APPROVAL_REQUESTED
RUN_RESUMEDReducer 可以按顺序 fold 这些事件重建派生状态;snapshot/checkpoint 用来减少从头重放的成本,但不能改变事件已经提交的事实。
Crash Recovery
真正问题是:
crash 发生时,外部世界可能已经变化,但本地状态可能尚未完成下一次提交。
text
1. call payment API
2. payment succeeds remotely
3. process crashes
4. local DB hasn't recorded success
5. resume
6. call payment API again🔍 源码对照:恢复正确性依赖 Checkpoint;Memory 维护失败不能改变 Turn 结果
精确定位
- 文件:
source/host/runner/turn-memory.ts - Symbol:
runTurnMemory()→runMemoryExtraction() - 深入索引:Code Atlas:07-memory-maintenance
ts
async function runTurnMemory(store, progress, session, ctx, ts, exchange) {
await runMemoryExtraction(store, session, ctx, exchange)
if (!progress) return
try {
progress.recordEpisodeTurn({ ts, ...exchange })
if (progress.pending().length < episodeInterval()) return
await summarizeAndPersistEpisode(progress, store, session, ctx)
} catch {
// maintenance must not fail the user-visible turn
}
}对照理解
- Memory extraction / episode summarization 属于 maintenance path,不是 Turn settlement 的强一致步骤。
- 源码故意吞掉这条维护路径的异常:记忆失败不能把已经完成的用户 Turn 反向判成失败。
- 因此 Memory、Checkpoint、Conversation State 必须分开:Checkpoint 决定能否恢复,Memory 只增强未来决策。
源码说明
把 turn-memory、transcript-mirror、storage 三条路径并排阅读,可以形成本文最重要的边界:Memory 回答“未来推理可能记住什么”,Transcript 回答“交互发生过什么”,Durable State 回答“程序恢复时哪些执行事实仍成立”。RAG 则是从外部知识源检索证据,四者不能互相顶替。
工程边界
这个仓库并不是 RAG 参考实现,因此这里只用它帮助划清 Memory/Transcript/State;Retrieval quality、embedding 和 rerank 不从此案例推导。
Shadow Harness 对照
- Crash recovery 只读取 durable authoritative state + versioned event/execution records。
- Memory/RAG 可补充 Context,但不得把“模型记得曾执行”升级为“副作用已提交”。
验证
让 Memory 中存在“邮件已经发送”的文本,但 ExecutionRecord 显示 outcome unknown;resume 必须服从 execution fact,而不是 memory narrative。
Memory 不应参与强一致恢复
错误:
text
模型从 Memory 记得:"邮件应该已经发过了"
→ Runtime 因此跳过发送RAG 也不能证明 Runtime State
同样,RAG 找到一份文档写着“deployment completed”不能替代真实 execution record。RAG 提供知识证据,不是当前执行事务日志。
因此恢复时的 authority 顺序应当是 execution record / checkpoint / event-derived state → Runtime;执行状态确定之后,再由 Memory / RAG 补充模型下一轮需要的认知信息。
最小实现 / 数据结构
接口层面要避免这种无边界的总管对象:
python
KnowledgeMemoryStateManager这种名字通常意味着 execution state、learned memory 和 retrieval evidence 已经混成一种责任。更清晰的逻辑拆分是:
text
StateStore
├── current Run/Task state
└── optimistic version
CheckpointStore
├── state snapshot
└── next/pending metadata
EventStore
└── immutable runtime events
ExecutionRecordStore
├── tool/node attempts
├── idempotency keys
└── external side-effect commit status
MemoryStore
└── learned cross-run information
Retriever
└── external knowledge evidence在 Shadow Harness 中怎么落地
Shadow Harness 应把恢复依赖拆成 StateStore、CheckpointStore、EventStore、ExecutionRecordStore,把认知信息拆成 MemoryStore 与 Retriever。Runtime resume 只能以执行事实层为 authority;Memory/RAG 由 ContextManager 在恢复状态确定之后按需加载。
Failure Modes
Vector DB = Memory = RAG
症状: 因为都可能使用 embedding/vector store,就用一个 search_everything() 处理 Memory、RAG 和运行状态。
为什么危险: 存储技术相同不代表语义相同:Memory 有 write/freshness/scope,RAG 有 provenance/ranking,Runtime State 要求强一致恢复。
处理: 拆分 MemoryStore、Retriever、StateStore/CheckpointStore;可共享基础设施但不共享 domain contract。
Crash recovery 依赖 transcript
症状: 恢复时读取聊天记录/summary,让模型判断哪些动作已经做过。
为什么危险: Transcript 不是外部副作用 commit log,模型无法证明邮件、支付、PR 是否真正提交。
处理: 恢复从 checkpoint/event/execution record 开始;conversation 只用于后续 Context。
Replay 真实生产副作用
症状: time travel/debug 从旧 checkpoint 重跑时直接调用真实邮件、支付、部署 Tool。
为什么危险: Replay 不天然具备 exactly-once;重新执行真实外部动作会复制副作用。
处理: Replay 默认 stub/mock/sandbox,或要求 Tool replay-safe;明确区分 replay 与 resume。
Event Log 没有 version/schema
症状: 事件 payload 随代码变化却没有 schema_version/event_version。
为什么危险: 旧事件在新 reducer 中可能被错误解释,state reconstruction 静默出错。
处理: 事件 schema 版本化,提供 upcaster/migration 或明确拒绝不兼容版本。
如何验证
| Case | 断言 |
|---|---|
| Vector DB = Memory = RAG | 同一数据库下运行 contract tests,三类接口必须执行不同 scope/consistency 规则。 |
| Crash recovery 依赖 transcript | 副作用成功但 transcript 未追加时 crash,resume 仍能识别已完成动作。 |
| Replay 真实生产副作用 | 对含 send_email 的历史 Run 做 replay,真实 provider 调用次数不得增加。 |
| Event Log 没有 version/schema | 旧 event fixture 在新代码中要么迁移成功,要么明确报 unsupported。 |
关联源码
自测
- 恢复 Run 时,为什么 RAG 文档和 Long-term Memory 不能替代 Event Log / Runtime State?它们分别属于什么证据类型?
- 一条“任务已完成”的 Memory 与最新 execution record 冲突时,哪一个应拥有恢复 authority?