OpenClaw/Codexで記憶検索を実装した流れ
この記事では、OpenClaw上のCodex系エージェントに記憶検索を実装した時の流れをまとめます。
単なる設定手順ではなく、「なぜ記憶検索を入れることにしたのか」「どの設定を追加したのか」「OpenAI APIキーを通常会話や画像生成向けには使わず、記憶検索用途に限定した点」を時系列で整理します。
実際のサーバー名、絶対パス、APIキー、ユーザーIDなどはすべてダミー化しています。自分の環境では適宜読み替えてください。
検討の出発点は、エージェントの長期記憶をどう扱うかでした。
ChatGPT PlusをOpenClaw経由で使用しているとき、度々、AIから
「記憶検索はインデックス不一致で使えなかった」
と出ていました。そのため時間が空いたタスクだと前のことを覚えていないことがしばしば。別運用しているGeminiと比べて差があるように感じていました。
OpenClawのワークスペースには、長期記憶用の MEMORY.md や、日次メモを置く memory/YYYY-MM-DD.md のようなファイルがあります。これらはエージェントの継続性には便利ですが、毎回の会話コンテキストに丸ごと入れると問題があります。
- 記憶ファイルが大きくなるほどコンテキストを圧迫する
- 毎回必要とは限らない情報までモデルに渡してしまう
- グループチャットでは、私的な記憶を不用意に混ぜたくない
- 過去ログや日次メモを必要な時だけ探せる方が扱いやすい
そこで、長期記憶を常時貼り込むのではなく、必要になった時だけ検索して読む方式にすることを検討しました。
方針:MEMORY.mdは貼らず、検索ツールで読む
採用した方針はシンプルです。
MEMORY.mdは通常の起動コンテキストには貼り込まない- 記憶が必要な質問の時だけ
memory_searchを使う - 検索結果から必要な行だけ
memory_getで読む - 検索にはEmbeddingモデルを使う
- Embedding用APIキーは、記憶検索専用として分離する
これにより、普段の会話は軽く保ちつつ、過去の決定や作業ログが必要な時には検索できる構成になります。
実装前の状態
実装前の設定では、通常会話で使うモデル設定はありましたが、記憶検索用の設定はありませんでした。
ダミー化した例です。
{
"agents": {
"defaults": {
"workspace": "/home/example/.openclaw/workspace",
"model": {
"primary": "openai/gpt-5.5"
},
"models": {
"openai/gpt-5.5": {
"params": {
"cacheRetention": "long"
}
}
}
}
}
}
この時点では memorySearch は未設定です。
また、シークレットproviderも通常のOpenClaw用providerだけで、Embedding専用providerはありませんでした。
{
"secrets": {
"providers": {
"openclawfile": {
"source": "file",
"path": "/home/example/.openclaw/secrets.json",
"mode": "json"
}
}
}
}
APIキーの扱いを先に決めた
記憶検索にはEmbedding APIが必要です。今回はOpenAI互換のEmbedding APIを使うことにしました。
APIキーはCharGPT Plusの契約とは別に、OpenAI Platformで$5課金して取得していますが、AI曰く記憶検索だけの用途であれば、数円レベルのコストだそうで、実際今回の設定中は$0.01しか使用されませんでした。
ただし、ここで重要なのは、追加するAPIキーを通常会話や画像生成向けのOpenAI providerには入れない、という点です。
これはセキュリティ上の分離だけでなく、課金コストを管理するためでもあります。通常会話や画像生成まで同じAPIキーで使えるようにすると、意図せず利用範囲が広がり、想定以上のAPI利用料につながる可能性があります。
今回は「記憶検索に必要なEmbeddingだけに使う」と決めることで、API利用の目的とコスト発生範囲を絞りました。
つまり、次のように用途を分けました。
- 通常会話:既存のモデル設定・既存の認証方式を使う
- 画像生成:今回追加するEmbedding用APIキーは使わない
- 記憶検索:新しく作る
embeddingsprovider のAPIキーだけを使う
設定上も、models.providers.openai.apiKey は未設定のままです。通常会話や画像生成向けのOpenAI providerには、今回のAPIキーを入れていません。
この分離により、Embedding APIキーの用途が記憶検索に限定されます。
結果として、通常会話や画像生成でAPIコストが増える心配を避けつつ、記憶検索に必要な最小限の範囲だけでAPIを使う構成になります。
Embedding専用のシークレットファイルを作る
次に、Embedding用APIキーを専用ファイルに置きます。
ダミー化した保存先の例です。
/home/example/.openclaw/secrets/openai-embeddings.json
中身は次のようなJSONにします。
{
"OPENAI_EMBEDDINGS_API_KEY": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
このファイルは、通常会話用の認証情報とは別にしておきます。設定の見通しがよくなり、後から用途を確認しやすくなります。
secrets.providersにembeddingsを追加する
OpenClawの設定ファイルに、Embedding専用のproviderを追加します。
設定ファイルの例です。
/home/example/.openclaw/openclaw.json
追加後のイメージは次の通りです。
{
"secrets": {
"providers": {
"openclawfile": {
"source": "file",
"path": "/home/example/.openclaw/secrets.json",
"mode": "json"
},
"embeddings": {
"source": "file",
"path": "/home/example/.openclaw/secrets/openai-embeddings.json",
"mode": "json"
}
}
}
}
ここで追加した embeddings は、後で memorySearch.remote.apiKey.provider から参照します。
agents.defaults.memorySearchを追加する
次に、エージェントのデフォルト設定へ memorySearch を追加します。
{
"agents": {
"defaults": {
"workspace": "/home/example/.openclaw/workspace",
"model": {
"primary": "openai/gpt-5.5"
},
"models": {
"openai/gpt-5.5": {
"params": {
"cacheRetention": "long"
}
}
},
"memorySearch": {
"provider": "openai-compatible",
"model": "text-embedding-3-small",
"remote": {
"baseUrl": "https://api.openai.example/v1/",
"apiKey": {
"source": "file",
"provider": "embeddings",
"id": "/OPENAI_EMBEDDINGS_API_KEY"
}
}
}
}
}
}
ポイントは、apiKey.provider が embeddings になっていることです。
通常会話用のモデル設定である model や models には、今回のAPIキーを入れていません。追加したAPIキーは memorySearch からだけ参照されます。
MEMORY.mdを直接貼らないようにする
記憶検索を入れるだけではなく、Codex側の扱いも整理しました。
MEMORY.md は、通常の指示ファイルとして全文を貼るのではなく、「記憶ファイルが存在する」という参照情報だけを持たせます。
Codexには、必要な時に次の流れで記憶を読むようにします。
1. 記憶が必要な質問か判断する
2. 必要なら memory_search を使う
3. 検索結果から該当ファイルと行番号を確認する
4. memory_get で必要な行だけ読む
5. 読んだ内容を回答に反映する
これで、記憶を使うべき時だけ外部記憶を参照する動きになります。
再起動して設定を反映する
設定を変更した後は、OpenClawのGatewayを再起動して反映します。
systemdで動かしている場合の例です。
sudo systemctl restart openclaw-gateway
sudo systemctl status openclaw-gateway
再起動後は、JSON構文エラーとシークレット参照エラーが出ていないか確認します。
jq . /home/example/.openclaw/openclaw.json > /dev/null
journalctl -u openclaw-gateway -n 100 --no-pager
実装後の確認
実装後は、Codexの会話内で memory_search と memory_get が使えるか確認します。
例えば、過去に決めたブログ出力パターンを聞くような質問をします。
以前決めたWordPress記事作成パターンを確認して
正しく動いていれば、Codexはまず memory_search で関連する記憶を探し、必要に応じて memory_get で該当行だけを読みます。
実際に、日次メモから「パターンAはWordPress記事用、実パスやファイル名はダミー化、見出しはH2始まり」という内容を検索できるようになりました。
最終的な構成
最終的な構成は次のようになります。
OpenClaw
├── 通常会話
│ └── 既存の model / models 設定を使う
├── 画像生成
│ └── 今回追加したEmbedding用APIキーは使わない
├── 記憶検索
│ ├── agents.defaults.memorySearch
│ ├── provider: openai-compatible
│ ├── model: text-embedding-3-small
│ └── secrets.providers.embeddings を参照
└── 長期記憶
├── MEMORY.md
└── memory/YYYY-MM-DD.md
この構成では、OpenAI互換APIのキーは memorySearch のEmbedding用途にだけ使われます。
models.providers.openai.apiKey は未設定のままにし、通常会話や画像生成向けのOpenAI providerにはキーを入れていません。
実装してよかった点
- 長期記憶を毎回コンテキストに入れずに済む
- 必要な時だけ過去メモを検索できる
- 記憶ファイルが増えても通常会話のコンテキストを圧迫しにくい
- グループチャットで余計な私的記憶を混ぜにくくなる
- Embedding用APIキーの用途を記憶検索に限定できる
注意点
記憶検索は、メモが存在していて初めて役に立ちます。重要な決定や再利用したい手順は、日次メモや長期記憶に明示的に書いておく必要があります。
また、APIキーの用途を限定したい場合は、設定上もproviderを分けるのが大事です。通常会話用、画像生成用、記憶検索用を同じ場所に混ぜると、後から「このキーは何に使われているのか」が分かりにくくなります。
課金コストの面でも、用途別にproviderを分けておくと管理しやすくなります。特に画像生成は1回あたりのコストが大きくなりやすいため、Embedding用APIキーとは明確に分けておく方が安心です。
まとめ
今回の実装では、長期記憶を毎回読み込む方式から、必要な時だけ検索して読む方式へ切り替えました。
実装の要点は次の通りです。
- 記憶を毎回コンテキストに入れる運用を見直した
- Embedding APIを使った
memorySearchを追加した - Embedding専用の
embeddingsproviderを作った - APIキーは記憶検索用途だけに限定した
- 課金コストを抑えるため、通常会話や画像生成には今回のAPIキーを使わない構成にした
models.providers.openai.apiKeyは未設定のままにした- 通常会話や画像生成向けのOpenAI providerにはキーを入れなかった
memory_searchとmemory_getで必要な記憶だけ読む形にした
この形にすると、エージェントの継続性を保ちながら、コンテキストとAPIキーの用途を整理できます。

