OpenClaw Dreaming 记忆流水线底层架构:状态分层、证据留痕与检索回流

OpenClaw Dreaming 记忆流水线底层架构:状态分层、证据留痕与检索回流 拆解 OpenClaw Dreaming 的分层记忆流水线看 Agent 如何把会话沉淀为可检索长期上下文。原文链接AI 小老六导语一个能​长期工作的 Agent​麻烦点不在“把对话存下来”。因为聊天记录本身太粗糙里面有临时指令、工具失败、过程性解释、重复确认也有少量会在未来反复有用的偏好、事实和工程判断。把这些内容原封不动塞进长期记忆只会让上下文越来越脏。OpenClaw Dreaming 机制处理的是一类问题怎样让一次次对话先变成可追溯素材再经过候选筛选、稳定归纳和索引构建最后成为未来任务可以调用的长期上下文。这套机制更像一条​后台运行的记忆生产线​。前台会话负责完成当前任务和保留原始事实后台 Dreaming 再把这些事实加工成不同稳定程度的记忆并通过SQLite、全文索引和 ​memory_search接回未来对话。记忆不是一个文件从日志、候选到索引的三层边界OpenClaw 的记忆系统最容易被误解为“一个 Markdown 长期笔记”。实际情况更接近一套分层存储原始会话、加工过程、长期正文、检索索引分别承担不同职责。层级典型位置保存内容核心职责人工介入建议原始输入层tech/sessions/*.jsonl用户消息、助手回复、工具事件、运行时元信息留住当时发生了什么不建议编辑适合作为源日志素材缓冲层memory/.dreams/session-corpus/YYYY-MM-DD.txt从 session 中抽取出的可读片段给 Dreaming 提供当天素材不建议编辑适合排查抽取问题运行审计层memory/.dreams/events.jsonl召回事件、阶段完成事件、写入路径解释某次 Dreaming 是否运行、如何运行只读排查状态信号层daily-ingestion.json、session-ingestion.json、short-term-recall.json、phase-signals.json游标、hash、召回次数、阶段命中支持增量处理、去重和候选晋升判断不建议手改长期正文层memory/YYYY-MM-DD.md、DREAMS.mdLight Sleep、REM Sleep、反思摘要和稳定上下文供人和 Agent 阅读、审计、复用可谨慎编辑保留结构标记检索索引层~/.openclaw/memory/tech.sqlitefiles、chunks、chunks_fts、embedding_cache支撑关键词检索、语义检索和增量索引不应作为最终事实源调用接口层memory_search、memory_get查询和回读能力让未来任务召回相关长期上下文不涉及编辑可以把这套结构拆成三条边界边界关键判断tech/sessions/*.jsonl记录事实但不判断长期价值它回答“当时发生过什么”不回答“什么值得以后记住”。.dreams/*记录生产过程但不是最终知识库它回答“为什么这条内容被召回或处理”不适合直接当长期事实。memory/*.md是可审计正文tech.sqlite是派生索引排查时可以先从索引定位再回到 Markdown 原文看上下文。图从会话日志到长期记忆检索回流的完整链路这张图表达的重点是记忆不会从当前对话直接跳到长期事实。它先经过素材化、候选化、稳定化再进入可检索的长期上下文。Session Ingestion先保留原始上下文再做延迟判断每次用户发起请求时系统首先要解决的是当前任务而不是立刻“学习”。因此用户消息、助手回复、工具调用和运行元信息会先落到 session JSONL。这个阶段只保证一件事原始上下文没有丢。后续 Dreaming 会从这些持续追加的 session 文件里做增量抽取。session-ingestion.json记录每个 session 文件的处理进度例如文件大小、修改时间、内容 hash、行数以及最后处理到的内容行。这样后台任务不需要每次全量扫描也能避免重复抽取同一段会话。素材进入session-corpus后会变成更适合阅读和回溯的行级文本[tech/sessions/...jsonl#L10] Assistant: 我先核对源码里的 dreaming / REM / DEEP 文件和规则再把确认后的结论补进文档。这一行看似普通实际保留了三个关键信息字段示例作用来源文件tech/sessions/...jsonl能定位到哪个 Agent 会话产生了素材行号锚点#L10支持回到原始日志查看上下文角色与内容Assistant: ...、User: ...给后续候选判断提供语义输入图会话日志增量抽取为素材语料的过程这一步的设计取舍很清楚​先完整留痕再延迟判断​。对话里的很多内容只对当前任务有用过早写入长期记忆会制造噪声但完全不留痕又会丢掉后续可能需要归纳的证据。Light 与 REM用稳定性区分候选记忆和长期判断memory/YYYY-MM-DD.md是 Dreaming 输出最直观的位置。它不是单纯按时间堆内容而是在文件内部用阶段标记区分不同稳定程度的信息。区块典型标记内容形态语义定位使用方式Light Sleep到light:endCandidate、confidence、evidence、recalls、status候选记忆表示“可能有用但还要观察”适合近期续接、路径线索、任务偏好补全REM Sleep到rem:endReflections、Possible Lasting Truths更稳定的长期归纳更适合影响后续回答、工具选择和写作规范会话补充普通 Markdown 小节文档链接、用户偏好、任务结果、实现锚点人工或系统补写的稳定上下文适合明确记录可复用事实Light 和 REM 的差别不在格式而在可信度和使用方式。对比维度Light SleepREM Sleep目标捕捉近期可能有价值的线索提炼可长期复用的事实、偏好、模式和约束粒度较细常带路径、原话、任务片段和证据位置较粗通常压缩成稳定判断可信度表达常见confidence、statusstaged、recalls通常来自多次 evidence 或更高置信归纳行为影响应谨慎使用主要补全上下文更容易影响后续回答和任务判断典型用途近期任务续接、排查线索保留用户偏好、长期规则、重复问题模式图候选记忆如何经过证据判断沉淀为 REM 归纳实际阅读日期记忆时比较稳的顺序是先看 REM 得到稳定判断再回到 Light 看证据和来源。这样可以避免把候选层的低置信线索误当成长期事实。图Light 候选更像暂存信号REM 归纳更接近可长期复用的稳定判断Recall State 与 Phase Signal候选为什么会被晋升如果只有 Light 和 REM 两个正文区块系统仍然难以回答一个调试问题为什么这条内容会被保留为什么它会从候选晋升为稳定记忆OpenClaw 用两类状态文件补齐这条证据链。文件处理对象常见字段粒度解决的问题daily-ingestion.jsonmemory/YYYY-MM-DD.md等日期记忆文件mtimeMs、size、path文件级判断每日记忆文件是否变化session-ingestion.jsontech/sessions/*.jsonlmtimeMs、size、contentHash、lineCount、lastContentLine文件级 行级 hash支持持续追加日志的增量抽取short-term-recall.json被检索命中的记忆片段recallCount、recallDays、queryHashes、conceptTags片段级判断哪些片段近期经常被搜索到phase-signals.jsonLight / REM 阶段出现的 memory keylightHits、remHits、更新时间阶段信号级判断候选是否具备晋升趋势​**short-term-recall.json关注的是“它是不是经常被查到”**​phase-signals.json关注的是“它是不是反复被 Dreaming 认为重要”。两者结合候选晋升才更有解释力。图召回热度和阶段信号共同影响候选晋升事件日志则提供运行过程的时间线。典型事件会像这样出现{type:memory.recall.recorded,query:dreaming_sessions:2026-05-09,resultCount:105}{type:memory.dream.completed,phase:light,inlinePath:.../memory/2026-05-10.md}{type:memory.dream.completed,phase:rem,inlinePath:.../memory/2026-05-10.md}这些事件不适合直接用来回答用户问题但很适合排查某个日期有没有被 Dreaming 处理处理到了 Light 还是 REM召回结果数量是否异常最终写入了哪个文件。DREAMS.md 与 tech.sqlite一个讲述变化一个服务检索长期记忆里还有两个容易混淆的对象DREAMS.md和tech.sqlite。DREAMS.md更像系统近期状态的叙事层。它会用更自然的方式记录反复出现的主题、工作流变化、阻塞点和观察结论。它有助于理解“最近系统在关注什么”但不一定适合作为严格事实源。​**tech.sqlite则完全是另一类东西**​。它是从 Markdown 记忆派生出来的检索加速层服务memory_search不应该替代 Markdown 原文做人工审计。对象更像什么主要读者稳定性适合用途DREAMS.md叙事型反思日志人类和 Agent偏解释性理解近期主题、工作流变化、未解决问题memory/YYYY-MM-DD.md结构化长期记忆正文Agent、检索系统、人类更适合长期复用作为长期记忆主路径和可追溯证据tech.sqlite派生索引memory_search、索引器依赖 Markdown 同步快速定位相关片段tech.sqlite的表结构大致承担这些职责表作用与文件系统的关系meta保存索引版本、配置等元信息帮助判断索引结构和运行参数files记录被索引文件的路径、hash、mtime、size判断哪些 Markdown 文件需要同步chunks保存按行切分后的记忆片段、文本和 embedding 信息把长 Markdown 拆成可检索单元chunks_ftsFTS5 全文索引支持关键词、路径、中文片段等全文检索embedding_cache缓存 embedding 结果避免同一文本重复生成 embedding图Markdown 记忆被切分、索引并服务检索这条链路解释了一个关键原则​检索结果只是入口Markdown 原文才是审计依据​。排查记忆内容时应先用索引找到路径和行号再回到memory/*.md看完整上下文。一次真实查询如何穿过记忆系统当用户提出一个与历史任务、偏好或技术结论有关的问题时OpenClaw 并不是只依赖当前上下文。它会在当前任务和历史记忆之间建立一条回路。步骤参与文件或接口发生的事情输出理解当前问题当前用户消息、会话上下文判断问题是否需要历史偏好、任务结果或技术结论明确检索意图召回历史memory_search、tech.sqlite从已索引记忆中找相关片段获得候选历史上下文回读证据memory_get、memory/*.md按路径和行号读取原始 Markdown避免只凭索引摘要判断查证过程.dreams/*.json/jsonl、phase-signals.json读取事件、游标、阶段信号判断某条记忆来源是否可靠组织回答DREAMS.md、session-corpus、日期记忆区分叙事层、素材层、候选层、稳定层形成可读解释写回结果文档、Markdown 或新的 session输出本次结论成为未来 Dreaming 的潜在素材图一次查询如何通过索引回读可审计原文Dreaming 的后台属性也体现在这里​当前对话产生素材后台筛选素材长期记忆被索引未来对话再把它召回​。系统不追求记住一切它反复压缩真正有复用价值的上下文。图长期记忆通过索引被召回再参与下一次 Agent 回答与任务执行为什么不能退回单文件记忆把所有长期信息放进一个memory.md文件看起来简单实际会很快暴露工程问题。工程问题单文件记忆的风险分层机制的处理方式原始会话太噪问候、失败重试、过程说明混进长期事实session-corpus先作为素材层等待筛选候选事实不稳定未验证事实直接污染长期记忆Light Sleep 用confidence、evidence、status暂存长期偏好需要压缩历史上下文越积越长检索结果越来越散REM Sleep 将重复模式压缩为稳定判断检索需要速度每次查询都扫描全量 Markdown成本高且不稳定SQLite chunk FTS embedding 提供快速检索调试需要证据链不知道某条记忆从哪里来、为什么出现events、ingestion、recall、phase signals 保留过程证据多阶段处理需要去重每次运行都可能重复写入同一素材ingestion 游标和 recall key 支持增量处理与去重图单文件记忆与 Dreaming 分层机制的工程差异分层不是为了把系统做复杂而是为了让不同稳定程度的信息拥有不同出口。越靠近原始会话越强调完整和可追溯越靠近 REM 和索引越强调稳定、压缩和复用。排查 Dreaming先看结果再追过程最后查索引分析 Dreaming 输出时不建议一上来就打开 SQLite也不建议直接修改.dreams里的状态文件。更稳的路径是按“结果、过程、索引”逐层排查。顺序文件先看它的原因重点关注1memory/YYYY-MM-DD.md先确认最终有没有沉淀Light / REM 是否存在内容是否符合预期2memory/.dreams/events.jsonl确认 Dreaming 是否完成、完成哪个阶段memory.dream.completed、phase、inlinePath3memory/.dreams/session-corpus/YYYY-MM-DD.txt查看当天原始会话素材是否被抽取是否有目标会话、来源行号是否正确4short-term-recall.json判断哪些片段近期被频繁召回recallCount、recallDays、conceptTags5phase-signals.json判断哪些片段被 Light / REM 反复命中lightHits、remHits6daily-ingestion.json、session-ingestion.json排查为什么没有新增素材或重复处理lineCount、contentHash、mtimeMs7tech.sqlite最后确认索引是否同步files、chunks、chunks_fts图按结果、过程、索引逐层定位记忆问题这条路径能减少误判先确认“最终有没有写入”再确认“过程有没有运行”最后确认“索引有没有跟上”。几个容易踩错的理解常见理解更准确的说法为什么重要Dreaming 就是把聊天记录写进 memory它会先抽取素材再通过候选、召回和阶段信号筛选避免把所有临时对话都当成长期事实.dreams目录就是长期记忆.dreams更偏中间状态和运行审计长期记忆主要看memory/*.md避免把状态文件误当正文知识库tech.sqlite是最终事实源它是派生索引Markdown 原文才更适合人工审计排查时应回到 path 和 line 的原文Light Sleep 已经是稳定事实Light 只是候选常带statusstaged和较低置信度后续回答不应过度依赖候选层REM Sleep 一定完全正确REM 更稳定但仍应看 evidence 和上下文长期记忆仍可能过期或受历史上下文影响文件存在就一定能被搜到需要被索引器同步进tech.sqlite才能被快速检索能解释 memory 文件和 search 结果不一致的问题用五个子系统重新理解 Dreaming从工程架构看Dreaming 可以拆成五个子系统而不是一堆零散文件子系统输入输出关键文件输入记录当前对话、工具事件、运行元信息原始 session 日志tech/sessions/*.jsonl素材抽取新增 session 行按日期聚合的可读素材session-corpus/YYYY-MM-DD.txt、session-ingestion.json候选判断素材、历史召回、阶段信号Light Candidateshort-term-recall.json、phase-signals.json长期沉淀多次命中或高价值候选REM Reflection、日期记忆memory/YYYY-MM-DD.md、DREAMS.md检索回流Markdown 记忆正文chunk、FTS、embedding、未来召回tech.sqlite、memory_search、memory_get图Dreaming 可拆解为输入、抽取、候选、沉淀和回流五个子系统这个拆法对排查很有帮助素材缺失就看输入记录和抽取候选不合理就看召回和阶段信号回答没有复用历史记忆就看索引回流和memory_search。结语OpenClaw Dreaming 的价值不在于让 Agent 机械地记住更多内容。它给长期记忆补上了一套生产过程。原始会话先被保留下来随后进入素材层素材被召回、聚合、打分形成 Light 候选重复出现或价值明确的内容被压缩成 REM 判断最终 Markdown 正文进入 SQLite 索引再通过memory_search和memory_get回到未来任务。这样形成的​长期记忆不是黑盒摘要也不是无限膨胀的聊天记录​。它有来源、有阶段、有证据、有索引排查时还能回到原文验证。对一个需要长期协作的 Agent 来说盲目记住所有事情没有意义能把可复用的上下文沉淀下来并在下一次任务里解释清楚为什么召回它才更有用。OpenClaw Dreaming 记忆系统拆解Agent 长期记忆如何从会话日志流向检索回流