言語を切り替える
テーマを切り替える

AI Agent のメモリ管理:長期記憶とナレッジガバナンス実践

「この前お願いした、あの注文の件はどうなった?」

ユーザーがそう尋ねた瞬間、カスタマーサポートの Agent は固まってしまいました。いまの会話のコンテキストをいくら探しても、「注文」に関する記録は見つかりません。あの照会は昨日の午後、別の会話セッションで行われたものだったからです。

これはバグではありません。記憶喪失です。

この問題に初めて出くわしたときは、かなり厄介でした。Agent の受け答えは見事で、ユーザー体験も悪くない。ところがユーザーがウィンドウを切り替えたり、ブラウザを閉じたり、数時間あけて戻ってくるだけで、すべてがゼロに戻ってしまうのです。Agent はユーザーの好みを覚えていない、過去に下した判断も覚えていない、ましてやなぜそう判断したのかも覚えていません。

さらに厄介なのは、コンテキストウィンドウをただ広げるだけでは解決しないことです。むしろ——信じられないかもしれませんが——Agent はより愚かになります。これがいわゆる「コンテキスト腐敗」です。無関係な情報がノイズのようにモデルの注意を薄め、検索コストは指数的に膨らみ、遅延は数百ミリ秒から十数秒へと跳ね上がります。

では、Agent はどうすれば本当に「覚える」ことができるのか。会話をデータベースに保存すればよい、という単純な話ではありません。人間のように、大事なことは覚え、些細なことは忘れ、必要なときに思い出し、判断のときには理由をたどれる。そんな記憶が必要です。

この記事では、Agent のメモリシステムの根底にあるロジックを解きほぐします。3 種類の記憶タイプ(多くの人は 2 つしか知りません)、6 大主流フレームワークの選定比較、ナレッジグラフがベクトル DB の盲点をどう補うか、そして実戦で踏み抜いた落とし穴まで取り上げます。

なぜ Agent には独立したメモリシステムが必要なのか

コンテキスト腐敗:大きいウィンドウほど逆に悪化する

まずは LOCOMO ベンチマーク(Agent の記憶能力を評価する権威あるデータセット)から、いくつかの数字を見てみましょう。

72.9%
Full-context の精度
ただし遅延 9.87s
66.9%
Mem0 の精度
遅延はわずか 0.71s
13 倍
Token 消費量の差
26K vs 約 2K
10 秒
ユーザーの待ち時間
全量コンテキスト方式
Source: LOCOMO ベンチマーク

一見すると、Full-context のほうが精度は高い。でも、10 秒も待てますか?さらに重要なのは、Token 消費量が 13 倍も違うことです。GPT-4 の料金で換算すると、1 回の会話でコンテキストだけで数十円が燃えていきます。

なぜウィンドウが大きいほど、効果がかえって落ちることがあるのでしょうか。

たとえてみましょう。図書館で 1 冊の本を探すとします。蔵書が 10 冊なら、ひと目で見つかります。蔵書が 10 万冊あると——たとえ全部の表紙が同時に見えたとしても——目当ての本を探し出すのに長い時間がかかります。

モデルの注意機構も同じです。コンテキストウィンドウに情報を詰め込むほど、1 件あたりに割けるモデルの注意は少なくなります。無関係な過去の会話、古いタスクの状態、すでに解決済みの問題……それらがすべて一緒くたに押し込まれ、モデルはかえって何が重要なのか見分けられなくなるのです。

これがコンテキスト腐敗です。情報が多いほど、S/N 比は下がります。

以前こんな実験をしました。100 ターンの会話のあとで、第 1 ターンで触れたある細部を Agent に答えさせるのです。結果はどうだったか。全量コンテキストの精度は 90% から 60% へ落ちました。一方、メモリシステムを使った方式では、精度は 85% 以上で安定していました。

「ツール」から「パートナー」へ:会話の境界を越える記憶

記憶のない Agent は、せいぜい高機能なツールにすぎません。使い終われば、あなたのことを忘れてしまいます。

記憶のある Agent こそ、本当の意味で「パートナー」になれます。あなたが簡潔な回答を好むことを覚え、前にも似た質問をしたことを覚え、プロジェクトで使っているのが Vue ではなく React だと知っている。こうした情報を毎回伝え直す必要がなくなります。

Letta チーム(MemGPT の開発元)が示した好例があります。長期間動き続けるプログラミングアシスタントです。あなたのプロジェクトのコードスタイルを覚え、過去に遭遇したバグとその解決策を覚え、さらにはよく使うサードパーティライブラリまで覚えています。「同じような関数をもう 1 つ書いて」と頼めば、その「同じような」が何を指すのかを理解できます。前回書いたあの関数を覚えているからです。

このセッションをまたいだ連続性こそ、Agent が「ツール」から「パートナー」へ進化するための土台です。

3 つの中核的な記憶タイプ:短期・長期・推論(多くの人が 3 つ目を見落としている)

