1. OpenClaw Agent 记忆模块到底解决什么问题
OpenClaw 的 Agent 记忆(Memory)模块,简单说就是让 Agent 把「记住的东西」落到磁盘上的 Markdown 文件里,而不是只留在当前会话的上下文窗口里。它适合谁?适合那些用 OpenClaw 跑长期任务、做个人助理、维护项目笔记,或者希望 Agent 跨会话保留决策与偏好的开发者。核心检索词就是 OpenClaw、Agent、Memory、Markdown、memory_search——这几个词贯穿整篇。
我先把机制讲清楚:OpenClaw 的记忆是 agent 工作区中的纯 Markdown 文件,这些文件是事实来源,模型只「记住」写入磁盘的内容。也就是说,你不写盘,它就真的不记得。记忆搜索工具由活动的记忆插件提供,默认是 memory-core;如果你把plugins.slots.memory设为"none",记忆插件就被禁用,memory_search 和 memory_get 这两个工具也不会启用。
默认工作区布局是两层记忆。第一层是memory/YYYY-MM-DD.md日常日志,只允许追加,会话开始时读取今天和昨天的日志。第二层是MEMORY.md,可选的精挑细选的长期记忆。这里有个容易踩的坑:如果MEMORY.md和memory.md同时存在于工作区根目录,OpenClaw 仅加载MEMORY.md,小写的memory.md仅在MEMORY.md不存在时作为后备使用,而且只在主要的私有会话中加载,绝不在群组上下文中加载。
这些文件位于工作区下,由agents.defaults.workspace控制,默认是~/.openclaw/workspace。面向 agent 的工具有两个:memory_search对索引片段做语义召回,memory_get针对性地读取特定 Markdown 文件或行范围。值得一提的是,memory_get现在在文件不存在时会优雅降级,比如首次写入前的日常日志,内置管理器和 QMD 后端都会返回{ text: "", path }而不是抛 ENOENT 错误,这样 agent 就能处理「尚未记录任何内容」的情况,不用把工具调用包在 try/catch 里。
什么时候写入记忆?决策、偏好和持久性事实写入MEMORY.md;日常笔记和持续上下文写入memory/YYYY-MM-DD.md。如果有人让你「记住这个」,就把它写下来,不要留在内存中。这个功能仍在发展中,提醒模型存储记忆会有所帮助,它会知道该怎么做。如果你想让某些内容被固定下来,直接要求机器人将其写入记忆。
还有一个自动记忆刷新机制,叫预压缩提醒。当会话接近自动压缩时,OpenClaw 会触发一个静默的、agent 驱动的回合,提醒模型在上下文被压缩之前写入持久性记忆。默认提示明确说明模型可以回复,但通常NO_REPLY是正确的响应,这样用户永远不会看到这个回合。这由agents.defaults.compaction.memoryFlush控制,细节包括:软阈值在会话令牌估计值超过contextWindow - reserveTokensFloor - softThresholdTokens时触发刷新;默认静默,提示包含NO_REPLY;两个提示,一个用户提示和一个系统提示附加提醒;每个压缩周期只刷新一次,在sessions.json中跟踪;工作区必须可写,如果会话在沙箱中以workspaceAccess: "ro"或"none"运行,则跳过刷新。
理解了这些,你就明白为什么「记忆」不是玄学,而是文件读写加检索。接下来我把 endpoint 改到 TaoToken 统一通道,完成调用验证。
2. 接入 TaoToken 统一通道的前置准备
在动手配置记忆之前,先把模型调用通道理顺。OpenClaw 的记忆搜索默认使用远程嵌入,而远程嵌入需要嵌入提供方的 API key。OpenClaw 从认证配置文件、models.providers.*.apiKey或环境变量中解析 key。这里有个关键点:Codex OAuth 仅涵盖聊天/补全,不满足记忆搜索的嵌入要求。所以如果你只配了 Codex OAuth,memory_search 会因为拿不到嵌入 key 而保持禁用。
我的做法是把 endpoint 统一改到 TaoToken 通道,这样聊天模型和嵌入模型走同一个入口,key 管理也集中。TaoToken 官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api ,注意 API 地址不加 UTM 参数。你需要先去控制台创建 API Key,控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,API Keys 管理页是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。如果你还没决定用哪个模型,可以先去模型对话页试试 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
前置准备分三步。第一步,拿到 API Key,形如sk-xxxx,记下来。第二步,确认你的 OpenClaw 版本支持memorySearch.remote.baseUrl和memorySearch.remote.apiKey,这两个字段是自定义 OpenAI 兼容端点的关键。第三步,确认工作区可写,因为记忆文件要落盘,沙箱只读模式会跳过刷新。
这里要强调一个业务边界:TaoToken 是统一调用通道,不是让你绕过任何合规要求,也不是灰色中转。你用它就是把 baseUrl 指向官方 API 入口,key 用自己申请的,模型 ID 按文档填。所有配置都走标准 OpenAI 兼容协议,没有黑魔法。
关于模型选择,记忆搜索的嵌入模型和聊天模型可以分开。聊天模型你可以用 Claude 系列或 GPT 系列,嵌入模型用text-embedding-3-small这类。如果你长期做编码或 Agent 任务,可以考虑 Coding Plan,入口是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。如果你用 Claude Code 做润色或接入,参考 https://taotoken.net/claude-code?utm_source=taotoken_aicg_blog_end&utm_content=claude-code&utm_campaign=rewrite 。
前置准备做完,接下来就是可复制的配置片段。我会把记忆目录结构、memorySearch配置、以及 endpoint 指向 TaoToken 的写法一次给全。
3. 可复制的记忆目录结构与配置片段
先建目录结构。默认工作区是~/.openclaw/workspace,你可以这样初始化:
mkdir -p ~/.openclaw/workspace/memory touch ~/.openclaw/workspace/MEMORY.md touch ~/.openclaw/workspace/memory/$(date +%F).md目录长这样:
~/.openclaw/workspace/ ├── MEMORY.md └── memory/ ├── 2026-02-10.md └── 2026-02-09.mdMEMORY.md放长期记忆,memory/YYYY-MM-DD.md放日常日志。注意大小写,MEMORY.md优先于memory.md。
接下来是核心配置。OpenClaw 的配置是 JSON 风格,记忆搜索在agents.defaults.memorySearch下配置,不是顶层的memorySearch,这点很多人写错。下面这段把 provider 设为 openai,并把 remote 指向 TaoToken 统一通道:
{ "agents": { "defaults": { "workspace": "~/.openclaw/workspace", "memorySearch": { "enabled": true, "provider": "openai", "model": "text-embedding-3-small", "fallback": "none", "remote": { "baseUrl": "https://taotoken.net/api/v1/", "apiKey": "sk-你的_TaoToken_KEY" }, "extraPaths": ["../team-docs"], "sync": { "watch": true }, "query": { "hybrid": { "enabled": true, "vectorWeight": 0.7, "textWeight": 0.3, "candidateMultiplier": 4, "mmr": { "enabled": true, "lambda": 0.7 }, "temporalDecay": { "enabled": true, "halfLifeDays": 30 } } } } } } }如果你用 TOML 风格管理配置,等价写法是:
[agents.defaults] workspace = "~/.openclaw/workspace" [agents.defaults.memorySearch] enabled = true provider = "openai" model = "text-embedding-3-small" fallback = "none" [agents.defaults.memorySearch.remote] baseUrl = "https://taotoken.net/api/v1/" apiKey = "sk-你的_TaoToken_KEY" [agents.defaults.memorySearch.sync] watch = true如果你更习惯用settings.json集中管理,把上面 JSON 片段合并进你的 settings 文件即可,路径和字段名保持一致。三件套要写全:Base URL 是https://taotoken.net/api/v1/,Key 是你申请的sk-开头字符串,Model ID 是text-embedding-3-small。聊天模型那边同理,把models.providers的 baseUrl 也指向 TaoToken,model 填你选的聊天模型 ID。
再补一个自动记忆刷新的配置,放在agents.defaults.compaction下:
{ "agents": { "defaults": { "compaction": { "reserveTokensFloor": 20000, "memoryFlush": { "enabled": true, "softThresholdTokens": 4000, "systemPrompt": "会话即将压缩。现在存储持久性记忆。", "prompt": "将任何持久的笔记写入 memory/YYYY-MM-DD.md;如果没有要存储的内容,请回复 NO_REPLY。" } } } } }如果你要索引默认工作区之外的 Markdown,用extraPaths,路径可以是绝对路径或相对于工作区的路径,目录会被递归扫描.md文件,符号链接会被忽略。默认只索引 Markdown,除非开多模态。
配置写完,下一步就是验证请求,看 memory_search 是否真的能召回。
4. 验证 memory_search 与成功结果
验证分两步:先确认索引建起来了,再确认检索能召回。
第一步,写入一条测试记忆。往MEMORY.md里写:
# 长期记忆 - 项目代号:OpenClaw-Memory-Test - 默认嵌入模型:text-embedding-3-small - 统一通道:TaoToken再往今天的日志写:
# 2026-02-10 - 今天把 memorySearch.remote.baseUrl 改到 TaoToken 统一通道 - 验证 memory_search 能召回「统一通道」相关片段第二步,触发一次会话,让 OpenClaw 在会话启动时同步索引。同步在会话启动时、搜索时或按时间间隔调度,并异步运行。你可以直接在对话里让 agent 调用 memory_search:
请用 memory_search 搜索「统一通道」,返回片段和文件路径。成功时你会看到类似结构的结果:片段文本、文件路径、行范围、分数、provider/model,以及是否从本地嵌入回退到了远程嵌入。片段文本上限约 700 字符,不返回完整文件负载。目标块大小约 400 令牌,80 令牌重叠。
如果你想手动确认索引状态,可以检查每个 agent 的 SQLite 数据库,默认在~/.openclaw/memory/.sqlite,可通过agents.defaults.memorySearch.store.path配置,支持{agentId}令牌。索引存储会记录嵌入提供方/模型、端点指纹和分块参数,如果其中任何一项变化,OpenClaw 会自动重置并重新索引整个存储。
再验证 memory_get。让 agent 读取特定文件:
请用 memory_get 读取 MEMORY.md 的前 10 行。成功时返回文件内容。如果文件不存在,会返回{ text: "", path },不会抛 ENOENT。注意 memory_get 拒绝MEMORY.md/memory/之外的路径,这是安全边界。
混合搜索验证。启用query.hybrid后,OpenClaw 结合向量相似度和 BM25 关键词相关性。你可以用一个精确 token 查询,比如「text-embedding-3-small」,看 BM25 是否命中;再用一个语义查询,比如「我把调用入口换到哪了」,看向量是否命中。如果嵌入不可用或提供方返回零向量,仍然运行 BM25 并返回关键词匹配结果;如果无法创建 FTS5,保持纯向量搜索,不会硬失败。
时间衰减验证。查询「统一通道」时,今天的日志应该排在旧日志前面。默认半衰期 30 天,今天的笔记 100% 原始分数,7 天前约 84%,30 天前 50%,90 天前 12.5%。永久文件从不衰减,包括MEMORY.md和memory/中非日期的文件。
MMR 验证。如果你有多条相似日志,启用 MMR 后,近乎重复的片段会被排除,agent 获得更多样化的信息。默认 lambda 0.7,平衡相关性和多样性。
到这里,如果 memory_search 返回了带路径和行范围的片段,说明整条链路通了:Markdown 落盘、索引构建、TaoToken 嵌入调用、语义召回。
5. 本篇常见错误排查
第一个高频错误:401 Unauthorized。表现是 memory_search 一直禁用或报鉴权失败。原因通常是memorySearch.remote.apiKey没填、填错,或者 baseUrl 写成了https://taotoken.net/api而漏了/v1/。排查方法:确认 baseUrl 是https://taotoken.net/api/v1/,key 是sk-开头且没有多余空格。另外注意,Codex OAuth 不满足嵌入要求,如果你只配了 OAuth,嵌入 key 解析不到,记忆搜索会保持禁用直到配置完成。
第二个错误:local proxy failed。表现是本地嵌入模式启动失败。原因通常是node-llama-cpp原生构建没通过。排查方法:运行pnpm approve-builds,选择node-llama-cpp,然后pnpm rebuild node-llama-cpp。如果你不想折腾本地构建,直接把 provider 设为 openai 走 TaoToken 远程嵌入,fallback 设为 none。
第三个错误:reading choices 相关报错。表现是嵌入响应解析失败。原因通常是 baseUrl 指向的端点返回格式不是 OpenAI 兼容结构,或者 model ID 填错。排查方法:确认 model 是text-embedding-3-small这类标准嵌入模型 ID,baseUrl 末尾带/v1/。如果你用自定义端点,memorySearch.remote.headers可以加额外头部。
第四个错误:OAuth 相关报错。表现是聊天能用但记忆搜索不可用。原因就是前面说的,Codex OAuth 仅涵盖聊天/补全,不满足嵌入要求。排查方法:单独为嵌入配置 API key,走memorySearch.remote.apiKey。
第五个错误:memory_search 返回空结果。原因可能是 scope 拒绝了搜索。默认 scope 仅为 DM,拒绝所有,允许直接聊天。如果你在群组或频道里搜,会被拒绝。OpenClaw 会记录一个包含派生出的 channel/chatType 的警告,方便调试。放宽 scope 才能让 QMD 结果在群组显示。
第六个错误:索引不更新。原因可能是工作区只读,沙箱以workspaceAccess: "ro"或"none"运行会跳过刷新。排查方法:确认工作区可写。另外,监视器有 1.5 秒防抖,同步是异步的,刚写完文件立刻搜可能略有陈旧。
第七个错误:切换嵌入模型后维度不匹配。从gemini-embedding-001(768 维)切到gemini-embedding-2-preview(3072 维)会改变向量大小,在 768、1536、3072 之间改outputDimensionality同理。OpenClaw 检测到模型或维度更改会自动重新索引,但你要等它跑完。
第八个错误:QMD 二进制缺失。如果你设了memory.backend = "qmd"但没装 QMD CLI,OpenClaw 会自动回退到内置 SQLite 管理器,记忆工具继续工作。想用 QMD 就单独安装,并确保qmd在网关 PATH 里。
排查完这些,你的记忆模块基本就稳了。最后把 CTA 分流说清楚:排障和接入看 API Keys 和接入文档,验证模型去模型对话,长期编码和 Agent 任务上 Coding Plan。
6. 把记忆模块用起来的下一步
配置跑通之后,我建议你先别急着堆功能,而是把「写记忆」变成习惯。OpenClaw 的记忆是事实来源,模型只记住写入磁盘的内容。你可以每天让 agent 把关键决策追加到memory/YYYY-MM-DD.md,把长期偏好整理进MEMORY.md。如果有人让你「记住这个」,直接要求机器人写入记忆,不要留在上下文里。
如果你要长期跑编码或 Agent 任务,Coding Plan 入口是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。API Keys 管理在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。验证模型效果去 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。Claude Code 接入参考 https://taotoken.net/claude-code?utm_source=taotoken_aicg_blog_end&utm_content=claude-code&utm_campaign=rewrite 。
最后提醒一句:会话日志存在于磁盘上,任何具有文件系统访问权限的进程或用户都可以读取,所以请把磁盘访问视为信任边界。为了更严格的隔离,在单独的操作系统用户或主机下运行 agents。记忆模块的价值在于跨会话保留上下文,但前提是你把该写的写下来,把该配的配正确。