AIエージェントの長期記憶とは|ステートレスなLLMに記憶を持たせる仕組みと主要OSS比較(mem0 / Letta / Zep ほか)

AIエージェントの長期記憶とは|ステートレスなLLMに記憶を持たせる仕組みと主要OSS比較(mem0 / Letta / Zep ほか) AIエージェント
記事の根拠: 公式一次資料の比較
全サービスを同一条件で実測した比較ではありません
本文の最終更新: 2026年7月
検証: AIツール図鑑編集部(AI自動化・ツール実運用 / 料金・規約は公式資料で確認)

LLMが「覚えていられない」理由

言語モデルは、一回の推論を終えるとそのやり取りを保持しない。会話が次のターンに進めるのは、過去の発言をプロンプトに丸ごと積み直しているからであって、モデル自身が前回を覚えているわけではない。新しいセッションを開けば、基盤モデル単体では前のセッションの内容は引き継がれない(ChatGPTのような製品はアプリ側の履歴・メモリ・スレッド管理で継続性を持たせているが、それはモデルの外側の仕組みだ)。別のタスクへ移れば直前の判断も引き継がれない。この「一回ごとに白紙へ戻る」性質をステートレスと呼ぶ。エージェントを長期間にわたって使うほど、この前提が運用上の壁になる。

ここで一点、用語の混同を先に断っておく。本稿で扱う「メモリ/記憶」は、エージェントが何を覚え、いつ思い出すかという知識や状態の永続化の話であって、RAMやVRAMといったハードウェアのメモリ消費とは別の問題である。モデルを動かすときのGPUメモリ容量と、エージェントが過去の会話を覚えているかどうかは、まったく別の層にある。検索やドキュメントで「メモリ」という語に出会ったとき、どちらの意味かを取り違えると設計を見誤るので、最初に線を引いておく。

このステートレス性に、もう一つの制約が重なる。コンテキスト窓だ。これはステートレス性とは別の話で、モデルが一度の推論で受け取れる文字数(トークン数)の上限を指す。仮に毎回すべての履歴を積み直すとしても、窓が広いモデルでも無限ではないし、窓を広く使うほど推論のコストと遅延は増える。さらに、窓に大量のテキストを詰め込むと、肝心の情報が埋もれて応答の精度がかえって落ちる現象も知られている。だから「全部を窓に入れ続ける」やり方には早晩限界が来る。窓の外に情報を置いておき、必要なときだけ取り出して窓へ戻す仕組みが要る。それが長期記憶の出発点になる。

記憶の階層 ―― 短期と長期

エージェントの記憶は、おおまかに短期と長期の二層で考えると整理しやすい。短期記憶はコンテキスト窓の内側にある情報を指す。いま進行中の会話履歴、直近のツール実行結果、現在のタスクの作業メモなどがこれにあたる。窓に載っている間は即座に参照できるが、窓からあふれた瞬間に失われる。寿命はセッションの長さに縛られる。

長期記憶は、コンテキスト窓の外、すなわち外部ストアへ書き出して永続化した情報を指す。セッションをまたいでも、プロセスを再起動しても残り、必要になったときに検索して窓へ呼び戻す。短期記憶が作業机の上に広げた書類なら、長期記憶は引き出しにしまったファイルに近い。机の上は限られているので、使い終わった書類はしまい、必要になったら探して取り出す。この出し入れの設計が、長期記憶の実装の中身になる。

コンテキスト窓(短期記憶) いま参照中の会話履歴・作業メモ 窓からあふれると失われる/詰めすぎると精度低下 外部ストア(長期記憶) ベクタDB/知識グラフ など セッションをまたいで永続 保存 抽出・要約・事実化 想起 関連度で検索→窓へ戻す
図: 短期記憶(コンテキスト窓内)と長期記憶(外部ストアへ永続化)。保存と想起の出し入れが長期記憶の中身。

素朴な「全部貯める」方式とその限界

長期記憶のいちばん単純な実装は、過去の会話を全文そのまま保存しておき、新しい会話のたびに関連しそうな履歴を引っ張ってきて窓へ足す、というものだ。発想は分かりやすいが、運用が進むほど破綻しやすい。履歴が積み上がると検索の対象が膨れ上がり、関連度の判定が雑になる。古い発言と新しい発言が矛盾していても、両方をそのまま取り出してしまえばモデルは混乱する。トークン消費も会話量に比例して増えていく。生ログをただ貯めるだけでは、量が増えたときに使いものにならない。

要約・事実抽出・ベクタ検索による想起