Agent の記憶というと、多くの人は短期記憶と長期記憶しか思い浮かべません。でも実はもう 1 つ——Reasoning Memory(推論記憶)があり、ほとんどのシステムがまさにこれを欠いています。

1 つずつ説明しましょう。

短期記憶(Short-term Memory):いまのコンテキストウィンドウそのものです。容量が限られ、情報が新鮮で、会話の終了とともに消えるのが特徴です。RAM のようなもので、電源を切れば消えてしまいます。

長期記憶(Long-term Memory):外部ストレージに保存される情報で、ベクトルデータベース、リレーショナルデータベース、ナレッジグラフのいずれでもかまいません。容量が大きく、永続化でき、検索に対応するのが特徴です。ハードディスクのように、いつでも読み書きできます。

推論記憶(Reasoning Memory):これが最も見落とされがちです。記録するのは Agent の意思決定の過程——なぜ B ではなく A を選んだのか、そのときの制約条件は何だったのか、途中の推論チェーンはどうだったのか。推論記憶がなければ、Agent は判断を下しても「なぜ」を説明できません。これは説明可能性、デバッグ、継続的な学習のいずれにとっても非常に重要です。

Neo4j の技術ブログに、的を射た一節があります。「実行するだけで意思決定の過程を説明できない Agent は、仕事はこなすが振り返りをしない社員のようなものだ。短期的には問題なくても、長期的には必ず破綻する」。

私が見てきたフレームワークのうち、推論記憶を実装しているのはごく一部(Letta や Zep など)だけです。大半はまだ「会話をベクトル DB に保存する」段階にとどまっています。

Agent メモリの認知アーキテクチャ

4 層の記憶モデル

オペレーティングシステムや認知科学の設計を参考に、現代の Agent メモリシステムは通常、階層型アーキテクチャを採用します。最も代表的なのが Letta/MemGPT の 4 層モデルです。

Layer 1: Message Buffer(メッセージバッファ)
    ↓ あふれたら圧縮
Layer 2: Core Memory(コアメモリ)
    ↓ 能動的に書き込み
Layer 3: Recall Memory(リコールメモリ)
    ↓ 必要に応じて検索
Layer 4: Archival Memory(アーカイブメモリ)

Message Buffer:いまの会話のコンテキストウィンドウで、容量に限りがあります(たとえば 4K や 8K Token)。バッファが満杯に近づくと、システムは古いメッセージを要約に圧縮し、新しいメッセージのための空きを作ります。

Core Memory:丁寧に管理された小さな「ワーキングメモリ」で、いまのタスクに最も関連する情報を保持します。たとえばユーザーの好み、現在の目標、直近の意思決定などです。容量は数百〜数千 Token ほどで、コンテキストウィンドウ内に保持され、モデルが生成のたびに必ず見られるようにします。

Recall Memory:過去の会話のベクトルストレージです。Agent が「前回ユーザーは何を尋ねたか」を思い出す必要があるとき、ここから検索します。検索条件は意味的な類似度でもよいし、時間範囲やキーワードなどでもかまいません。

Archival Memory:長期アーカイブのストレージで、「将来役立つかもしれないが、いまは必要ない」情報を置きます。たとえば半年前のユーザーとの会話や、すでに完了したタスクの記録などです。

この階層設計の利点は何でしょうか。たとえてみましょう。あなたがコードを書いているとき、Core Memory はあなたの頭とエディタで開いている数個のファイル、Recall Memory は Git 履歴やプロジェクトのドキュメント、Archival Memory はパソコンの中の他のプロジェクトやネット上の資料庫にあたります。階層が近いほどアクセスは速いが容量は小さく、階層が遠いほど容量は大きいがアクセスは遅くなります。

MemGPT のオペレーティングシステム的な管理

MemGPT(現在は Letta)の設計思想は実に興味深いものです。Agent のメモリ管理を、OS のメモリ管理になぞらえています。

OS では RAM は有限で、ハードディスクは無限です。RAM が足りなくなると、システムは一部のデータをディスクにスワップし、必要になったら読み込み直します。

MemGPT も同様の設計をしています。

  • RAM = コンテキストウィンドウ(有限・高価・高速)
  • Disk = 外部ストレージ(無限・安価・低速)

Agent には「自己管理」の仕組みがあります。OS がページテーブルを管理するのと同じように、コンテキストウィンドウ内に「Core Memory Block」を保持します。Core Memory が満杯になると、Agent は能動的に一部の情報を外部ストレージへ「退避」させ、アーカイブした情報が必要になれば、外部ストレージから能動的に「呼び戻し」ます。

この設計の肝は、何を残し、何を消し、何を調べるかを Agent 自身が決める点にあります。ルールでハードコーディングするのではなく、いまのタスクに応じて Agent が動的に調整するのです。

具体例を挙げましょう。Core Memory Block のデータ構造はこうなっています。

{
  "label": "user_preferences",
  "description": "ユーザーの好みの設定",
  "value": "簡潔な回答を好む、日本語を好む、よく React を使う",
  "limit": 2000
}

