検索エンジンで実現する動的エージェントメモリ
はじめに
AI エージェントが実用的なタスクをこなすには、過去の経験や知識を「メモリ(記憶)」として保持し、必要なときに取り出せる仕組みが不可欠です。もちろん、LLM のコンテキストウィンドウにすべてを詰め込むアプローチは、スケーラビリティとコストの両面で限界があります。そのため、外部メモリとしてデータを記録し、再利用するプラクティスが広まっています。既存のエージェントメモリにはいくつか課題があります。ベクトルDB偏重のデータストア、データ間の関係性理解の欠如、データ更新の観点・・・エージェントメモリはテキストベースの意味と関係性や変化を扱うため、リレーショナルデータベースやKVS、ベクトルDBでは表現しきれないデータ構造を持つことになります。
本記事では、ハイブリッド検索エンジンをバックエンドとした動的エージェントメモリシステム「DSE(Dynamic Search Engine for Agentic Memory)」のアーキテクチャを提唱します。DSE は Elasticsearch によるハイブリッド検索、Neo4j によるナレッジグラフ、Temporal による非同期ワークフローを組み合わせ、認知科学に基づく 4 種類のメモリを動的に管理します。
なお、DSEは筆者が(Claude Codeを使いながら)独自に実装したものになります。以下レポジトリで公開しています。
DSE: https://github.com/shibuiwilliam/dse
この記事ではDSEについて以下を解説します。
- AI エージェントにおけるメモリ管理の本質的な課題
- 検索エンジンベースのメモリアーキテクチャの設計思想
- BM25 + kNN ハイブリッド検索とグラフ展開を組み合わせたカスケード検索パイプライン
- Ebbinghaus 忘却曲線やベイズ更新を応用したメモリライフサイクル管理の実装方式
AI エージェントメモリの課題
コンテキストウィンドウの限界
現在の LLM ベースエージェントの多くは、会話履歴や外部知識をプロンプトに直接埋め込む方式を採用しています。しかし、この方式には根本的な問題があります。
コスト増大: メモリが蓄積するほどトークン消費が増え、API コストが線形に増加します。数千件のメモリを毎回すべてプロンプトに含めることは現実的ではありません。
検索精度の欠如: すべてのメモリを投入しても、LLM が「今のタスクに関連する記憶」を適切に選択できる保証はありません。無関係な情報はノイズとなり、推論精度を下げます。検索したいデータは意味ベースのテキストとなるため、RDBやKVS、ベクトルDB、RAGだけでは適切な検索の仕組みを実現することができません。
静的な知識管理: 従来のベクトルデータベースベースの RAG は「挿入したら終わり」です。メモリ同士の矛盾検出、古い情報の自動アーカイブ、知識の一般化といった動的な管理ができません。
人間の記憶との乖離
人間の記憶は単なるデータストアではありません。認知科学では、記憶は以下のように分類されます。
| 記憶タイプ | 定義 | エージェントでの例 |
|---|---|---|
| エピソード記憶 | 具体的な出来事・経験 | 「3/10 にデプロイしたらレイテンシが 20% 増加した」 |
| 意味記憶 | 事実・知識・一般化 | 「Python はインタプリタ言語である」 |
| 手続き記憶 | 手順・スキル・ルール | 「マージ前には必ず統合テストを実行する」 |
| 展望記憶 | 未来の意図・リマインダー | 「来週月曜にモデル精度を確認する」 |
これらは減衰速度も異なり、エピソード記憶は速く忘れ、手続き記憶は長く残ります。既存のメモリシステムはこうした認知的特性を考慮していません。
求められるメモリシステムの要件
上記の課題を解決するには、以下の要件を満たすメモリシステムが必要です。
- 動的検索: 蓄積量に依存せず、必要なメモリだけを低レイテンシで取得できること
- 多様な検索モード: キーワード一致、意味的類似度、関係性のグラフ探索を組み合わせられること
- ライフサイクル管理: メモリの生成・更新・圧縮・矛盾解決・アーカイブを自動化できること
- エージェント統合: AI エージェントが標準プロトコルでメモリ操作を行えること
提案手法:検索エンジンで実現する動的メモリ
DSE は「AI エージェントのメモリシステムを検索エンジンで実装する」というアプローチを取ります。この設計の核心は Retrieval-First の原則です。メモリの利用は常に検索を経由し、LLM のパラメトリックメモリに依存しません。
認知科学に基づくメモリモデル
DSE は前述の 4 種類のメモリを MemoryRecord というスキーマで統一的に管理します。各メモリには約 40 のフィールドがあり、コンテンツ・埋め込みベクトル・分類情報・信頼度・ライフサイクル情報・関係性を保持します。
メモリタイプごとに減衰率が異なり、Ebbinghaus の忘却曲線に基づく数式で自動管理されます。
base_decay = exp(-decay_rate × age_days)
access_boost = 1.0 + 0.1 × ln(1 + access_count_30d)
importance_factor = 0.5 + 0.5 × importance_score
decay_score = min(1.0, base_decay × access_boost × importance_factor)
エピソード記憶は 1 日あたり 0.05 の速度で減衰する一方、手続き記憶は 0.008 と緩やかです。展望記憶は条件が満たされるまで減衰しません。頻繁にアクセスされるメモリは「アクセスブースト」によって減衰が抑制されます。
5 層のストレージアーキテクチャ
DSE は単一のデータストアではなく、5 つのストレージを役割に応じて使い分けます。
| ストレージ | 技術 | 役割 |
|---|---|---|
| 検索インデックス | Elasticsearch 8.x | BM25 全文検索 + kNN ベクトル検索のハイブリッド検索 |
| ナレッジグラフ | Neo4j 5.x | メモリ間の 8 種類の関係性(矛盾・補完・因果など)を管理 |
| オブジェクトストレージ | GCS / MinIO | メモリ全文と来歴(Provenance)の永続化 |
| ワーキングメモリ | Redis 7.x | セッション内の短期記憶と API キャッシュ |
| ワークフローエンジン | Temporal | 書き込みサーガ・定期メンテナンス・知識発見の非同期実行 |
アーキテクチャ全体像
DSE のアーキテクチャ全体像を以下に示します。
データフロー:書き込みパス
メモリの書き込みは Temporal ワークフローによるサーガパターンで実現されます。各フェーズは独立にリトライ可能で、途中で失敗しても冪等なリトライにより最終的な一貫性が保証されます。
書き込み時の LLM エンリッチメントが重要なポイントです。エージェントが content_text だけを渡しても、DSE は自動で要約・タグ・エンティティ・重要度・メモリタイプを推論します。
データフロー:読み取りパス
読み取りは 3 段階のカスケード検索パイプラインを通ります。各段階は精度とレイテンシのトレードオフに基づいて選択されます。
| ステージ | レイテンシ | 手法 | ユースケース |
|---|---|---|---|
| Fast | < 50ms | ベクトル検索のみ | 高緊急度のクエリ |
| Precision | < 200ms | BM25 + kNN + RRF 統合 | 通常のクエリ(デフォルト) |
| Deep | < 1000ms | Precision + グラフ展開 | 関係性が重要な複雑なクエリ |
検索パイプラインのロジック
DSE の検索パイプラインは、クエリ前処理・カスケード検索・ランキング・コンテキスト組立の 4 段階で構成されます。
クエリ前処理
ユーザーのクエリは LLM によるインテント抽出を経て、検索に最適な形に変換されます。
インテント抽出では primary_intent(主な検索意図)、memory_types(対象メモリタイプ)、entities(固有名詞)、time_range(時間範囲)、urgency(緊急度)を推論します。
Reciprocal Rank Fusion(RRF)
Precision ステージでは BM25 全文検索とベクトル検索の結果を RRF で統合します。RRF はランキング手法の違いによるバイアスを排除するアルゴリズムです。
rrf_score(doc) = Σ 1 / (K + rank_i(doc) + 1)
i
ここで K = 60 はスムージング定数です。BM25 で 1 位、ベクトル検索で 3 位の文書は 1/(60+0+1) + 1/(60+2+1) = 0.032 のスコアを得ます。キーワードと意味の両面で関連性の高い文書が自然に上位に来る設計です。
マルチファクタースコアリング
RRF 後、各結果に対して 5 つの要素を組み合わせた最終スコアを算出します。
final_score = (
0.5 × rrf_score # 検索関連度
+ 0.3 × (confidence × decay) # 信頼度 × 鮮度
+ 0.2 × recency # 時間的近接度
+ exploration_factor # 多様性ボーナス
) × superseded_penalty # 置換済み → 0.1
× contradiction_penalty # 矛盾フラグ → 0.3
Recency(時間的近接度)は半減期 168 時間(1 週間)のシグモイド関数です。
recency = 1 / (1 + ln(age_hours / 168))
Exploration bonus(多様性ボーナス)はアクセス頻度が低いメモリを積極的に露出させます。これにより、埋もれた有用な記憶が発見される可能性が高まります。
グラフ展開(Deep ステージ)
Deep ステージでは、Precision の結果上位 5 件に対して Neo4j のグラフを 1 ホップ探索し、関連メモリを補強します。CONTRADICTS エッジはここでは除外され、矛盾する情報を誤って含めることを防ぎます。グラフ経由で発見されたメモリには 0.6 倍のスコア割引が適用されます。
コンテキスト組立
ランキング後の結果は、トークンバジェットに基づいて 3 段階のティアに振り分けられます。
| ティア | 条件 | 内容 | トークンコスト |
|---|---|---|---|
| Full | スコア > 0.8 かつ残バジェット ≥ 500 | オブジェクトストレージからの全文 | 可変 |
| Summary | 残バジェット ≥ 100 | LLM 生成の 500 文字以内の要約 | 約 250 トークン |
| Reference | 残バジェット ≥ 20 | [TYPE] ID: 要約抜粋 |
約 20 トークン |
これにより、限られたコンテキストウィンドウを最大限に活用しつつ、重要度の高いメモリに詳細な情報を割り当てます。
重要な実装方式
ナレッジグラフと 8 種類のエッジ
DSE のナレッジグラフは単なる補助データストアではなく、メモリの品質管理において中心的な役割を果たします。
| エッジ | 意味 | 生成トリガー |
|---|---|---|
SUPERSEDED_BY |
A は B に置き換えられた | 矛盾解決 |
COMPLEMENTS |
A と B で完全な情報になる | 矛盾チェック・関係発見 |
CONTRADICTS |
A と B は相反する | 矛盾チェック |
DERIVES |
A から B が推論・要約された | 意味圧縮(Semantic Compression) |
CAUSES |
A が B を引き起こした | 関係発見(LLM 分類) |
REFERENCES |
A は B を参照する | 関係発見(LLM 分類) |
HAS_CHILD |
A は B を包含する | 明示的な作成 |
TEMPORALLY_PRECEDES |
A は B より前の出来事 | Allen の区間代数 |
CONTRADICTS エッジは矛盾検出と品質管理に直結します。新しいメモリの書き込み時に、コサイン類似度が閾値(デフォルト 0.92)を超える既存メモリが見つかると、LLM が矛盾・補完・重複・無関係を判定します。自動解決可能な矛盾(信頼度の差が 0.30 以上)は自動で SUPERSEDED_BY エッジが作成され、それ以外は管理 UI のキューに送られます。
Semantic Compression(意味圧縮)
エピソード記憶は時間とともに蓄積されますが、個別の経験よりも「そこから何を学んだか」の方が長期的な価値があります。Semantic Compression は、類似したエピソード記憶のクラスタを一般化された意味記憶に圧縮するプロセスです。
実装では、HDBSCAN クラスタリングで埋め込みベクトルの類似度が 0.75 以上のエピソードをグループ化し、LLM で一般化した要約を生成します。生成された意味記憶と元のエピソード間には DERIVES エッジが作成され、来歴が追跡可能な状態を保ちます。
Confidence のベイズ更新
各メモリの信頼度(Confidence)は固定値ではなく、証拠に基づいてベイズ的に更新されます。
| 証拠タイプ | 効果 |
|---|---|
| 裏付け情報源(独立) | +0.225(基本値 0.15 × 1.5) |
| 裏付け情報源(同一) | +0.105(基本値 0.15 × 0.7) |
| 矛盾する情報源 | -0.20 |
| ユーザーの明示的修正 | 指定値に強制 |
| 繰り返し参照 | +0.05 |
| 時間経過 | -0.01 |
| 関係性推論からの派生 | -0.05 |
独立した情報源からの裏付けには 1.5 倍、同一情報源には 0.7 倍の乗数が適用されます。ユーザーの明示的修正はベイズ更新をバイパスし、値を直接設定します。これにより「ユーザーが常に正しい」という原則が実装に反映されています。
MCP によるエージェント統合
DSE は Model Context Protocol(MCP)サーバーを提供し、AI エージェントが標準プロトコルでメモリ操作を行えるようにしています。14 種類のツールが利用可能です。
MCP の store_memory ツールは特に重要です。エージェントが namespace と content_text だけを渡すと、DSE は自動で以下を実行します。
- LLM によるメタデータ推論(要約・タグ・エンティティ・重要度・メモリタイプ)
- 埋め込みベクトルの生成
- Elasticsearch へのインデックス登録
- Neo4j へのグラフノード登録
- 矛盾チェックワークフローの起動
エージェント側の実装負担を最小限に抑えつつ、高品質なメモリ管理を提供する設計です。
Temporal によるワークフロー管理
DSE のバックグラウンド処理は Temporal のワークフローとして実装されています。3 つのタスクキューで関心事を分離し、独立にスケーリング可能です。
| タスクキュー | ワークフロー | スケジュール |
|---|---|---|
dse-main |
MemoryWriteWorkflow, ProspectiveScanWorkflow | リアルタイム / 毎分 |
dse-maintenance |
DailyMaintenanceWorkflow, SemanticCompressionWorkflow | 毎日 / 毎週 |
dse-discovery |
RelationDiscoveryWorkflow, TemporalEdgeBuildWorkflow | 毎日 |
DailyMaintenanceWorkflow は Ebbinghaus 忘却曲線に基づく Decay スコアの再計算と、スコアが 0.2 を下回ったメモリの自動アーカイブを実行します。RelationDiscoveryWorkflow は埋め込みベクトルの類似度でメモリペア候補を抽出し、LLM で関係タイプを分類してグラフエッジを自動生成します。
使い方
DSE はオープンソースで公開されています。ここでは、ローカル環境での起動からエージェント統合までの手順を紹介します。
リポジトリ: https://github.com/shibuiwilliam/dse
前提条件
以下のツールが必要です。
- Python 3.13+ と uv
- Node.js 22+ と pnpm 9+(ダッシュボード用)
- Docker と Docker Compose v2
- Gemini API キー(オフライン開発時は不要)
セットアップと起動
リポジトリをクローンし、環境変数を設定します。
git clone https://github.com/shibuiwilliam/dse
cd dse
cp .env.example .env
.env ファイルを編集し、最低限 GEMINI_API_KEY を設定してください。Gemini API を使わずにオフラインで試す場合は USE_MOCK_LLM=true を設定します。
すべてのサービスをワンコマンドで起動します。
make run-all
このコマンドは Docker サービス(Elasticsearch、Neo4j、Redis、Temporal、MinIO、Redpanda)の起動、Python パッケージのインストール、データベースの初期化、そして API サーバー・Temporal ワーカー・MCP サーバー・フロントエンドの起動をまとめて行います。
起動後、以下の URL でアクセスできます。
| サービス | URL |
|---|---|
| API サーバー(OpenAPI ドキュメント) | http://localhost:8000/docs |
| MCP サーバー | http://localhost:8001/mcp |
| 管理ダッシュボード | http://localhost:3000 |
| Temporal UI(ワークフロー監視) | http://localhost:8080 |
| Neo4j Browser(グラフ確認) | http://localhost:7474 |
メモリを保存する
REST API でメモリを保存します。content_text だけ渡せば、要約・タグ・エンティティ・重要度は LLM が自動推論します。
curl -X POST http://localhost:8000/v1/memories \
-H "Content-Type: application/json" \
-d '{
"namespace": "user:engineer",
"content_text": "Python 3.13 で型パラメータの構文が導入され、ジェネリクスの記述が簡潔になった",
"memory_type": "semantic",
"source_type": "user_explicit"
}'
メモリを検索する
カスケード検索パイプラインを通じて、トークンバジェットに収まるコンテキストパッケージを取得します。
curl -X POST http://localhost:8000/v1/memories/retrieve \
-H "Content-Type: application/json" \
-d '{
"query": "Python の最新の型システム機能は?",
"namespace": "user:engineer",
"token_budget": 2000,
"cascade_stage": "precision"
}'
レスポンスにはスコア順にメモリが並び、トークンバジェットに応じて全文・要約・参照の 3 段階で内容が返ります。このレスポンスをそのままエージェントのプロンプトに注入できます。
サンプルデータを投入する
リポジトリにはサンプルデータセットが付属しています。bulk_load.py スクリプトで一括登録できます。
python scripts/bulk_load.py data/engineer-memory.jsonl
PDF やテキストファイルからメモリを生成することも可能です。セマンティックチャンキングで文書を分割し、各チャンクをメモリとして登録します。
python scripts/ingest_document.py data/your-document.pdf --namespace user:engineer
定期ワークフローを登録する
Semantic Compression や Relation Discovery などの自律的改善ワークフローを有効にするには、Temporal にスケジュールを登録します。
make register-schedules
Elasticsearch 内の既存ネームスペースを自動検出し、ネームスペースごとにスケジュールを登録します。
Claude Desktop / Claude Code から使う
MCP サーバーを通じて、Claude Desktop や Claude Code から DSE を直接利用できます。Claude Desktop の場合、設定ファイルに以下を追加します。
{
"mcpServers": {
"dse": {
"command": "uv",
"args": ["run", "--directory", "/path/to/dse/backend", "python", "-m", "dse.mcp"],
"env": {
"GEMINI_API_KEY": "your-key"
}
}
}
}
Claude Code の場合は、プロジェクトの .mcp.json に同様の設定を記述します。設定後、Claude は retrieve_memories、store_memory などの 14 種類のツールを自動的に認識し、会話の中でメモリの保存と検索を行えるようになります。
Example Chat で体験する
DSE にはサンプルチャットアプリ(example-chat/)が付属しています。Claude Agent SDK + DSE MCP を組み合わせた AI チャットで、会話の中でメモリの保存と検索がリアルタイムに行われます。すべての会話ターンは自動で DSE に記録されるため、セッションをまたいでも「前回何を話したか」を Claude が記憶しています。
DSE が make run-all で起動済みの状態で、以下を実行します。
cd example-chat
npm install
cp .env.example .env
# .env を編集: ANTHROPIC_API_KEY を設定
バックエンド(Express サーバー)とフロントエンド(Vite + React)を起動します。
# ターミナル 1: バックエンド(ポート 4000)
npm run dev
# ターミナル 2: フロントエンド(ポート 4001)
npm run dev:client
http://localhost:4001 をブラウザで開くとチャット画面が表示されます。左のサイドバーには Claude が DSE のどのツールを使ったか(メモリ検索・保存・グラフ探索など)がリアルタイムで表示されます。
管理ダッシュボードで可視化する
http://localhost:3000 の管理ダッシュボードでは、メモリの検索・ナレッジグラフの可視化・矛盾の解決・Semantic Compression の実行などを GUI で操作できます。サイドバーでネームスペースを選択すると、すべてのページが自動でフィルタリングされます。
まとめ
DSE は「AI エージェントのメモリを検索エンジンで実現する」というアプローチにより、従来のベクトルデータベースベースや RAG によるエージェントメモリが抱える課題を解決することを目指します。
-
カスケード検索パイプライン: BM25 全文検索、kNN ベクトル検索、ナレッジグラフ展開を 3 段階のカスケードで組み合わせ、精度とレイテンシのバランスを動的に制御します。RRF によるスコア統合とマルチファクターランキングにより、単一の検索手法では得られない検索品質を実現しています。
-
認知科学に基づくライフサイクル管理: Ebbinghaus 忘却曲線による自動減衰、ベイズ更新による信頼度管理、HDBSCAN + LLM による Semantic Compression が、人間の記憶のように「忘れるべきものは忘れ、一般化すべきものは一般化する」メモリの自律的な品質向上を実現しています。
-
ナレッジグラフによる品質保証: 8 種類のエッジタイプによる矛盾検出・自動解決、来歴追跡(Provenance)、関係性の自動発見が、メモリの整合性と信頼性を維持します。
DSE はレポジトリを公開しており、MCP サーバーを通じて Claude Desktop や Claude Code などの AI エージェントから直接利用することもできます。make run-all 一発ですべてのローカルサービスが起動することができます。







