Memory
OpenClaw memory is plain Markdown in the agent workspace. The files are the source of truth; the model only “remembers” what gets written to disk. Memory search tools are provided by the active memory plugin (default:memory-core). 記憶體搜尋工具由目前啟用的記憶體外掛提供(預設:
memory-core)。可使用 plugins.slots.memory = "none" 停用記憶體外掛。
Memory files(Markdown)
預設的工作區配置使用兩層記憶體:memory/YYYY-MM-DD.md- 每日紀錄(僅追加)。
- Read today + yesterday at session start.
MEMORY.md(選用)- 精選的長期記憶。
- Only load in the main, private session (never in group contexts).
agents.defaults.workspace,預設為
~/.openclaw/workspace)。完整配置請參見 Agent workspace。 1. 請參閱 Agent workspace 以了解完整版面配置。
何時寫入記憶體
- 決策、偏好與可長期保存的事實寫入
MEMORY.md。 - 日常筆記與進行中的脈絡寫入
memory/YYYY-MM-DD.md。 - 若有人說「記住這個」,就把它寫下來(不要只放在 RAM)。
- 此區域仍在持續演進中。 3. 這有助於提醒模型儲存記憶;它會知道該怎麼做。
-
- 如果你希望某件事能被保留下來,請要求機器人把它寫入記憶中。
自動記憶體清空(預先壓縮 ping)
當一個工作階段接近自動壓縮時,OpenClaw 會觸發一個靜默的、具代理性的回合,提醒模型在內容被壓縮之前寫入持久記憶。 6. 預設提示明確指出模型 可以回覆,但通常NO_REPLY 才是正確的回應,這樣使用者永遠不會看到這個回合。
此行為由 agents.defaults.compaction.memoryFlush 控制:
- 軟性門檻:當工作階段的權杖數估計值跨過
contextWindow - reserveTokensFloor - softThresholdTokens時觸發清空。 - 預設為無聲:提示包含
NO_REPLY,因此不會送達使用者。 - 兩個提示:使用者提示+系統提示一併附加提醒。
- 每個壓縮循環僅一次清空(於
sessions.json追蹤)。 - 工作區必須可寫入:若工作階段以沙箱模式執行且使用
workspaceAccess: "ro"或"none",則會略過清空。
向量記憶搜尋
OpenClaw 可以在MEMORY.md 與 memory/*.md 上建立小型向量索引,
使語意查詢即使措辭不同也能找到相關筆記。
預設值:
-
- 預設啟用。
-
- 監看記憶檔案的變更(去抖動)。
- 請在
agents.defaults.memorySearch(而非頂層memorySearch)下設定記憶體搜尋。 -
- 預設使用遠端嵌入(embeddings)。 預設使用遠端嵌入(embeddings)。 預設使用遠端嵌入。若未設定
memorySearch.provider,OpenClaw 會自動選擇: - 若設定了
memorySearch.local.modelPath且檔案存在,使用local。 - 若可解析 OpenAI 金鑰,使用
openai。 - 若可解析 Gemini 金鑰,使用
gemini。 - 若可解析 Voyage 金鑰,使用
voyage。 - 否則在完成設定前,記憶搜尋會維持停用。
- 預設使用遠端嵌入(embeddings)。 預設使用遠端嵌入(embeddings)。 預設使用遠端嵌入。若未設定
- 本地模式使用 node-llama-cpp,且可能需要
pnpm approve-builds。 - 可用時使用 sqlite-vec 以加速 SQLite 內的向量搜尋。
models.providers.*.apiKey,或環境變數中解析金鑰。 13. Codex OAuth 僅涵蓋聊天/補全,無法滿足用於記憶搜尋的嵌入需求。 14. 對於 Gemini,請使用 GEMINI_API_KEY 或 models.providers.google.apiKey。 15. 對於 Voyage,請使用 VOYAGE_API_KEY 或 models.providers.voyage.apiKey。 16. 使用自訂的 OpenAI 相容端點時,請設定 memorySearch.remote.apiKey(以及選用的 memorySearch.remote.headers)。
QMD 後端(實驗性)
設定memory.backend = "qmd" 以將內建的 SQLite 索引器替換為
QMD:一個以本地為優先的搜尋側車,結合
BM25+向量+重新排序。Markdown 仍是唯一可信來源;OpenClaw 透過殼層呼叫
QMD 進行擷取。重點如下: 17. Markdown 仍是唯一可信來源;OpenClaw 會呼叫 QMD 進行檢索。 18. 重點:
先決條件
-
- 預設停用。 預設停用。 預設停用。需於每個設定中選擇加入(
memory.backend = "qmd")。
- 預設停用。 預設停用。 預設停用。需於每個設定中選擇加入(
- 需另行安裝 QMD CLI(
bun install -g https://github.com/tobi/qmd或下載 發行版),並確保qmd二進位檔位於 Gateway 閘道器的PATH。 - QMD 需要允許擴充的 SQLite 建置(macOS 使用
brew install sqlite)。 - QMD 透過 Bun+
node-llama-cpp完全在本地執行,並在首次使用時 從 HuggingFace 自動下載 GGUF 模型(不需要獨立的 Ollama 常駐程式)。 - Gateway 閘道器 會在
~/.openclaw/agents/<agentId>/qmd/下設定XDG_CONFIG_HOME與XDG_CACHE_HOME,於自成一體的 XDG home 中執行 QMD。 - 作業系統支援:安裝好 Bun+SQLite 後,macOS 與 Linux 可即用。 Windows 最佳方式為 WSL2。 20. Windows 最佳支援方式為 WSL2。
- Gateway 閘道器 會在
~/.openclaw/agents/<agentId>/qmd/下寫入自成一體的 QMD home(設定+快取+ sqlite DB)。 - 透過
qmd collection add從memory.qmd.paths(加上預設的工作區記憶體檔案)建立集合,接著在開機與可設定的間隔 (memory.qmd.update.interval,預設 5 m)執行qmd update+qmd embed。 - 閘道器現在會在啟動時初始化 QMD 管理器,因此即使在第一次呼叫
memory_search之前,也會啟用週期性更新計時器。 - 開機時的重新整理現在預設在背景執行,避免阻塞聊天啟動;設定
memory.qmd.update.waitForBootSync = true可保留先前的阻塞行為。 - 搜尋透過
qmd query --json執行。若 QMD 失敗或缺少二進位檔, OpenClaw 會自動回退至內建的 SQLite 管理器,確保記憶工具可繼續運作。 21. 如果所選模式在您的 QMD 建置版本中拒絕使用旗標,OpenClaw 會改以qmd query重試。 若 QMD 失敗或缺少二進位檔,OpenClaw 會自動回退至內建的 SQLite 管理器,確保記憶工具持續運作。 - OpenClaw 目前未提供 QMD 的嵌入批次大小調校;批次行為由 QMD 本身控制。
- 首次搜尋可能較慢:QMD 可能在第一次
qmd query執行時 下載本地 GGUF 模型(重新排序/查詢擴展)。-
OpenClaw 在執行 QMD 時會自動設定
XDG_CONFIG_HOME/XDG_CACHE_HOME。 -
若要手動預先下載模型(並暖身與 OpenClaw 相同的索引),
請使用代理程式的 XDG 目錄執行一次性查詢。
OpenClaw 的 QMD 狀態位於你的狀態目錄下(預設為
~/.openclaw)。 OpenClaw 的 QMD 狀態位於你的 狀態目錄(預設為~/.openclaw)。 你可以匯出 OpenClaw 使用的相同 XDG 變數,將qmd指向完全相同的索引: OpenClaw 的 QMD 狀態位於你的 狀態目錄(預設為~/.openclaw)。 你可以匯出 OpenClaw 使用的相同 XDG 變數,將qmd指向完全相同的索引:
-
OpenClaw 在執行 QMD 時會自動設定
memory.qmd.*)
command(預設qmd):覆寫可執行檔路徑。includeDefaultMemory(預設true):自動索引MEMORY.md+memory/**/*.md。includeDefaultMemory(預設true):自動索引MEMORY.md+memory/**/*.md。paths[]:新增額外目錄/檔案(path,選用pattern,選用 穩定的name)。sessions:選擇加入工作階段 JSONL 索引(enabled、retentionDays、exportDir)。update:控制重新整理頻率與維護執行: (interval、debounceMs、onBoot、waitForBootSync、embedInterval、commandTimeoutMs、updateTimeoutMs、embedTimeoutMs)。limits:限制回憶負載(maxResults、maxSnippetChars、maxInjectedChars、timeoutMs)。scope:與session.sendPolicy相同的結構描述。 預設僅限私訊(deny全部、allow直接聊天);放寬後可在群組/頻道中顯示 QMD 命中。 23. 預設為僅 DM(全部deny,僅allow直接聊天);放寬設定即可在群組/頻道中顯示 QMD 命中結果。match.keyPrefix會比對正規化後的 session key(轉為小寫,並移除 開頭的agent:<id>:)。 範例:discord:channel:。match.rawKeyPrefix會比對原始的 session key(轉為小寫),包含agent:<id>:。 範例:agent:main:discord:。- 舊版:
match.keyPrefix: "agent:..."仍會被視為 raw-key 前綴, 但為了清楚起見,建議改用rawKeyPrefix。
- When
scopedenies a search, OpenClaw logs a warning with the derivedchannel/chatTypeso empty results are easier to debug. - 來自工作區外的片段會以
qmd/<collection>/<relative-path>顯示於memory_search結果中;memory_get會理解該前綴並從設定的 QMD 集合根目錄讀取。 - 當
memory.qmd.sessions.enabled = true時,OpenClaw 會將已去識別化的工作階段逐字稿 (使用者/助理回合)匯出到~/.openclaw/agents/<id>/qmd/sessions/下的專用 QMD 集合,讓memory_search能回憶近期 對話而不需觸碰內建的 SQLite 索引。 - 當
memory.citations為auto/on時,memory_search片段現在會包含Source: <path#line>頁尾;設定memory.citations = "off"可將路徑中繼資料保留為內部(代理程式仍會收到路徑以用於memory_get,但片段文字會省略頁尾,且系統提示會警告代理程式不要引用)。
memory.citations不論後端為何皆適用(auto/on/off)。- 當
qmd執行時,我們會標記status().backend = "qmd", 讓診斷顯示是哪個引擎提供結果。若 QMD 子行程結束或 JSON 輸出無法解析, 搜尋管理器會記錄警告並回傳內建提供者(既有的 Markdown 嵌入),直到 QMD 恢復。 24. 如果 QMD 子程序退出或 JSON 輸出無法解析,搜尋管理器會記錄警告並回傳內建提供者(既有的 Markdown 嵌入),直到 QMD 恢復為止。
其他記憶體路徑
若要索引預設工作區配置之外的 Markdown 檔案,請新增明確路徑:-
- 路徑可以是絕對路徑或相對於工作區的路徑。
- 目錄會被遞迴掃描以尋找
.md檔案。 - 僅索引 Markdown 檔案。
- 忽略符號連結(檔案或目錄)。
Gemini 嵌入(原生)
將提供者設定為gemini 以直接使用 Gemini 嵌入 API:
remote.baseUrl為選用(預設為 Gemini API 基底 URL)。remote.headers可在需要時新增額外標頭。- 預設模型:
gemini-embedding-001。
remote 設定:
memorySearch.provider = "local" 或設定
memorySearch.fallback = "none"。
回退:
memorySearch.fallback可為openai、gemini、local或none。- 回退提供者僅在主要嵌入提供者失敗時使用。
- 預設為停用。 對 OpenAI 與 Gemini 嵌入預設啟用。 OpenAI 與 Gemini 嵌入預設啟用。設定
agents.defaults.memorySearch.remote.batch.enabled = false可停用。 - 預設行為會等待批次完成;必要時可調整
remote.batch.wait、remote.batch.pollIntervalMs與remote.batch.timeoutMinutes。 - 設定
remote.batch.concurrency以控制並行提交的批次工作數量(預設:2)。 - 當
memorySearch.provider = "openai"或"gemini"時會套用批次模式,並使用對應的 API 金鑰。 - Gemini 批次工作使用非同步嵌入批次端點,且需要 Gemini Batch API 可用。
- 對於大型回填,OpenAI 通常是我們支援中最快的選項,因為可在單一批次工作中提交大量嵌入請求,並讓 OpenAI 非同步處理。
- OpenAI 為 Batch API 工作負載提供折扣定價,因此大型索引通常比同步送出相同請求更便宜。
- 詳情請參見 OpenAI Batch API 文件與價格:
memory_search— 回傳包含檔案+行範圍的片段。memory_get— 依路徑讀取記憶體檔案內容。
- 設定
agents.defaults.memorySearch.provider = "local"。 - 提供
agents.defaults.memorySearch.local.modelPath(GGUF 或hf:URI)。 - 選用:設定
agents.defaults.memorySearch.fallback = "none"以避免遠端回退。
記憶工具如何運作
memory_search會對來自MEMORY.md+memory/**/*.md的 Markdown 區塊 進行語意搜尋(目標約 400 權杖、80 權杖重疊)。它會回傳片段文字(上限約 700 字元)、 檔案路徑、行範圍、分數、提供者/模型,以及是否從本地→遠端嵌入回退。 不會回傳完整檔案內容。 28. 回傳的內容包含片段文字(上限約 700 字元)、檔案路徑、行號範圍、分數、提供者/模型,以及是否從本地 → 遠端嵌入回退。 29. 不會回傳完整檔案內容。memory_get會讀取特定的記憶體 Markdown 檔案(相對於工作區), 可選擇指定起始行與行數。位於MEMORY.md/memory/之外的路徑會被拒絕。 30. 位於MEMORY.md/memory/之外的路徑會被拒絕。- 兩個工具僅在代理程式的
memorySearch.enabled解析為 true 時啟用。
會被索引的內容(以及時機)
- 檔案類型:僅 Markdown(
MEMORY.md、memory/**/*.md)。 - 索引儲存:每個代理程式一個 SQLite,位於
~/.openclaw/memory/<agentId>.sqlite(可透過agents.defaults.memorySearch.store.path設定,支援{agentId}權杖)。 - 新鮮度:對
MEMORY.md+memory/的監看器會將索引標記為需要更新(去抖動 1.5 秒)。 32. 同步會在工作階段開始、搜尋時或依間隔排程,並以非同步方式執行。 33. 工作階段逐字稿使用增量閾值來觸發背景同步。 - 重新索引觸發:索引會儲存嵌入 提供者/模型+端點指紋+分塊參數。 只要其中任一變更,OpenClaw 會自動重設並重新索引整個儲存區。 34. 若其中任何一項變更,OpenClaw 會自動重置並重新索引整個儲存庫。
混合搜尋(BM25+向量)
啟用時,OpenClaw 會結合:- 向量相似度(語意匹配,措辭可不同)
- BM25 關鍵字關聯性(精確權杖,如 ID、環境變數、程式碼符號)
為何要混合?
向量搜尋很擅長「意思相同」:- 「Mac Studio gateway host」vs「執行 Gateway 閘道器 的機器」
- 「去抖檔案更新」vs「避免每次寫入就索引」
- ID(
a828e60、b3b9895a…) - 程式碼符號(
memorySearch.query.hybrid) - 錯誤字串(「sqlite-vec unavailable」)
我們如何合併結果(目前設計)
- 實作草圖:
- 從兩側各自擷取候選池:
- 向量:依餘弦相似度取前
maxResults * candidateMultiplier。 - BM25:依 FTS5 BM25 排名取前
maxResults * candidateMultiplier(數值越低越好)。
- 將 BM25 排名轉為近似 0..1 的分數:
textScore = 1 / (1 + max(0, bm25Rank))
-
- 依 chunk id 合併候選項並計算加權分數:
finalScore = vectorWeight * vectorScore + textWeight * textScore
vectorWeight+textWeight於設定解析時正規化為 1.0, 因此權重行為等同百分比。- 若嵌入不可用(或提供者回傳零向量),仍會執行 BM25 並回傳關鍵字匹配。
- 若無法建立 FTS5,則保留僅向量搜尋(不會硬性失敗)。
Embedding cache
OpenClaw 可在 SQLite 中快取 區塊嵌入,讓重新索引與頻繁更新 (尤其是工作階段逐字稿)不必為未變更的文字重新嵌入。 設定:工作階段記憶搜尋(實驗性)
You can optionally index session transcripts and surface them viamemory_search.
This is gated behind an experimental flag.
- Session indexing is opt-in (off by default).
- 工作階段更新會去抖,並在跨過差量門檻後 非同步索引(盡力而為)。
memory_search從不等待索引完成;在背景同步完成前,結果可能略為過時。- 結果仍僅包含片段;
memory_get仍僅限記憶體檔案。 - Session indexing is isolated per agent (only that agent’s session logs are indexed).
- 工作階段紀錄會存於磁碟(
~/.openclaw/agents/<agentId>/sessions/*.jsonl)。任何具有檔案系統存取權的程序/使用者都可讀取, 因此請將磁碟存取視為信任邊界。若需更嚴格隔離,請以不同 OS 使用者或主機執行代理程式。 Any process/user with filesystem access can read them, so treat disk access as the trust boundary. Any process/user with filesystem access can read them, so treat disk access as the trust boundary. For stricter isolation, run agents under separate OS users or hosts.
SQLite 向量加速(sqlite-vec)
當 sqlite-vec 擴充可用時,OpenClaw 會將嵌入儲存在 SQLite 虛擬表(vec0)中,並在資料庫內執行向量距離查詢。
這能在不將每個嵌入載入到 JS 的情況下保持搜尋效能。 This keeps search fast without loading every embedding into JS. This keeps search fast without loading every embedding into JS.
設定(選用):
enabled預設為 true;停用時,搜尋會回退為在處理序內 對已儲存嵌入進行餘弦相似度計算。- 若 sqlite-vec 擴充缺失或載入失敗,OpenClaw 會記錄錯誤並以 JS 回退繼續 (不使用向量表)。
extensionPath可覆寫隨附的 sqlite-vec 路徑(適用於自訂建置 或非標準安裝位置)。
本地嵌入自動下載
- 預設本地嵌入模型:
hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf(約 0.6 GB)。 - 當
memorySearch.provider = "local"時,node-llama-cpp會解析modelPath; 若缺少 GGUF,會 自動下載 至快取(或設定的local.modelCacheDir), 然後載入。下載可在重試時續傳。 Downloads resume on retry. Downloads resume on retry. - 原生建置需求:執行
pnpm approve-builds,選擇node-llama-cpp, 接著pnpm rebuild node-llama-cpp。 - 回退:若本地設定失敗且
memorySearch.fallback = "openai",我們會自動切換至遠端嵌入 (除非覆寫,預設為openai/text-embedding-3-small),並記錄原因。
自訂 OpenAI 相容端點範例
remote.*的優先順序高於models.providers.openai.*。remote.headers會與 OpenAI 標頭合併;發生金鑰衝突時以遠端為準。 省略remote.headers可使用 OpenAI 的預設值。 Omitremote.headersto use the OpenAI defaults. Omitremote.headersto use the OpenAI defaults.