limit に近づくと、Agent は次のいずれかを選べます。圧縮(重要な情報を抽出する)、分割(複数の Block に分ける)、あるいは退避(Archival Memory へ移す)です。

Sleep-time Compute:非同期のメモリ処理で応答をブロックしない

これは Letta が提案した、とても巧妙な設計です。

従来のやり方では、会話が終わるたびに即座に記憶を処理します——重要な情報を抽出し、ベクトルインデックスを更新し、要約を生成する。これでは応答がブロックされ、ユーザーは待たされます。

Sleep-time Compute のやり方はこうです。会話の最中は、まず生データをキューに放り込み、すぐに応答を返します。そして Agent が「アイドル状態(sleep)」になったときに、ゆっくり記憶を処理するのです。

利点は明確です。

  1. ユーザーが感じる遅延が大幅に減る
  2. より複雑な記憶処理(たとえばナレッジグラフの構築)を、タイムアウトを気にせずに実行できる
  3. バッチ処理のほうが効率が高く、コストも低い

もちろん、記憶の更新に遅れが出るという代償もあります。大半のシーン(カスタマーサポート、アシスタント、プログラミングのパートナー)では、数秒から数分の遅れは許容できます。ただし、リアルタイムの記憶が必要なシーン(たとえばリアルタイム会話中の感情認識)にはあまり向きません。

記憶の退避と再帰的要約:70% を残して連続性を確保する

コンテキストウィンドウが満杯になったとき、何を消して何を残すかをどう決めればよいでしょうか。

シンプルな戦略の 1 つが再帰的要約です。古い会話を 1 段落の要約に圧縮し、中核となる情報を残して詳細を捨てます。

しかし問題が出てきます。どれくらい圧縮すれば適切なのか。圧縮しすぎれば重要な情報が失われ、圧縮が足りなければ空きが足りないままです。

Letta チームの実験データが参考値を示しています。情報量の 70% を残すのが、連続性と圧縮率の最適なバランス点だというものです。

具体的にはどうするのか。いまコンテキストウィンドウに 100 件のメッセージがあり、満杯になったと仮定します。

  1. 前半 50 件のメッセージを 500 Token の要約に圧縮する
  2. 要約には、ユーザーの目標、主要な制約、重要な意思決定、未解決の問題を残す
  3. 生データは Archival Memory に移し、後で必要になれば調べられるようにする
  4. 新しいコンテキストウィンドウ = 要約 + 後半 50 件のメッセージ + 新しいメッセージ

こうすれば、連続性を確保しつつ(Agent は以前に何が起きたかを把握できる)、空きも解放できます(会話を続けられる)。

ナレッジガバナンス:記憶のライフサイクル管理

記憶は「入れたら終わり」ではありません。捕捉、圧縮、保存、検索、減衰、クリーンアップというライフサイクルがあります。それぞれの段階に戦略が必要です。

3 種類の記憶の TTL 戦略:ユーザーの好み vs タスク状態 vs 操作ログ

TTL(Time To Live、生存時間)は、記憶管理の中核となるパラメータです。記憶のタイプによって、TTL はまったく異なります。

ユーザー長期記憶:TTL は無限、あるいは極めて長い(数年)。たとえばユーザーの名前、好み、よく使うツール、技術スタックの選択など。こうした情報はめったに変わらないので、長期間保持すべきです。

タスク記憶:TTL は設定可能(時間〜日単位)。たとえばいまのプロジェクトのコンテキスト、直近のバグ記録、進行中の意思決定など。タスクが終われば、記憶はクリーンアップまたはアーカイブできます。

イベント記憶:TTL は短い(分〜時間単位)。たとえばいまの会話ターン、一時的な計算結果、検索したばかりの情報など。使い終われば捨ててかまいません。

すべての記憶を 1 つのベクトル DB に放り込み、TTL の区別をまったくしていないプロジェクトを少なからず見てきました。結果として、ベクトル DB はどんどん大きくなり、検索はますます遅くなり、しかも古くて無関係な情報を山ほど呼び戻してしまいます。

合理的なやり方は、3 つの異なるストレージを使い、それぞれに異なる TTL とクリーンアップ戦略を設定することです。

ユーザー長期記憶 → ベクトルデータベース(TTL なし、定期的に圧縮)
タスク記憶 → リレーショナル DB + ベクトル(TTL はタスクのサイクルに合わせる)
イベント記憶 → メモリまたは Redis(TTL は短く、自動で期限切れ)

要約・圧縮の技術:200 字の構造化サマリー

100 ターンの会話を 1 段落の要約に圧縮する。聞くと簡単そうですが、実際にやると細部が多くあります。

要約が単純すぎると情報が失われ、複雑すぎるとモデルが読み解けません。

Letta の実践は、効果の高い構造化テンプレートを示しています。