そこで、生の履歴をそのまま貯めるのではなく、保存する前に加工する方式が広く使われている。代表的な手口は三つある。一つは要約で、長い会話を短い要旨へ畳んでから保存し、窓を圧迫しないようにする。二つめは事実抽出で、会話から「ユーザーはPythonを好む」「先月の提案はA案で確定した」といった再利用しやすい単位の情報を取り出して構造化する。三つめはベクタ検索で、保存した記憶を埋め込み(ベクトル)へ変換しておき、新しい問い合わせと意味的に近い記憶を類似度で引き当てる。キーワードの完全一致ではなく意味の近さで探せるのが、ベクタ検索が想起に向く理由だ。

実運用では、これらを組み合わせる。会話が来たら事実を抽出して構造化し、ベクタDBへ埋め込みとして保存しておく。問い合わせが来たら意味的に近い記憶を検索し、上位だけを窓へ戻す。後述するツールの多くは、この「抽出して保存し、関連度で取り出す」という流れを土台にしつつ、保存先や更新の仕方で個性を出している。

何を覚え、いつ思い出すか

記憶を持たせると決めたら、次に問われるのは「何を覚えるか」だ。すべてを覚える必要はないし、覚えすぎは害になる。実務で価値が出やすいのは、いくつかの種類に分かれる。ユーザーの嗜好(言語の好み、口調、出力フォーマットの希望)は、毎回聞き直さずに済むので体験に直結する。過去の決定(どの方針で進めると合意したか)は、後戻りや蒸し返しを防ぐ。タスクの中間結果(長い処理の途中経過)を残しておけば、中断から再開できる。失敗からの学習(このやり方は前回うまくいかなかった、という記録)も、同じ轍を踏まないために効く。

覚える種類を、記憶研究になぞらえて区別する設計もある。事実や知識を蓄える意味記憶、特定の出来事を思い出すためのエピソード記憶、振る舞いの手順そのものを保持する手続き記憶、という分け方だ。LangMemはこの三分類を明示的に扱う。分類そのものが目的ではなく、保存と想起の扱いを種類ごとに変えるための足場になる。

想起のタイミングも設計の勘どころになる。やみくもに全記憶を窓へ流し込めば、短期記憶を全部貯めるのと変わらない。問い合わせの内容から関連度の高い記憶だけを選んで取り出すのが基本で、ここでベクタ検索の類似度や、記憶の新しさ・参照頻度といった重みづけが効いてくる。同じくらい意味が近い記憶が複数あるとき、より新しいものや過去によく使われたものを優先する、といった調整だ。取り出す量を絞るほど窓は軽くなるが、絞りすぎれば必要な記憶を取りこぼす。このさじ加減が、記憶システムの体感品質をかなり左右する。

取り出すきっかけにも幅がある。ユーザーの発言ごとに毎回検索を走らせる素直なやり方もあれば、エージェント自身が「ここで過去の記憶を参照すべきだ」と判断したときにツール呼び出しで取りに行く設計(ReActエージェントのように推論と行動を交互に進める形)もある。後者はLettaが採るアプローチで、想起の主導権をモデル側に持たせる分、いつ何を思い出すかの制御がエージェントの振る舞いに委ねられる。どちらを選ぶかで、記憶システムの組み込み方は変わってくる。

忘却と更新 ―― 古い事実をどう上書きするか

記憶を「足す」のは比較的やさしいが、「直す」のは難しい。ユーザーが先月は東京在住で今月は大阪へ引っ越した、という場合、古い「東京在住」を残したまま「大阪在住」を足すと、二つの矛盾する事実が同居する。検索で両方が引っかかれば、エージェントはどちらを信じるべきか分からなくなる。だから記憶システムには、新しい情報が来たときに古い情報をどう扱うか、という更新の戦略が要る。

扱い方は方式によって分かれる。新しい事実で古い事実を置き換える(上書きする)やり方もあれば、古い事実を消さずに「ここまでは有効だった」という有効期間の情報を付けて無効化し、履歴は残すやり方もある。後者はZepの基盤であるGraphitiが採る方式で、いつからいつまで真だったかを時間軸で保持する。どちらが良いかは用途次第で、過去の経緯を遡れる必要があるなら無効化方式が向くし、単に最新状態だけ分かればよいなら上書きでも足りる。いずれにせよ、矛盾の検知と古い記憶の取り扱いを設計から外すと、記憶は時間とともに信頼できなくなる。

主要ツールの比較

2026年6月時点で、エージェントの長期記憶を支えるOSS・サービスはいくつか実用段階にある。形態(ライブラリかマネージドサービスか)、記憶の方式、永続先、ライセンスで性格が分かれる。以下は公式ドキュメント・GitHubで確認できた範囲の整理で、各値は各ツールの公式情報に基づく。ライセンスはいずれも2026年6月時点のもの。

