Grok Build · Memory Engineering
Dream 的真实机制
Dream 会把近期 session 日志与现有 MEMORY.md 合并成长期记忆。它由会话结束、可选周期检查或手动命令进入,并受门控与最佳努力锁共同约束。
读懂 Dream 从触发到重建索引的完整链路,能解释 DreamGate、幂等要求、锁竞争和写入失败回滚各自解决什么问题。
TEACHING DIAGRAM
一次 Dream 的状态机
下图是教学化图示。节点名称来自源码,布局与文字说明经过课程化整理。
入口与门控
1. 配置门
MemoryDreamConfig.enabled 默认为 true。子 Agent 会话直接跳过 Dream。
2. 时间门
min_hours 默认为 4。锁文件 mtime 记录上次成功 consolidation 的时间。
3. 会话门
min_sessions 默认为 3。统计上次 consolidation 后修改的 session Markdown,并排除当前会话。
触发事实:默认 check_interval_secs = None,代表不启用周期检查。源码明确支持 session end 和 /dream;只有配置检查间隔后,session actor 才会按周期检查门控。因此不能概括为「所有空闲时必然自动运行」。
crates/codegen/xai-grok-memory/src/dream.rs
crates/codegen/xai-grok-memory/src/dream_lock.rs
crates/codegen/xai-grok-memory/src/storage.rs
crates/codegen/xai-grok-memory/src/index.rs
crates/codegen/xai-grok-config-types/src/memory.rs
crates/codegen/xai-grok-shell/src/session/acp_session_impl/memory_dream.rs
check_dream_gates
maybe_run_dream
锁、幂等与失败恢复
DreamLock 是最佳努力协调
.dream-lock 保存 PID,并用 mtime 兼作上次成功时间。活进程持有且未过期时返回 Ok(None)。死进程或超时锁可被回收。
源码注释明确说明它并非严格互斥。写后复读能降低竞争概率,仍可能有两个进程都认为自己获胜,所以 Dream 必须容忍重复 consolidation。
成功边界决定清理边界
- 模型返回空、NO_REPLY 或无 Markdown 标题时,不写入也不删 session。
- 写 MEMORY.md 失败时调用 rollback(prior) 恢复旧锁状态。
- 写入成功后才清理已读取的 session;5 分钟内仍活跃的文件会跳过。
- 搜索索引只移除实际删掉的路径,再为新 MEMORY.md 重建索引与 embedding。
真实源码快照
crates/codegen/xai-grok-memory/src/dream.rsREAL SOURCE · abridged
pub fn check_dream_gates(
config: &MemoryDreamConfig,
lock: &DreamLock,
sessions_dir: &Path,
current_session_sid8: Option<&str>,
) -> DreamGate {
if !config.enabled { return DreamGate::Disabled; }
// Time gate, then session gate
...
DreamGate::Open { sessions }
}
快照说明:代码保留真实函数签名与返回类型,中间实现以省略号压缩。页面中的状态机 SVG 属于教学化表达,不对应仓库生成的架构图。
课堂练习:定位失败后的系统状态
情境:Dream 已完成模型调用,但写入 MEMORY.md 失败。请回答:锁文件应恢复到什么状态?哪些 session 文件可以删除?索引需要更新吗?再从 execute_dream 的分支给出依据。
Takeaway:Dream 的可靠性来自成功边界设计。门控减少无效调用,最佳努力锁降低并发,幂等承担少量重复风险,回滚与延迟清理保证失败后仍能再次尝试。