{
  "goals": ["ユーザーが達成したいこと"],
  "constraints": ["ユーザーの制約条件"],
  "decisions": ["Agent が下した意思決定"],
  "open_questions": ["まだ解決していない問題"],
  "evidence_index": ["重要な情報のソースインデックス"]
}

会話が 1 区切りつくたびに、Agent はこのような約 200 字の構造化サマリーを生成します。その利点は次のとおりです。

  1. 構造が明確:モデルが読み込むとき、各部分が何かをすぐ理解できる
  2. 情報密度が高い:中核だけを残し、無駄を省く
  3. 追跡可能:evidence_index が生データを指すので、詳細が必要なら調べられる

以前、非構造化の要約も試しました。たとえば「これはユーザーの注文照会に関する会話で……」といったものです。効果はずっと劣りました。モデルが読み込むときに重要な情報をすばやく特定しづらく、検索にも使いにくいのです。

検索の注入戦略:いつ能動的に注入し、いつ受動的に検索するか

記憶の検索には 2 つのモードがあります。能動的な注入と受動的な検索です。

能動的注入:生成のたびに、関連する記憶を自動でコンテキストに詰め込みます。記憶量が多くなく、リアルタイム性が求められるシーンに向いています。欠点は、記憶が多すぎるとコンテキストの空きを圧迫することです。

受動的検索:必要なときだけクエリします。モデルが「検索リクエスト」を生成し、ベクトル DB やナレッジグラフへ探しに行きます。記憶量が多く、遅延に敏感なシーンに向いています。欠点は、検索の遅延が 1 回分増えることです。

Letta の提案は、Core Memory は能動的注入、Recall/Archival Memory は受動的検索というものです。

どういう意味でしょうか。Core Memory の情報(ユーザーの好み、現在の目標)は、生成のたびに必ず知っておくべきものなので、コンテキストに能動的に注入します。Recall や Archival にある過去の情報は、モデルが「ちょっと思い出す必要がある」と判断したときだけ検索します。

これにはモデルに「自己認識」が必要です。自分がいつ資料を調べる必要があるかを知っていることです。GPT-4 や Claude はこの点で良好で、プロンプトで誘導できます。小さなモデルには、より明確なルールが必要になります。

記憶の減衰とクリーンアップ:「記憶の肥大化」を避ける

記憶の肥大化は現実的な問題です。ユーザーが使い込むほど記憶が増え、検索が遅くなり、呼び戻される情報も雑多になります。

解決法は、減衰とクリーンアップです。

減衰:各記憶に「重要度スコア」を持たせ、時間の経過とともに徐々に下げます。長期間検索も利用もされなければ、スコアがあるしきい値まで下がり、アーカイブまたは削除がトリガーされます。

クリーンアップ:記憶ストアを定期的にスキャンし、期限切れ・重複・低価値の記憶を削除します。

具体的な実装は、記憶インデックスの設計を参考にできます。

{
  "memory_id": "mem_001",
  "content": "ユーザーは React の技術スタックを好む",
  "importance": 0.85,
  "last_accessed": "2026-04-12",
  "access_count": 23,
  "decay_rate": 0.01
}

毎晩未明に、クリーンアップのタスクを 1 つ走らせます。

  • importance < 0.2 → 削除
  • 重複した記憶 → マージ
  • expired TTL → アーカイブ

こうすることで、記憶ストアは制御可能な規模に保たれ、検索効率が安定し、時間とともに肥大化することがなくなります。

技術選定:ベクトル DB vs ナレッジグラフ

ベクトル DB の強みと限界:意味検索は関係を復元できない

ベクトルデータベースは、いま最も主流の記憶ストレージ方式です。Pinecone、Weaviate、Milvus、Qdrant……どれも聞いたことがあるはずです。

その中核となる能力は、意味的な類似度検索です。テキストをベクトルに変換し、最も近い隣接点を探します。

「ユーザーは簡潔な回答を好む」と「ユーザーは短い返信を好む」——この 2 つの文はベクトル空間で近くに位置し、互いに呼び戻せます。これがベクトル DB の得意分野です。

しかしベクトル DB には致命的な盲点があります。「関係」を見つけられないのです。

例を挙げましょう。会話履歴に次のような文があるとします。

  • 「EC のプロジェクトを作っている」
  • 「プロジェクトでは Next.js を使っている」
  • 「バックエンドは Supabase」
  • 「最近は決済モジュールに取り組んでいる」

「プロジェクトの技術スタック」でベクトル検索すると、「Next.js を使っている」だけを呼び戻し、「バックエンドは Supabase」を取りこぼすかもしれません。この 2 文は意味的にはそれほど似ていないからです。しかし実際には関連があります。どちらもプロジェクトの技術選定です。

ここでナレッジグラフの出番となります。

Graph RAG:Agent につながりを理解させる

ナレッジグラフが保存するのは、エンティティと関係です。

先ほどの例は、ナレッジグラフではこうなります。