ツール 形態 記憶の方式 主な永続先 ライセンス 特徴
mem0 OSSライブラリ + マネージドプラットフォーム 会話から事実を抽出して保存(現行OSSはADD-only型の抽出)、意味検索・BM25・エンティティ連結を併用 ベクタDB(Python SDK既定はローカルQdrant、構成により差し替え可)+履歴用SQLite、構成によりグラフDBも Apache-2.0 import して add()/search() を呼ぶだけの軽量な導入。多数のフレームワーク連携を公式提供
Letta(旧MemGPT) OSSフレームワーク + クラウド エージェント自身がツール呼び出しでメモリブロックを編集。コア(memory blocks)/会話検索(conversation search)/アーカイブ(archival memory)の階層 データベース永続(プロセス再起動をまたいで状態保持) Apache-2.0 状態をサービスとして常駐させ、エージェントが自分の記憶を管理する設計
Zep / Graphiti Graphiti=OSSエンジン、Zep=マネージドプラットフォーム 時間軸付きの知識グラフ。事実が変わると古い事実を無効化し履歴は保持 グラフDB(Neo4j / FalkorDB / Amazon Neptune 等) Apache-2.0(Graphiti) 事実の有効期間を追跡し出所まで辿れる。時系列で「いつ真だったか」を問える
LangMem OSS SDK(LangGraph 連携) 意味・エピソード・手続きの三種を扱い、会話から情報を抽出して保存・更新 LangGraph の BaseStore(本番では PostgreSQL 等) MIT 記憶の種類を明示的に区別。LangGraph のストア層と統合しつつ任意ストアでも使える
Cognee OSSプラットフォーム + マネージド 取り込みデータを知識グラフ化(ECLパイプライン)、グラフとベクタのハイブリッド グラフDB + ベクタDB(Neo4j / PGVector 等) Apache-2.0 多様な形式を取り込んでグラフへ構造化。グラフ推論と意味検索を組み合わせる
TencentDB Agent Memory OSSライブラリ / プラグイン 4層(会話→事実→シーン→人物像)で段階的に抽象化、ツールログは記号化して圧縮 ローカルSQLite + sqlite-vec(既定で外部API依存なし) MIT 完全ローカルで動く設計。下層は証跡として、上層は人が読める形で保持

選び方の目安として、まず手軽に記憶を足したいならライブラリとして組み込めるmem0やLangMemが入りやすい。エージェント自身に記憶の管理まで任せたいならLetta、事実の変遷を時間軸で厳密に追いたいならZep/Graphiti、取り込んだ資料をグラフとして横断的に問いたいならCognee、外部送信を避けて手元だけで完結させたいならTencentDB Agent Memoryが候補になる。形態(ライブラリかサービスか)と永続先(ベクタかグラフかローカルか)の二点を先に決めると、選択肢はかなり絞り込める。記憶単体でなくエージェント全体の組み方から考えたい場合は、AIエージェント構築フレームワークの比較もあわせて見るとよい。

最小の使い方イメージ(mem0)

記憶を組み込む流れは、ツールが違ってもおおむね「保存する」と「探す」の二操作に集約される。OSS版mem0の公開APIを例に、いちばん短い形を示す。下記は会話から記憶を保存し、後で意味検索で呼び戻す一般的な使い方のイメージで、既定では裏側で事実抽出とベクタ保存が走る(モデルや保存先は設定で差し替えられる)。

from mem0 import Memory

m = Memory()

# 会話を渡すと、内部で事実を抽出して保存する
messages = [
    {"role": "user", "content": "出力は常に日本語の常体でお願いします"},
    {"role": "assistant", "content": "承知しました。常体で出力します"},
]
m.add(messages, user_id="alice")

# 別のタイミングで、意味的に関連する記憶を検索して取り出す
results = m.search("このユーザーの文体の好みは?", filters={"user_id": "alice"})
for item in results["results"]:
    print(item["memory"])

add()に渡した会話から、内部で「日本語の常体を好む」といった事実が抽出され、ベクタとして保存される。次回以降はsearch()で文体に関する問い合わせを投げると、その記憶が関連度の高い順に返ってくる。これを応答生成のプロンプトに足せば、毎回好みを聞き直さずに済む。ツールが変わっても、保存と検索という二つの操作に集約される構図は共通している。

設計上の注意

