ai-memory 的至少一次语义与崩溃恢复:重放收敛机制完整指南
【免费下载链接】ai-memorySolution for long term memory for agent coding CLIs and to facilitate handoff between different agent vendors项目地址: https://gitcode.com/GitHub_Trending/ai/ai-memory
ai-memory 是一个为 AI 编码 Agent(Claude Code、Codex、Gemini CLI 等)提供长期记忆共享的 Rust 系统。它最容易被新手忽略、却最保证可靠性的设计,是至少一次(at-least-once)语义与崩溃恢复:当事件在服务端处理中途丢失响应、进程崩溃时,系统依靠"重放收敛机制"保证记忆宁可重复、绝不丢失,并最终收敛到一致状态。本文用零代码的方式,带你完整看懂这套机制。
一、为什么"至少一次"是记忆系统的必选项 🧠
记忆写入发生在 Agent 与 CLI 之间的生命周期钩子(会话开始、工具调用、会话结束等)中。这条链路上有两类典型故障:
- 事件丢了:钩子脚本发出事件后,服务端已处理但响应丢失,客户端以为失败;
- 处理断了:服务端在"写库完成"之后、"生成会话页面/交接单"之前进程崩溃。
如果追求"恰好一次",系统必须处理海量分布式锁与补偿逻辑;ai-memory 选择了工程上更稳的方案:至少一次 + 幂等去重 + 重放收敛。也就是说——同一事件可以重试、可以重复到达,系统保证:
- 每条记忆至少被完整处理一次(不丢);
- 重复到达的事件不会产生重复观察记录(不重);
- 崩溃后重放时,未完成的部分会被补做,已完成的部分被跳过(收敛)。
ai-memory Web 端项目记忆页面视图
二、事件旅程:本地 Spool 与"幂等密钥" 🔑
崩溃恢复的第一块拼图在客户端。原生ai-memory hook --event ...命令不会傻等服务端,而是把事件先写入本地spool(暂存队列),由独立的hook-drain后台进程负责投递:
- 每个 spool 条目携带一个稳定的幂等密钥(idempotency key),跨所有重试保持不变;
- 会话结束类事件(
stop、pre-compact、session-end)会启动脱离式 drain 助手,投递不依赖某一个关闭钩子存活; - 4xx 是永久性拒绝、不重试;5xx 与网络不可达则入队重试。
关键承诺:即使服务端处理成功但批次响应丢失,客户端重放不会造成重复观察,也不会重复"会话已结束"的下游效果。 细节见 docs/install.md。
三、服务端去重:ingest_keys 表的三种结局 🗂️
服务端用一张项目级去重表ingest_keys接收密钥,表定义在 V33__ingest_keys.sql 中,只有两个核心状态位:seen_at(见到)与completed_at(完成)。
一次带密钥的写库操作(insert_observation_keyed)在同一 SQLite 事务中"认领密钥 + 插入观察记录",只有三种结局:
| 结局 | 含义 | 服务端行为 |
|---|---|---|
| Inserted | 密钥首次出现 | 正常记录观察,继续处理 |
| AlreadyComplete | 密钥已标记完成 | 整个事件确认并跳过,不产生任何副作用 |
| ResumePending | 密钥见过但未完成 | 不重复插观察,只补做下游效果(wiki 提交、交接单等) |
"密钥认领"与"观察写入"原子绑定在同一个事务里,崩溃不可能出现"密钥被认领但记忆没落库"的中间态。密钥本身也有 30 天 TTL,到期后借机清理,防止无限膨胀。
四、崩溃恢复收敛路径:从"重复"到"收敛" 🔄
这是整套机制最精彩的部分。完成标记completed_at只在所有下游效果全部结束后才写入(见 complete_observation_ingest_if_claimed)。在此之前,任何下游效果都是至少一次的:
- 崩溃窗口内:进程在效果中途挂掉,重放时可能重复执行一个已生效的动作(比如再提交一次 wiki)——这是被接受的代价;
- 但绝不会静默丢失剩余效果:重放会沿
ResumePending路径把没做完的补齐; - 重叠重试不竞速:每个"项目 + 密钥"有一把进程内门闩(IngestGates),保证并发的重试不会和原始处理互相踩踏。
路由层对三种结局的处理一目了然:AlreadyComplete直接返回、ResumePending记录"恢复未完成的带密钥事件"后继续补做(router.rs)。
SessionEnd 的特殊收敛:水位线与交接单同事务
会话结束事件最重(要生成会话摘要页、自动交接单、LLM 整合入队)。ai-memory 的约定是:结束水位线与自动交接单在同一个 SQLite 事务里提交——恢复时永远不会只看到"一半"的数据库效果。之后若同一 SessionEnd 被重放:
- 发现事务已完成 → 只补齐中断的 wiki 提交、持久化 LLM 任务与密钥完成标记;
- 不会追加第二条观察、第二张交接单,重放收敛而非叠加。
整体设计叙述可对照 docs/ARCHITECTURE.md 与 docs/design-decisions.md 查看。
五、总结:新手如何判断这套机制在生效 ✅
记住三个"信号"即可验证崩溃恢复是否按设计工作:
- 重放不重复:同一个带密钥事件重放,观察表行数不变(
AlreadyComplete生效); - 补做不遗漏:处理中途崩溃后重放,会话页面、交接单等缺失效果被补齐(
ResumePending生效); - 收敛不叠加:SessionEnd 重放后,交接单只有一张,水位线不重复推进。
一句话概括:ai-memory 用"本地 spool 幂等密钥 + 服务端三态去重 + 完成标记水位线"三层结构,把脆弱的网络与进程环境,收敛成一条'不丢、不重、最终一致'的记忆写入流水线🚀。
【免费下载链接】ai-memorySolution for long term memory for agent coding CLIs and to facilitate handoff between different agent vendors项目地址: https://gitcode.com/GitHub_Trending/ai/ai-memory
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考