(ユーザー) --[取り組み中]--> (EC プロジェクト)
(EC プロジェクト) --[フロントエンド]--> (Next.js)
(EC プロジェクト) --[バックエンド]--> (Supabase)
(EC プロジェクト) --[現在のモジュール]--> (決済モジュール)

Agent が「プロジェクトの技術スタックは何か」と問われたとき、グラフをたどって、関連するすべての技術選定を見つけられます。

Neo4j の技術ブログは、完全な Agent メモリの実装方式を示しており、その中核は 3 種類のグラフです。

  1. ユーザーグラフ:ユーザープロファイル、好み、過去の行動
  2. タスクグラフ:いまのタスク、サブタスク、依存関係
  3. ナレッジグラフ:ドメイン知識、概念のつながり

グラフクエリの威力は、マルチホップ検索にあります。ベクトルは「似ている」ものしか見つけられませんが、グラフは「関連している」ものを見つけられます。

たとえば「ユーザーはこのプロジェクトでどんな問題に遭遇したか」を調べるとき、グラフは次のようにたどれます。

  • 「ユーザー」ノードから出発する
  • 「参加したプロジェクト」を見つける
  • プロジェクトに関連する「問題」を見つける
  • 問題の「解決策」を見つける

このようなマルチホップの関連は、ベクトル DB にはできません。

Reasoning Memory:意思決定の追跡の鍵

もう一度、推論記憶について話しましょう。これは多くのフレームワークが見落としている重要な能力です。

推論記憶が記録するのは「何が起きたか」ではなく、「なぜそうしたか」です。

たとえば、こうです。

  • ユーザーが尋ねる:「ログインページを作って」
  • Agent が尋ねる:「サードパーティログインは必要ですか?」
  • ユーザーが答える:「不要、メールログインだけでいい」
  • Agent が決める:NextAuth を使い、OAuth は統合しない

推論記憶は次のように記録します。

{
  "decision": "NextAuth を使い、OAuth は統合しない",
  "reasoning": "ユーザーはメールログインのみ必要で、サードパーティログインは不要",
  "constraints": ["OAuth を導入しない"],
  "alternatives_considered": ["Clerk", "独自認証"],
  "chosen_because": "NextAuth は軽量で、要件に合致する"
}

この記憶の価値はどこにあるのでしょうか。

  1. 説明可能性:ユーザーが「なぜ Clerk を使わないの?」と尋ねたとき、Agent が答えられる
  2. デバッグ:問題が起きたとき、意思決定チェーンをたどれる
  3. 継続的な学習:次回似た状況に遭遇したとき、過去の判断を参考にできる

Neo4j の実装では、推論記憶は「意思決定ノード」としてモデル化され、関連する「制約ノード」や「結果ノード」につながっています。こうすることで、1 つの意思決定の前後関係を完全に追跡できます。

ハイブリッド方式:ベクトル + グラフ + 構造化ストレージ

ここまで話してきましたが、結局どれを選べばよいのでしょうか。

答えは、ハイブリッド方式です。

ベクトル DB 単体では関係が失われます。ナレッジグラフ単体では構築コストが高く、意味検索が弱い。リレーショナル DB 単体では、柔軟性も呼び戻し能力も不足します。

実践での最適な組み合わせは次のとおりです。

  • ベクトルデータベース:会話テキストを保存し、意味検索を行う
  • ナレッジグラフ:エンティティの関係を保存し、マルチホップ推論を行う
  • リレーショナルデータベース:構造化データ(ユーザー情報、タスク状態)を保存する

3 者の連携モデルはこうです。

  1. ユーザーの質問はまずベクトル検索を通し、意味的に関連する会話の断片を呼び戻す
  2. 断片からエンティティを抽出し、グラフへ関連情報を問い合わせる
  3. 構造化データは直接リレーショナル DB を調べる

こうすれば、意味検索の柔軟性を残しつつ、グラフの関連付け能力も得られ、さらに構造化データの効率的なクエリも手に入ります。

6 大フレームワークの実戦比較

理論をたっぷり語ってきました。実際のフレームワークをどう選ぶか見ていきましょう。

Mem0:すばやい統合と多階層メモリ

Mem0 は、いま最も人気のある Agent メモリフレームワークの 1 つです。位置づけは「メモリ as a Service」——記憶の保存や検索を自分で管理する必要がなく、API を呼ぶだけで済みます。

主な特徴:

  • マネージドサービスで、自前のインフラ構築が不要
  • 21 種類のフレームワーク統合に対応(LangChain、LangGraph、LlamaIndex、CrewAI など)
  • 記憶の抽出・更新・検索を自動化
  • マルチテナント、マルチセッションに対応

LOCOMO ベンチマークのデータ:

  • 精度:66.9%
  • 遅延:0.71s
  • Token 消費量:約 2K

適したシーン:

  • 高速なプロトタイプ開発
  • 音声 Agent(遅延に敏感)
  • 複数フレームワークの統合が必要なプロジェクト