記憶を持たせると一見すべてが良くなりそうだが、運用には固有の落とし穴がある(本番運用で踏みやすい落とし穴全般はAIエージェントのアーキテクチャ設計でも整理されている)。導入前に押さえておきたい点を挙げる。

  • 記憶の肥大化: 何でも覚えると、検索対象が膨らんで関連度判定が鈍り、想起の精度もコストも悪化する。覚える対象を絞り、不要になった記憶を整理する仕組みが要る。
  • 関連度の低い記憶の混入: 検索の取り出し件数や閾値が緩いと、無関係な記憶が窓へ紛れ込み、応答をかえって歪める。取り出す量は絞り気味に始めて調整するのが無難。
  • 記憶の真偽と陳腐化: 保存した事実が誤っていたり、時間が経って古くなったりしても、検索ではそのまま引っかかる。更新・無効化の戦略を最初から組み込んでおかないと、記憶は時間とともに信頼を失う。記憶の正しさを継続的に測る発想はエージェントの評価設計とも通じる。
  • プライバシーの扱い: ユーザーの発話を記憶として保存することは、個人情報を蓄積することと表裏一体になる。保存先がローカルか外部サービスか、暗号化されるか、保存内容がモデルの学習に使われるかは、ツールと設定によって異なる。「外部に出ない」「学習に使われない」を無条件に断定はできず、採用するツールの保存先・暗号化・学習利用の方針を実際の設定で確認したうえで、条件付きで扱うべきところだ。完全ローカルで動く構成(TencentDB Agent Memoryなど)は、ローカルLLMと同じく外部送信を避けたい場合の選択肢になるが、これも構成次第である点は変わらない。

コンテキストエンジニアリングとの使い分け

長期記憶の話は、コンテキストエンジニアリング(プロンプトに何をどう詰めるか、文脈の組み立て)としばしば隣り合う。両者は重なる部分があるが、担う役割は違う。コンテキストエンジニアリングは、いま手元にある材料(指示・履歴・取得した情報)を、限られた窓の中へどう配置すれば応答が良くなるかという、窓の内側の組み立ての話だ。一方で長期記憶は、窓の外に情報を保存しておき、必要なときに取り出して窓へ戻す、保存と想起の仕組みを指す。

両者は対立しない。むしろ連携する。長期記憶が外部ストアから関連する記憶を取り出し、コンテキストエンジニアリングがその記憶を含めた材料を窓の中へうまく並べる、という分担になる。記憶が「何を窓へ戻す候補にするか」を担い、文脈の組み立てが「戻す候補を実際にどう配置するか」を担う。記憶システムを入れても、取り出した記憶を窓のどこに、どんな形で置くかという組み立ての設計は別途必要になる。逆に組み立てだけ工夫しても、窓の外に蓄積する仕組みがなければセッションをまたいだ継続性は得られない。両輪として捉えると、エージェントの設計がすっきりする。

よくある質問

長期記憶とRAGはどう違うのか

RAG(検索拡張生成)は、あらかじめ用意した文書群から関連箇所を検索して回答に使う仕組みで、対象は基本的に静的な知識ベースだ。長期記憶も検索して取り出す点は似ているが、対象がユーザーとのやり取りから動的に生まれる事実や決定であり、新しい会話のたびに書き込まれ、更新・無効化される点が異なる。RAGの技術(ベクタ検索など)を長期記憶の実装に流用することは多く、両者は排他ではない。

コンテキスト窓が十分に広ければ長期記憶は不要になるか

窓が広がれば短期記憶として保持できる量は増えるが、それだけでは解決しない。窓は依然として有限で、長期運用では蓄積量が窓を超える。窓を広く使うほどコストと遅延が増え、情報が埋もれて精度が落ちる傾向もある。窓の拡大は短期記憶の余裕を増やすが、セッションをまたぐ永続化や、関連する記憶だけを選んで戻す仕組みの必要性そのものは消えない。

記憶した情報が外部に送られない構成は可能か

ツールと設定による。TencentDB Agent Memoryのように既定で外部API依存なし・ローカルSQLiteで完結する設計もあり、外部送信を避けたい用途の選択肢になる。一方、マネージドサービスを使う場合や、事実抽出・埋め込み生成にクラウドのモデルを呼ぶ構成では、内容が外部へ渡る。保存先・暗号化・学習利用の方針は採用するツールの実際の設定で確認する必要があり、「外部に出ない」を無条件には断定できない(2026年6月時点)。

覚えた事実が古くなったときはどうなるか

放置すれば古い事実も検索で引っかかり、誤った応答の原因になる。対策は方式によって分かれ、新しい事実で古い事実を上書きするもの、古い事実を消さずに有効期間を付けて無効化し履歴を残すもの(ZepのGraphiti等)がある。更新・無効化の戦略をシステム選定の段階で確認しておくのが、記憶の信頼性を保つうえで重要になる。

参考資料

タイトルとURLをコピーしました