メモリ
OpenClaw のメモリの仕組み(ワークスペースファイル + 自動メモリ更新)。
OpenClaw メモリはエージェントワークスペース内の純粋な Markdownです。これらのファイルは
真実のソースであり、モデルはディスクに書き込まれた内容のみを「記憶」します。
メモリ検索ツールはアクティブなメモリプラグインによって提供されます(デフォルト:
''memory-core'')。''plugins.slots.memory = "none"'' を使用してメモリプラグインを無効にします。
メモリファイル(Markdown)
デフォルトのワークスペースレイアウトは2つのメモリレイヤーを使用します:
- ''memory/YYYY-MM-DD.md''
- 日次ログ(追記のみ)。
- 今日と昨日はターンの開始時に読み込まれます。
- ''MEMORY.md''(オプション)
- キュレートされた長期メモリ。
- メインのプライベートセッションでのみ読み込まれます(グループコンテキストでは読み込まれません)。
これらのファイルはワークスペースの下にあります(''agents.defaults.workspace''、デフォルト
メモリに書き込むタイミング
- 決定、設定、永続的な事実は ''MEMORY.md'' に送ります。
- 日次ノートとランタイム環境は ''memory/YYYY-MM-DD.md'' に送ります。
- 誰かが「これを覚えておいて」と言ったら、書き留めてください(RAM に保持しないでください)。
- この領域はまだ進化中です。モデルにメモリを保存するよう思い出させるのに役立ちます。モデルは何をすべきかを知っています。
- 何かを永続化したい場合は、ボットにメモリに書き込むよう依頼してください。
自動メモリフラッシュ(圧縮前 ping)
セッションが自動圧縮に近づくと、OpenClaw は**サイレント、
エージェントターンは、モデルに**永続的なメモリを書き込む**
before the'' context is compacted. The default prompt explicitly states the model _may reply_,
通常は ''NO_REPLY'' が正しい応答であるため、ユーザーはこのターンを見ることはありません。
これは ''agents.defaults.compaction.memoryFlush'' によって制御されます:
{
agents: {
defaults: {
compaction: {
reserveTokensFloor: 20000,
memoryFlush: {
enabled: true,
softThresholdTokens: 4000,
systemPrompt: "Session nearing compaction. Store durable memories now.",
prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store.",
},
},
},
},
}Details:
- ソフトしきい値:セッショントークン推定値が超えるとフラッシュがトリガーされます
''contextWindow - reserveTokensFloor - softThresholdTokens''。
- ''デフォルトでサイレント'':プロンプトには ''NO_REPLY'' が含まれているため、何も配信されません。
- 2つのプロンプト:ユーザープロンプトとリマインダーが添付されたシステムプロンプト。
- ''圧縮サイクルごとに1回のフラッシュ''(''sessions.json'' で追跡)。
- ワークスペースは書き込み可能である必要があります:セッションがサンドボックスで実行されており、
''workspaceAccess: "ro"'' または ''"none"'' の場合、フラッシュはスキップされます。
完全な圧縮ライフサイクルについては、
''セッション管理 + 圧縮''を参照してください。
ベクトルメモリ検索
OpenClaw は ''MEMORY.md'' と ''memory/*.md'' の上に小さなベクトルインデックスを構築できます(
オプトインした追加のディレクトリやファイルを含む)。これにより、セマンティッククエリが関連する
ノートを見つけることができます。表現が異なる場合でも。
デフォルト:
- デフォルトで有効。
- メモリファイルの変更を監視(デバウンス)。
- デフォルトでリモート埋め込みを使用。''memorySearch.provider'' が設定されていない場合、OpenClaw は自動的に選択します:
1. ''local''(''memorySearch.local.modelPath'' が設定されており、ファイルが存在する場合)。
2. ''openai''(OpenAI キーを解決できる場合)。
3. ''gemini''(Gemini キーを解決できる場合)。
4. それ以外の場合、設定されるまでメモリ検索は無効のままです。
- ローカルモードは node-llama-cpp を使用し、''pnpm approve-builds'' が必要な場合があります。
- SQLite 内のベクトル検索を高速化するために sqlite-vec(利用可能な場合)を使用します。
リモート埋め込みには埋め込みプロバイダーの API キーが必要です。OpenClaw は
認証プロファイル、''models.providers.*.apiKey''、または環境
#
追加のメモリパス
デフォルトのワークスペースレイアウト外の Markdown ファイルをインデックス化する場合は、
agents: {
defaults: {
memorySearch: {
extraPaths: ["../team-docs", "/srv/shared-notes/overview.md"]
}
}
}明示的なパスを追加します:
Notes:
- パスは絶対パスまたはワークスペース相対パスにできます。
- ディレクトリ内の ''.md'' ファイルを再帰的にスキャンします。
#
Gemini 埋め込み(ネイティブ)
プロバイダーを ''gemini'' に設定して、Gemini 埋め込み API を直接使用します:
agents: {
defaults: {
memorySearch: {
provider: "gemini",
model: "gemini-embedding-001",
remote: {
apiKey: "YOUR_GEMINI_API_KEY"
}
}
}
}Notes:
- ''remote.baseUrl'' はオプションです(デフォルトは Gemini API ベース URL)。
- ''remote.headers'' は必要に応じて追加のヘッダーを追加できます。
- デフォルトモデル:''gemini-embedding-001''。
カスタムの OpenAI 互換エンドポイント(OpenRouter、vLLM、またはプロキシ)を使用する場合、
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
remote: {
baseUrl: "https://api.example.com/v1/",
apiKey: "YOUR_OPENAI_COMPAT_API_KEY",
headers: { "X-Custom-Header": "value" }
}
}
}
}OpenAI プロバイダーと一緒に ''remote'' 設定を使用できます:
API キーを設定したくない場合は、''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 は単一のバッチジョブで多くの埋め込みリクエストを送信し、OpenClaw に非同期で処理させることができるため、通常、最速のオプションです。
- OpenAI は Batch API ワークロードに対して割引価格を提供するため、大規模なインデックス作成は、同じリクエストを同期的に送信するよりも安価になることがよくあります。
メモリツールの仕組み
- ''memory_search'' は ''MEMORY.md'' + ''memory/**/*.md'' から Markdown チャンクをセマンティックに検索します(約 400 トークンターゲット、80 トークンオーバーラップ)。スニペットテキスト(最大 700 文字)、ファイルパス、行範囲、スコア、プロバイダー/モデル、およびローカル → リモート埋め込みからフォールバックしたかどうかを返します。完全なファイルペイロードは返しません。
- ''memory_get'' は特定のメモリ Markdown ファイル(ワークスペース相対)を読み取り、必要に応じて開始行から N 行を読み取ります。''MEMORY.md'' / ''memory/'' 外のパスは、''memorySearch.extraPaths'' に明示的にリストされている場合にのみ許可されます。
- 両方のツールは、エージェントの ''memorySearch.enabled'' が true に解決される場合にのみ有効になります。
#
何がインデックス化されるか(およびいつ)
- ファイルタイプ:Markdown のみ(''MEMORY.md''、''memory/**/*.md''、および ''memorySearch.extraPaths'' 下の ''memorySearch.extraPaths'' ファイル)。
- Index storage: Per-agent SQLite at ''~/.openclaw/memory/<agentId>.sqlite'' (configurable via ''agents.defaults.memorySearch.store.path'', supports ''{agentId}'' token).
- 鮮度:''MEMORY.md''、''memory/''、および ''memorySearch.extraPaths'' 上のウォッチャーはインデックスをダーティとしてマークします(デバウンス 1.5 秒)。同期はセッション開始時、検索時、または一定間隔でスケジュールされ、非同期で実行されます。セッショントランスクリプトはデルタしきい値を使用してバックグラウンド同期をトリガーします。
- 再インデックストリガー:インデックスは埋め込みプロバイダー/モデル + エンドポイントフィンガープリント + チャンキングパラメータを保存します。これらのいずれかが変更されると、OpenClaw は自動的にストア全体をリセットし、再インデックス化します。
#
ハイブリッド検索(BM25 + ベクトル)
有効にすると、OpenClaw は次を組み合わせます:
- ベクトル類似性(セマンティックマッチング、表現が異なる場合があります)
- BM25 キーワード関連性(ID、環境変数、コードシンボルなどの正確なトークン)
プラットフォームで全文検索がサポートされていない場合、OpenClaw は純粋なベクトル検索にフォールバックします。
##
なぜハイブリッドなのか?
ベクトル検索は「これは同じことを意味する」に優れています:
- 「Mac Studio ゲートウェイホスト」と「ゲートウェイを実行しているコンピューター」
- 「ファイル更新のデバウンス」と「書き込みごとのインデックス作成を回避」
しかし、正確で高シグナルのトークンでは弱い場合があります:
- ID(''a828e60''、''b3b9895a…'')
- コードシンボル(''memorySearch.query.hybrid'')
- エラー文字列(「sqlite-vec が利用できません」)
BM25(全文)は逆です。正確なトークンに強く、言い換えに弱いです。
ハイブリッド検索は実用的な中間の立場です。両方の検索シグナルを使用するため、
「自然言語」クエリと「針の中の針」クエリの両方で良好な結果が得られます。
##
結果をマージする方法(現在の設計)
実装の概略:
1. 両方の側から候補プールを取得します:
- ''ベクトル'':コサイン類似度による上位 ''maxResults * candidateMultiplier''。
- ''BM25'':FTS5 BM25 ランクによる上位 ''maxResults * candidateMultiplier''(低いほど良い)。
2. BM25 ランクを ~0..1 のスコアに変換します:
- ''textScore = 1 / (1 + max(0, bm25Rank))''
3. チャンク ID で候補を結合し、加重スコアを計算します:
- ''finalScore = vectorWeight * vectorScore + textWeight * textScore''
Notes:
- ''vectorWeight'' + ''textWeight'' は設定解決時に 1.0 に正規化されるため、重みはパーセンテージとして機能します。
agents: {
defaults: {
memorySearch: {
query: {
hybrid: {
enabled: true,
vectorWeight: 0.7,
textWeight: 0.3,
candidateMultiplier: 4
}
}
}
}
}#
埋め込みキャッシュ
OpenClaw は SQLite にチャンク埋め込みをキャッシュできるため、再インデックス化と頻繁な更新(特にセッショントランスクリプト)は変更されていないテキストを再埋め込みしません。
Configuration:
agents: {
defaults: {
memorySearch: {
cache: {
enabled: true,
maxEntries: 50000
}
}
}
}#
セッションメモリ検索(実験的)
''セッショントランスクリプト''のインデックス作成をオプトインし、''memory_search'' を介して表示できます。
これは実験的なフラグの後ろにあります。
agents: {
defaults: {
memorySearch: {
experimental: { sessionMemory: true },
sources: ["memory", "sessions"]
}
}
}Notes:
- セッションインデックス作成はオプトインです(デフォルトでオフ)。
- セッション更新はデバウンスされ、デルタしきい値を超えると非同期でインデックス化されます(ベストエフォート)。
- ''memory_search'' はインデックス作成でブロックしません。バックグラウンド同期が完了するまで、結果は少し古くなる場合があります。
- 結果にはスニペットのみが含まれます。''memory_get'' はメモリファイルに制限されます。
- セッションインデックスはエージェントごとに分離されています(そのエージェントのセッションログのみをインデックス化します)。
- Session logs are stored on disk (''~/.openclaw/agents/<agentId>/sessions/*.jsonl''). Any process/user with filesystem access can read them, so treat disk access as a trust boundary. For stricter isolation, run agents under separate OS users or hosts.
agents: {
defaults: {
memorySearch: {
sync: {
sessions: {
deltaBytes: 100000, // ~100 KB
deltaMessages: 50 // JSONL lines
}
}
}
}
}#
SQLite ベクトル高速化(sqlite-vec)
sqlite-vec 拡張機能が利用可能な場合、OpenClaw は埋め込みを
SQLite 仮想テーブル(''vec0'')に保存し、ベクトル距離クエリを
データベース内で実行します。これにより、すべての埋め込みを JS にロードせずに検索を高速に保ちます。
agents: {
defaults: {
memorySearch: {
store: {
vector: {
enabled: true,
extensionPath: "/path/to/sqlite-vec"
}
}
}
}
}設定(オプション):
Notes:
- ''enabled'' はデフォルトで true。無効にすると、検索はプロセス内の
保存された埋め込みのコサイン類似度にフォールバックします。
#
ローカル埋め込みの自動ダウンロード
- デフォルトのローカル埋め込みモデル:''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 互換エンドポイントの例
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
remote: {
baseUrl: "https://api.example.com/v1/",
apiKey: "YOUR_REMOTE_API_KEY",
headers: {
"X-Organization": "org-id",
"X-Project": "project-id"
}
}
}
}
}Notes:
- ''remote.*'' は ''models.providers.openai.*'' より優先されます。
- ''remote.headers'' は OpenAI ヘッダーとマージされます。キーの競合ではリモートが優先されます。''remote.headers'' を省略して OpenAI デフォルトを使用します。