弱み:

  • マネージドサービスのため、データが自分の手元にない
  • 高度な機能(推論記憶など)への対応が限定的
  • カスタマイズ性は自前構築の方式に劣る

コード例:

from mem0 import Memory

m = Memory()

# 記憶を追加する
m.add("ユーザーは簡潔な回答を好む", user_id="user_001")

# 記憶を検索する
results = m.search("ユーザーの好み", user_id="user_001")

# 戻り値:["ユーザーは簡潔な回答を好む"]

笑ってしまうほどシンプルです。これこそ Mem0 最大の強み、つまり導入コストの低さです。

Letta:長期間動き続ける Agent の第一候補

Letta(前身は MemGPT)は別の路線を行きます。記憶管理を OS 的な階層アーキテクチャとして設計し、Agent の「自己管理」能力を重視します。

主な特徴:

  • OS 的な階層メモリ:RAM(コンテキスト)+ Disk(外部ストレージ)
  • 記憶の読み書き・退避・呼び戻しを Agent が自律的に判断
  • Sleep-time Compute による非同期処理
  • 推論記憶への完全な対応

適したシーン:

  • 長期間動き続ける Agent(プログラミングアシスタント、パーソナルアシスタントなど)
  • 意思決定の完全な追跡が必要なプロジェクト
  • 自律性が強く求められるシーン

弱み:

  • 学習曲線がやや急
  • 自前でのデプロイと管理が必要
  • モデルの能力に要求がある(小さなモデルではうまく「自己管理」できない場合がある)

アーキテクチャ図:

┌─────────────────────────────────────┐
│          Agent (LLM)                │
│  ┌───────────────────────────────┐  │
│  │      Core Memory (RAM)        │  │
│  │  - Self Block: 私は...          │  │
│  │  - User Block: ユーザーは...     │  │
│  │  - Task Block: 現在のタスク...    │  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘
         ↓ 能動的に管理
┌─────────────────────────────────────┐
│    External Storage (Disk)          │
│  - Recall Memory (ベクトル DB)       │
│  - Archival Memory (アーカイブ)       │
└─────────────────────────────────────┘

ユーザーに長期間寄り添う Agent を作るなら、Letta は現状で最も成熟した選択肢です。

Zep:会話記憶のスペシャリスト

Zep は、会話シーンの記憶管理に特化しています。中核となる能力は「段階的な要約」——会話が進むにつれて履歴を絶えず圧縮し、コンテキストウィンドウの使い勝手を保ちます。

主な特徴:

  • 段階的な要約:会話が長くなるほど、要約は洗練される
  • 意味 + 時間のハイブリッド検索
  • 事実抽出:会話から自動でエンティティと関係を抽出
  • マルチモーダル(テキスト、画像)に対応

適したシーン:

  • カスタマーサポートのボット
  • 会話型 AI アプリケーション
  • 長い会話履歴が必要なシーン

弱み:

  • 会話シーン寄りで、汎用 Agent シーンへの対応は限定的
  • オープンソース版は機能が限られ、エンタープライズ版は価格が高め

Zep の見どころの 1 つは、会話中の「事実」を自動で検出できることです。たとえば「ユーザーの名前は山田太郎」「ユーザーは東京に住んでいる」といった情報を、構造化データとして保存します。こうすれば、次回の会話で履歴をさかのぼらずにそのまま使えます。

Cognee:ナレッジグラフ方式

Cognee は、ナレッジグラフのメモリに特化したフレームワークです。強力な関係推論能力が必要なら、第一候補になります。

主な特徴:

  • ナレッジグラフを自動構築
  • 複数のグラフデータベースに対応(Neo4j、NetworkX など)
  • エンティティ抽出 + 関係抽出のパイプライン
  • 増分更新に対応

エンティティ抽出のコスト比較:

方法遅延品質コスト
spaCy約 5ms
GLiNER2約 50ms
LLM約 500ms最高

適したシーン:

  • ナレッジ密集型 Agent(リサーチアシスタント、ナレッジベース Q&A など)
  • マルチホップ推論が必要なシーン
  • 関係ネットワークが求められるシーン

弱み:

  • 構築コストが高い、特に LLM でエンティティ抽出を行う場合
  • グラフデータベースのインフラが必要
  • 単純なシーンには過剰設計になりがち

選定の意思決定マトリクス

ここまで語ってきましたが、どう選べばよいのか。意思決定マトリクスにまとめました。

シーン推奨フレームワーク理由
高速プロトタイプ / MVPMem0導入が最速、インフラ不要
音声 AgentMem0低遅延、マネージドサービスが安定
長期間寄り添う AgentLettaOS 的な管理、推論記憶が充実
企業カスタマーサポートZep会話記憶に強く、事実抽出が自動
ナレッジ密集型 AgentCogneeグラフ能力が強く、関係推論が強力
自前インフラ構築Letta + 任意のベクトル DB最も柔軟、コストを制御可能

