メモリ
OpenClaw メモリは エージェント ワークスペース内のプレーンな Markdown です。ファイルが信頼できる唯一の情報源であり、モデルはディスクに書き込まれた内容だけを「記憶」します。 ファイルは真実の ソースです。モデルはディスクに書き込まれたものだけを「記憶」します。 メモリ検索ツールは、アクティブなメモリプラグインによって提供されます (デフォルト:memory-core )。 メモリ検索ツールは、アクティブなメモリ プラグイン(デフォルト: memory-core)によって提供されます。メモリ プラグインは plugins.slots.memory = "none" で無効化できます。 メモリ検索ツールは、アクティブなメモリ プラグイン(デフォルト: memory-core)によって提供されます。メモリ プラグインは plugins.slots.memory = "none" で無効化できます。
メモリ ファイル(Markdown)
デフォルトのワークスペース レイアウトでは、2 つのメモリ レイヤーを使用します。memory/YYYY-MM-DD.md- 日次ログ(追記のみ)。
- セッション開始時に「今日+昨日」を読み込みます。
MEMORY.md(任意)- 厳選された長期メモリ。
- メインのプライベート セッションでのみ読み込み(グループ コンテキストでは決して読み込みません)。
agents.defaults.workspace、デフォルト ~/.openclaw/workspace)配下にあります。完全なレイアウトについては Agent workspace を参照してください。 完全なレイアウトについては、Agent workspaceを参照してください。 完全なレイアウトについては、Agent workspaceを参照してください。
メモリを書き込むタイミング
- 判断、好み、永続的な事実は
MEMORY.mdに書き込みます。 - 日々のメモや実行中のコンテキストは
memory/YYYY-MM-DD.mdに書き込みます。 - 誰かが「これを覚えて」と言ったら、書き込みます(RAM に保持しません)。
- この領域はまだ進化しています。 この領域は現在も進化中です。モデルにメモリ保存を促すと役立ちます。モデルは何をすべきか理解しています。
- 何かを確実に残したい場合は、ボットにメモリへ書き込むよう依頼してください。
自動メモリ フラッシュ(プレコンパクション ping)
セッションが 自動コンパクションに近づく と、OpenClaw は サイレントなエージェント ターン をトリガーし、コンテキストが圧縮される 前 に永続メモリを書き込むようモデルに促します。デフォルトのプロンプトではモデルが 返信してもよい と明示されていますが、通常はNO_REPLY が正しい応答となり、ユーザーにこのターンが表示されることはありません。 デフォルトのプロンプトでは、モデル may reply、
と明示的に表示されますが、通常 NO_REPLY は正しい応答であるため、ユーザーはこのターンを見ることはありません。
これは agents.defaults.compaction.memoryFlush によって制御されます。
- ソフトしきい値: セッションのトークン推定値が
contextWindow - reserveTokensFloor - softThresholdTokensを超えるとフラッシュがトリガーされます。 - デフォルトでサイレント: プロンプトに
NO_REPLYが含まれるため、何も配信されません。 - 2 つのプロンプト: ユーザー プロンプトとシステム プロンプトがリマインダーを追加します。
- コンパクション サイクルごとに 1 回のフラッシュ(
sessions.jsonで追跡)。 - ワークスペースが書き込み可能である必要: セッションが
workspaceAccess: "ro"または"none"でサンドボックス化されて実行されている場合、フラッシュはスキップされます。
ベクター メモリ検索
OpenClaw はMEMORY.md と memory/*.md 上に小さなベクター インデックスを構築でき、表現が異なっても関連ノートを意味検索で見つけられます。
デフォルト:
- デフォルトで有効。
- メモリ ファイルの変更を監視(デバウンス)。
- メモリ検索は
agents.defaults.memorySearch(トップレベルのmemorySearchではありません)で構成します。 - デフォルトでリモート埋め込みを使用します。 デフォルトではリモート埋め込みを使用。
memorySearch.providerが設定されていない場合、OpenClaw は自動選択します:memorySearch.local.modelPathが設定され、ファイルが存在する場合はlocal。- OpenAI のキーを解決できる場合は
openai。 - Gemini のキーを解決できる場合は
gemini。 - Voyage のキーを解決できる場合は
voyage。 - それ以外の場合、設定されるまでメモリ検索は無効のままです。
- ローカル モードは node-llama-cpp を使用し、
pnpm approve-buildsが必要になる場合があります。 - 利用可能な場合、sqlite-vec を使用して SQLite 内のベクター検索を高速化します。
models.providers.*.apiKey、または環境
変数からキーを解決します。 Codex OAuthはチャット/補完のみをカバーしており、
メモリ検索の埋め込みを満たしていません。 Geminiの場合は、GEMINI_API_KEY または
models.providers.google.apiKey を使用します。 Voyage では、VOYAGE_API_KEY または
models.providers.voyage.apiKey を使用してください。 デフォルトでリモート埋め込みを使用します。 デフォルトではリモート埋め込みを使用。 memorySearch.provider が設定されていない場合、OpenClaw は自動選択します:
QMD バックエンド(実験的)
組み込みの SQLite インデクサーを QMD に置き換えるにはmemory.backend = "qmd" を設定します。QMD は、BM25+ベクター+再ランキングを組み合わせたローカル ファーストの検索サイドカーです。Markdown は信頼できる唯一の情報源のままで、OpenClaw は取得のために QMD を呼び出します。要点は次のとおりです。 Markdownは真実の源泉であり続けます。オープンクローの貝殻
検索のためにQMDに移動します。 キーポイント: Markdownは真実の源泉であり続けます。オープンクローの貝殻
検索のためにQMDに移動します。 キーポイント:
前提条件
- デフォルトで無効になっています。 デフォルトで無効になっています。 デフォルトでは無効。設定ごとにオプトイン(
memory.backend = "qmd")。 - QMD CLI を別途インストール(
bun install -g https://github.com/tobi/qmdまたはリリースを取得)し、qmdバイナリがゲートウェイのPATHにあることを確認します。 - QMD には拡張を許可する SQLite ビルドが必要です(macOS では
brew install sqlite)。 - QMD は Bun+
node-llama-cppにより完全にローカルで動作し、初回使用時に HuggingFace から GGUF モデルを自動ダウンロードします(別途 Ollama デーモンは不要)。 - ゲートウェイは、
XDG_CONFIG_HOMEとXDG_CACHE_HOMEを設定することで、~/.openclaw/agents/<agentId>/qmd/配下の自己完結型 XDG ホームで QMD を実行します。 - OSサポート:Bun + SQLiteが インストールされるとmacOSとLinuxはボックスから動作します。 WindowsはWSL2経由でサポートされています。 WindowsはWSL2経由でサポートされています。
- ゲートウェイは、
~/.openclaw/agents/<agentId>/qmd/配下に自己完結型の QMD ホーム(設定+キャッシュ+sqlite DB)を書き込みます。 - コレクションは
memory.qmd.paths(およびデフォルトのワークスペース メモリ ファイル)からqmd collection addで作成され、その後qmd update+qmd embedが起動時および設定可能な間隔(memory.qmd.update.interval、デフォルト 5 分)で実行されます。 - gateway は起動時に QMD マネージャーを初期化するようになったため、最初の
memory_search呼び出し前でも定期更新タイマーが有効になります。 - 起動時のリフレッシュは、チャット起動をブロックしないようデフォルトでバックグラウンド実行になりました。従来のブロッキング動作を維持するには
memory.qmd.update.waitForBootSync = trueを設定します。 - 検索は
qmd query --json経由で実行されます。QMD が失敗するかバイナリが見つからない場合、OpenClaw は自動的に組み込みの SQLite マネージャーへフォールバックし、メモリ ツールは引き続き動作します。 QMD に失敗した場合やバイナリが欠落している場合、 OpenClawは自動的に組み込みSQLiteマネージャに落ちるため、メモリツール が動作し続けます。 選択したモードがお使いの QMD ビルドでフラグを受け付けない場合、OpenClaw はqmd queryで再試行します。 QMD が失敗した場合、またはバイナリが 存在しない場合、OpenClaw は自動的に組み込みの SQLite マネージャーにフォールバックするため、メモリツールは引き続き動作します。 - OpenClaw は現時点で QMD の埋め込みバッチ サイズ調整を公開していません。バッチ挙動は QMD 自身が制御します。
- 初回検索は遅い場合があります: 初回の
qmd query実行時に、QMD がローカル GGUF モデル(再ランキング/クエリ拡張)をダウンロードすることがあります。-
OpenClaw は QMD 実行時に
XDG_CONFIG_HOME/XDG_CACHE_HOMEを自動設定します。 -
手動でモデルを事前ダウンロード(同じインデックスをウォームアップ)したい場合は、エージェントの XDG ディレクトリを使ってワンオフ クエリを実行してください。
OpenClawのQMD状態はstate dir (デフォルトは
~/.openclaw)の下にあります。 OpenClawのQMD状態はstate dir (デフォルトは~/.openclaw)の下にあります。 OpenClaw の QMD 状態は state ディレクトリ(デフォルト~/.openclaw)配下にあります。同一の XDG 変数をエクスポートすることで、qmdを同じインデックスに向けられます。
-
OpenClaw は QMD 実行時に
memory.qmd.*)
command(デフォルトqmd): 実行ファイル パスを上書き。searchMode(デフォルトsearch): どの QMD コマンドをmemory_search(search、vsearch、query)のバックエンドとして使用するかを指定します。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と同一のスキーマ。デフォルトは DM のみ(denyはすべて、allowはダイレクト チャット)。グループ/チャンネルで QMD ヒットを表示するには緩和します。scope:session.sendPolicyと同一のスキーマ。デフォルトは DM のみ(denyはすべて、allowはダイレクト チャット)。グループ/チャンネルで QMD ヒットを表示するには緩和します。 デフォルトは DMのみ (denyall,allowdirectチャット) です。グループ/チャンネルで QMD がヒットするように緩めます。match.keyPrefixは正規化されたセッションキー(小文字化され、先頭のagent:<id>:が削除されたもの)に一致します。 例:discord:channel:。match.rawKeyPrefixは raw セッションキー(小文字化)に一致し、agent:<id>:を含みます。 例:agent:main:discord:。- レガシー:
match.keyPrefix: "agent:..."も引き続き raw-key プレフィックスとして扱われますが、明確さのためにrawKeyPrefixの使用を推奨します。
scopeによって検索が拒否されると、OpenClaw は派生したchannel/chatTypeを含む警告をログに記録するため、空の結果をデバッグしやすくなります。- ワークスペース外から取得したスニペットは、
memory_searchの結果でqmd/<collection>/<relative-path>として表示されます。memory_getはそのプレフィックスを理解し、設定された QMD コレクション ルートから読み取ります。 memory.qmd.sessions.enabled = trueの場合、OpenClaw はサニタイズ済みのセッション トランスクリプト(ユーザー/アシスタントのターン)を~/.openclaw/agents/<id>/qmd/sessions/配下の専用 QMD コレクションにエクスポートし、組み込み SQLite インデックスに触れずにmemory_searchが最近の会話を想起できるようにします。memory_searchスニペットには、memory.citationsがauto/onの場合、Source: <path#line>フッターが含まれます。memory.citations = "off"を設定するとパス メタデータを内部扱いにできます(エージェントはmemory_getのためにパスを受け取りますが、スニペット本文からはフッターが省かれ、システム プロンプトで引用しないよう警告されます)。
memory.citationsは、バックエンド(auto/on/off)に関わらず適用されます。qmdが実行されると、診断でどのエンジンが結果を提供したか分かるようにstatus().backend = "qmd"をタグ付けします。QMD サブプロセスが終了するか JSON 出力を解析できない場合、検索マネージャーは警告をログに記録し、QMD が回復するまで組み込みプロバイダー(既存の Markdown 埋め込み)を返します。 17. QMD サブプロセスが終了した場合、または JSON 出力を解析できない場合、検索マネージャーは警告をログに記録し、QMD が復旧するまで組み込みプロバイダー(既存の Markdown 埋め込み)を返します。
追加のメモリ パス
デフォルトのワークスペース レイアウト外にある Markdown ファイルをインデックスしたい場合は、明示的なパスを追加します。- パスは絶対パスまたはワークスペース相対にできます。
- ディレクトリは
.mdファイルを再帰的にスキャンします。 - インデックスされるのは Markdown ファイルのみです。
- シンボリックリンク(ファイル/ディレクトリ)は無視されます。
Gemini 埋め込み(ネイティブ)
Gemini の埋め込み API を直接使用するには、プロバイダーをgemini に設定します。
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 は 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 文字上限)、ファイル パス、行範囲、スコア、プロバイダー/モデル、ローカル→リモート埋め込みへのフォールバック有無を返します。ファイル全体のペイロードは返しません。 スニペットテキスト (最大 700 文字)、ファイルパス、行範囲、スコア、プロバイダー/モデル、およびローカル → リモート埋め込みから戻ったかどうかを返します。 完全なファイルペイロードは返されません。memory_getは、特定のメモリ Markdown ファイル(ワークスペース相対)を、開始行と N 行の指定付きで読み取ります。MEMORY.md/memory/外のパスは拒否されます。MEMORY.md/memory/以外のパスは拒否されます。MEMORY.md/memory/以外のパスは拒否されます。- 両ツールは、エージェントに対して
memorySearch.enabledが true に解決された場合にのみ有効です。
何がインデックスされるか(およびタイミング)
- ファイル種別: Markdown のみ(
MEMORY.md、memory/**/*.md)。 - インデックス保存先: エージェントごとの SQLite(
~/.openclaw/memory/<agentId>.sqlite、agents.defaults.memorySearch.store.pathで設定可能、{agentId}トークンをサポート)。 - Freshness: watcher on
MEMORY.md+memory/はインデックスを汚します(デバウンス1.5)。 同期は、セッション開始時、検索時、または間隔でスケジュールされ、非同期で実行されます。 セッショントランスクリプトは、バックグラウンド同期をトリガーするためにデルタ閾値を使用します。 - 再インデックス トリガー: インデックスは プロバイダー/モデル+エンドポイント フィンガープリント+チャンク化パラメータ を保存します。いずれかが変更されると、OpenClaw は自動的に全体をリセットして再インデックスします。 再インデックス トリガー: インデックスは プロバイダー/モデル+エンドポイント フィンガープリント+チャンク化パラメータ を保存します。いずれかが変更されると、OpenClaw は自動的に全体をリセットして再インデックスします。 これらの変更があった場合、OpenClawは自動的にストア全体をリセットして再インデックスを作成します。
ハイブリッド検索(BM25+ベクター)
有効時、OpenClaw は次を組み合わせます。- ベクター類似度(意味一致、表現が異なっても可)
- BM25 キーワード関連度(ID、環境変数、コード シンボルなどの完全一致)
なぜハイブリッドか
ベクター検索は「同じ意味」を捉えるのが得意です。- 「Mac Studio gateway host」 vs 「ゲートウェイを実行しているマシン」
- 「ファイル更新をデバウンス」 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))
- チャンク ID で候補を和集合し、重み付きスコアを計算:
finalScore = vectorWeight * vectorScore + textWeight * textScore
vectorWeight+textWeightは設定解決時に 1.0 に正規化され、重みが割合として振る舞います。- 埋め込みが利用不可(またはプロバイダーがゼロ ベクターを返す)場合でも、BM25 を実行してキーワード一致を返します。
- FTS5 を作成できない場合、ベクターのみ検索を維持します(致命的エラーにはしません)。
埋め込みキャッシュ
OpenClaw は SQLite に チャンク埋め込み をキャッシュでき、再インデックスや頻繁な更新(特にセッション トランスクリプト)で未変更テキストの再埋め込みを避けられます。 設定:セッション メモリ検索(実験的)
任意で セッション トランスクリプト をインデックスし、memory_search 経由で表示できます。
この機能は実験フラグの背後にあります。
これは実験的な旗の後ろにゲートされている。
これは実験的な旗の後ろにゲートされている。
- セッション インデックスは オプトイン(デフォルト無効)。
- セッション更新はデバウンスされ、デルタしきい値を超えると 非同期でインデックス されます(ベストエフォート)。
memory_searchはインデックス待ちでブロックしません。バックグラウンド同期が完了するまで結果は多少古い可能性があります。- 結果は引き続きスニペットのみを含みます。
memory_getはメモリ ファイルに限定されたままです。 - セッション インデックスはエージェントごとに分離されます(そのエージェントのセッション ログのみが対象)。
- セッション ログはディスク上(
~/.openclaw/agents/<agentId>/sessions/*.jsonl)に保存されます。ファイルシステムにアクセスできるプロセス/ユーザーは読み取れるため、ディスク アクセスを信頼境界として扱ってください。より厳密な分離が必要な場合は、エージェントを別の OS ユーザーやホストで実行してください。 ファイルシステムへのアクセスを持つプロセス/ユーザは、それらを読み取ることができるので、ディスクアクセスを信頼の境界として扱います。 より厳格な分離を行うには、別々の OS ユーザーまたはホストでエージェントを実行します。 ファイルシステムへのアクセスを持つプロセス/ユーザは、それらを読み取ることができるので、ディスクアクセスを信頼の境界として扱います。 より厳格な分離を行うには、別々の OS ユーザーまたはホストでエージェントを実行します。
SQLite ベクター高速化(sqlite-vec)
sqlite-vec 拡張が利用可能な場合、OpenClaw は埋め込みを SQLite 仮想テーブル(vec0)に保存し、データベース内でベクター距離クエリを実行します。これにより、すべての埋め込みを JS に読み込まずに高速検索が可能になります。 これにより、JSにすべての埋め込みをロードすることなく、検索が高速になります。 これにより、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)に 自動ダウンロード してから読み込みます。ダウンロードは再試行時に再開されます。 ダウンロードは再試行時に再開されます。 ダウンロードは再試行時に再開されます。- ネイティブ ビルド要件:
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 ヘッダーとマージされ、キー競合時はリモートが優先されます。OpenAI のデフォルトを使用するにはremote.headersを省略してください。remote.headersを省略して、OpenAI のデフォルトを使用します。remote.headersを省略して、OpenAI のデフォルトを使用します。