汎用的なアドバイスを 1 つ挙げるなら、次のとおりです。

  • まず Mem0 でプロトタイプを動かす
  • 長期記憶のニーズが出たら、Letta へ移行する
  • 複雑な関係推論のニーズが出たら、Cognee や Neo4j を加える

実戦事例とベストプラクティス

音声 Agent のメモリ方式

音声 Agent は遅延に極めて敏感です。ユーザーが話し終えてから 200ms 以内に反応がないと、もたつきを感じます。

つまり、記憶の検索は 100ms 以内に完了する必要があります(音声合成と伝送に 100ms を残すため)。

Mem0 の方式は次のとおりです。

  1. Core Memory のプリロード:ユーザーの好みやよく使う設定を、セッション開始時に一度メモリへ読み込む
  2. Recall Memory の受動的検索:明確に必要なときだけクエリし、効率的なベクトルインデックスを使う
  3. 非同期更新:会話の終了後に非同期で記憶を更新し、応答をブロックしない

ElevenLabs の音声 Agent が Mem0 を統合した実測データでは、エンドツーエンドの遅延を 300ms 以内に抑え、ユーザーの体感も良好でした。

企業カスタマーサポート Agent

企業カスタマーサポートの中核ニーズは、ユーザーを長期間覚えていて、意思決定の過程を説明できることです。

典型的なアーキテクチャはこうです。

ユーザーのメッセージ

意図認識

┌─────────────────┬─────────────────┐
│  Core Memory     │  Recall Memory  │
│  (ユーザープロファイル) │  (過去の会話)     │
└─────────────────┴─────────────────┘

ナレッジベース検索(RAG)

回答を生成

推論記憶を記録(なぜこう答えたか)

Zep はこのシーンで良好です。自動の事実抽出でユーザーの基本情報を覚え、段階的な要約で長い会話を処理できます。

パーソナルアシスタント:セッションをまたいだ学習

パーソナルアシスタントの中核能力は、ユーザーの好みを学習し、セッションをまたいで連続性を保つことです。

鍵となる設計は次のとおりです。

  1. ユーザープロファイル記憶:長期間保存し、ユーザーの好み・習慣・よく使うツールを記録する
  2. プロジェクトコンテキスト記憶:プロジェクトごとに分離し、プロジェクトを切り替えるときに対応するコンテキストを読み込む
  3. 推論記憶:なぜある案を推奨したか、なぜある選択肢を捨てたかを記録する

Letta の設計はこのシーンに非常に向いています。Core Memory にユーザープロファイルを、Recall Memory にプロジェクト履歴を、Archival Memory にアーカイブしたプロジェクトを置きます。

落とし穴ガイド

踏み抜いてきた落とし穴を共有します。

落とし穴 1:すべての記憶をベクトル DB に詰め込む

問題:ベクトル DB は意味検索だけが得意で、正確なクエリや関係推論は不得意。

解決:ハイブリッドストレージにする。構造化データ(ユーザー ID、プロジェクト状態)はリレーショナル DB、意味記憶はベクトル DB、関係記憶はグラフへ。

落とし穴 2:TTL 戦略がない

問題:記憶がどんどん増え、検索がますます遅くなり、期限切れの情報を山ほど呼び戻す。

解決:記憶のタイプごとに TTL を設定する。イベント記憶は数時間で期限切れ、タスク記憶はタスク終了時にクリーンアップ、ユーザープロファイルは長期保持。

落とし穴 3:推論記憶を無視する

問題:Agent が意思決定を下したのに、なぜそうしたかを説明できない。デバッグが難しく、ユーザーに不信感を持たれる。

解決:意思決定チェーンを明示的に記録する。重要な意思決定ごとに、何を選んだか、なぜか、捨てた選択肢は何かを記録する。

落とし穴 4:記憶管理を LLM に頼りすぎる

問題:小さなモデルに、何を覚え何を消すかを自分で決めさせると、効果が非常に悪い。

解決:小さなモデルにはルールで補助する。たとえば明確なエンティティ抽出ルール、固定の記憶テンプレート、あらかじめ設定した重要度の重みなど。

まとめ

ここまで語ってきましたが、核心はいくつかだけです。

第 1 に、記憶は Agent の「第二の脳」であり、オプション機能ではなく中核アーキテクチャ。 メモリのない Agent は、ハードディスクのないパソコンのようなもので、電源を切れば記憶を失い、毎回ゼロから始まります。Agent を「ツール」から「パートナー」へ進化させたいなら、メモリシステムは避けて通れない壁です。

第 2 に、3 種類の記憶タイプはどれも欠かせない。 短期記憶がコンテキストを支え、長期記憶が永続化を支え、推論記憶が説明可能性を支えます。多くのフレームワークは前の 2 つしか作っておらず、推論記憶は大きく過小評価された能力です。

第 3 に、フレームワークの選定はシーン次第で、銀の弾丸はない。 音声 Agent は Mem0(低遅延)、長期タスクは Letta(OS 的な管理)、ナレッジ密集型は Cognee(グラフが強力)、カスタマーサポートのシーンは Zep(会話に特化)を選びます。

第 4 に、ベクトル DB は万能ではない。 意味検索は「類似」を、ナレッジグラフは「関係」を、構造化ストレージは「正確さ」を探します。3 つを組み合わせて初めて正解です。

第 5 に、記憶には管理が必要で、入れたら終わりではない。 TTL 戦略、減衰メカニズム、定期クリーンアップ、どれも欠かせません。さもなければ記憶ストアはゴミ捨て場へと膨れ上がります。

あなたへの行動アドバイス:

  1. LOCOMO ベンチマークのデータから始め、メモリシステムの性能指標を理解する
  2. Mem0 や neo4j-agent-memory ですばやくプロトタイプを組み、まず動かしてみる
  3. Reasoning Memory に注目する。これは次の段階の Agent 能力競争で、中核となる差別化ポイントになる

Agent の未来は、「より賢いモデル」だけではなく、「より永続的な記憶」にあります。Agent が 1 か月前のあなたの発言を覚え、なぜその判断をしたのかを理解し、次の会話でコンテキストを引き継げる——それこそが本当の意味での「知性」です。


参考資料

FAQ

AI Agent になぜ独立したメモリシステムが必要なのですか?コンテキストウィンドウでは足りないのですか?
コンテキストウィンドウは容量に限りがあり、コストも高くなります。LOCOMO ベンチマークでは、全量コンテキスト方式は精度こそ高い(72.9%)ものの、遅延が 9.87 秒に達し、Token 消費量はメモリシステムの 13 倍です。さらに深刻なのがコンテキスト腐敗で、ウィンドウが大きいほど無関係な情報が増え、モデルの注意が分散して逆に効果が落ちます。独立したメモリシステムは、短期・長期・推論記憶の階層管理によってこの問題を解決します。
短期記憶、長期記憶、推論記憶の違いは何ですか?
3 種類の記憶はそれぞれ役割が異なります。

• 短期記憶:コンテキストウィンドウそのもので、容量が限られ、会話の終了とともに消える。RAM に近い
• 長期記憶:外部ストレージ(ベクトル DB/グラフ)。容量が大きく永続化でき、ハードディスクに近い
• 推論記憶:意思決定の過程(なぜ B ではなく A を選んだか)を記録し、説明可能性やデバッグに使う

多くのフレームワークは前の 2 つしか実装しておらず、推論記憶は大きく過小評価された能力です。
Mem0、Letta、Zep、Cognee の 4 つはどう選べばよいですか?
シーンに応じて選びます。

• Mem0:高速プロトタイプ、音声 Agent(低遅延 0.71s)
• Letta:長期間寄り添う Agent(OS 的な管理、推論記憶が充実)
• Zep:企業カスタマーサポート(段階的な要約、事実抽出)
• Cognee:ナレッジ密集型 Agent(グラフが強力、マルチホップ推論)

まず Mem0 でプロトタイプを動かし、ニーズに応じて Letta や Cognee へ移行するのがおすすめです。
ベクトルデータベースとナレッジグラフはどう組み合わせればよいですか?
ベクトル DB は意味的な類似度検索(似た内容を探す)が得意で、ナレッジグラフは関係推論(関連する内容を探す)が得意です。ハイブリッド方式では、ベクトル DB に会話テキストを入れて意味検索を行い、ナレッジグラフにエンティティの関係を入れてマルチホップ推論を行い、リレーショナル DB に構造化データを入れて正確なクエリを行います。3 つを組み合わせて初めて、あらゆるシーンをカバーできます。
メモリシステムは記憶の肥大化を招きませんか?どう管理すればよいですか?
招きます。ユーザーが使い込むほど記憶が増え、検索が遅くなります。管理の戦略は次のとおりです。

• TTL 戦略:タイプごとに有効期限を設定する(イベント記憶は数時間、タスク記憶はサイクル単位、ユーザープロファイルは長期)
• 減衰メカニズム:重要度スコアを時間とともに下げ、しきい値を下回ったらアーカイブする
• 定期クリーンアップ:期限切れ・重複・低価値の記憶を削除する

Letta は情報量の 70% を残すことを推奨しており、連続性と圧縮率の最適なバランス点です。
Reasoning Memory とは何ですか?なぜ多くのフレームワークは実装していないのですか?
Reasoning Memory(推論記憶)が記録するのは意思決定の過程です。なぜこの案を選んだのか、どの選択肢を捨てたのか、そのときの制約条件は何だったのか。これは説明可能性、デバッグ、継続的な学習にとって極めて重要です。実装が難しいのは、単に会話テキストを保存するのではなく、推論チェーンを構造化して記録する必要があるためです。現状では Letta や Zep など、ごく一部のフレームワークしか対応していません。

13分で読めます · 公開日: 2026年4月13日 · 更新日: 2026年6月8日

関連記事

コメント

GitHubアカウントでログインしてコメントできます