要するに
AIエージェントが失敗するのは知能が不足しているからではなく、忘れてしまうからである。エージェントの4つのメモリタイプ、それらがどのように保存されるか、そしてAPIの挙動にどのように影響するかを理解することで、より信頼性の高いエージェントを構築し、本番環境に投入する前にバグを特定できる。
はじめに
ほとんどのAIエージェントの失敗の汚れた秘密はここにある。モデルは問題ない。メモリ層が壊れているのだ。
3ターン前の出来事を思い出せないエージェント、セッション間でユーザーのコンテキストを失うエージェント、あるいはタスクの途中で自己矛盾するエージェントは、モデルの品質が原因で幻覚を見ているわけではない。メモリアーキテクチャが慎重に設計されていなかったか、全くテストされていなかったために失敗しているのだ。
最近トレンドになったオープンソースのエージェントメモリシステムであるHippoは、生物学的なアプローチを採用している。人間の記憶が機能するのと同じように、短期記憶、長期記憶、エピソード記憶を個別にモデル化している。このプロジェクトは、実際のギャップを浮き彫りにした。ほとんどの開発者はエージェントメモリを後回しにして構築し、それが本番環境で壊れていることを初めて知るのだ。
AIエージェントメモリとは何か?
エージェントメモリとは、AIシステムが現在の入力 beyond の情報をアクセスまたは保持することを可能にするあらゆるメカニズムである。それがなければ、すべてのAPIコールはステートレスとなる。モデルはプロンプトを受け取り、応答を返し、何も記憶しない。
4つの異なるメモリタイプがそれぞれ異なる目的を果たす。
エージェントメモリの4つのタイプ
ワーキングメモリ
ワーキングメモリはエージェントのアクティブなコンテキストであり、現在のプロンプト内のすべてを指す。ほとんどのLLMベースのエージェントにとって、これはコンテキストウィンドウである。GPT-4oは128Kトークンのコンテキストウィンドウを持ち、Claude 3.5 Sonnetは200Kをサポートし、Gemini 1.5 Proは1Mをサポートする。
ワーキングメモリは高速かつ正確だが、高価(トークンごとに料金が発生)であり、かつ上限がある。上限に達すると、最も古いコンテキストは警告なく破棄される。これは、長期間にわたるタスクにおけるエージェントのバグの最も一般的な原因である。
エピソード記憶
エピソード記憶は、何が起こったか、つまり過去のインタラクション、決定、観測のログを保存する。エージェントの日記のようなものだと考えればよい。
実際には、これは通常ベクトルデータベース(Chroma、Pinecone、Qdrant)または構造化されたイベントログである。エージェントは応答を生成する前に、セマンティック検索を介して関連する過去のエピソードを取得する。Hippoのアプローチでは、タイムスタンプと減衰重み付けを伴うインタラクションシーケンスを保存するため、最近のインタラクションほど取得優先度が高くなる。
セマンティック記憶
セマンティック記憶は、エージェントが知っていること、すなわち事実、ドメイン知識、ユーザーの好み、安定した世界知識を保存する。エピソード記憶とは異なり、時間順序はない。
これは事前に読み込まれたり(ユーザープロファイルデータを含むシステムプロンプト)、動的に構築されたり(過去の会話から抽出された事実がナレッジグラフに保存される)、外部から取得されたり(ドキュメントストアに対するRAG)する。
手続き記憶
手続き記憶は、物事を行う方法、つまり行動シーケンス、ツール使用パターン、およびエージェントが学習したスキルを保存する。これは構築するのが最も難しく、本番システムではしばしば省略される。
実際には、システムプロンプトに埋め込まれた少数の例として、またはエージェントが取得して適応できる保存された行動計画のライブラリとして現れる。
実際のシステムでのメモリの保存方法
4つのタイプが4つの別々のストアにきれいにマッピングされることはめったにない。実際のセットアップは次のようなものになることが多い。
コンテキストウィンドウ(ワーキングメモリ):アクティブなプロンプト内のすべて。エージェントフレームワークによって管理される。会話が終了すると期限切れになる。
外部ベクトルストア(エピソード記憶 + セマンティック記憶):Chroma、Pinecone、またはQdrantが、過去のインタラクションと知識チャンクの埋め込みを保存する。エージェントは各ターンでこれをクエリし、関連するチャンクをプロンプトに注入する。
構造化DB(セマンティック記憶 + 手続き記憶):ユーザー設定、アカウント状態、学習済みアクションテンプレートにPostgreSQLまたはSQLiteを使用する。ツール呼び出しを介してクエリされる。
インメモリキャッシュ(ワーキングメモリのオーバーフロー):埋め込み検索を必要としない最近のコンテキストへの高速アクセス用にRedisまたは単純な辞書を使用する。
Hippoは、その3層メモリシステムを明示的なハンドオフロジックで具体的にモデル化している。最近アクセスされていないワーキングメモリのエントリはエピソード記憶に統合され、最終的にセマンティック記憶に要約される。これは、睡眠中に人間の記憶が統合される仕組みを反映している(このプロジェクトには、統合をトリガーするための「sleep」コマンドさえある)。
エージェントメモリがAPIの挙動に与える影響
ここからが実際に重要になる。エージェントAPIを構築または利用する場合、メモリはAPIコールの見た目や、何が問題を引き起こすかを直接的に左右する。
セッションID:ほとんどのエージェントAPIは、呼び出し間でメモリを関連付けるためにセッションIDまたはスレッドIDを使用する。OpenAI Assistants APIはthread_idを使用する。ドロップされた、または再利用されたスレッドIDは、エージェントがコンテキストを失うか、2人のユーザーのセッションが混ざり合う原因となる。
リクエストペイロード内のコンテキストサイズ:プロンプトにメモリを注入するエージェントは、時間の経過とともにリクエストボディを大きくする。2KBで始まるエージェントの会話は、20ターン後には40KBにまで膨れ上がる可能性がある。HTTPクライアントにペイロードサイズ制限がある場合、リクエストはサイレントに失敗する。
取得レイテンシ:ベクトルストアのルックアップは、1ターンあたり50~200ミリ秒を追加する。API応答時間についてアサートする場合、メモリ取得は実際の要因となる。
失敗後の不整合な状態:エージェントのツール呼び出しがタスクの途中で失敗した場合、エピソードログは部分的なアクションを記録する可能性がある。次のターンは破損した状態から始まる。優れたエージェントは、ツール使用の前後で状態をチェックポイントする。
ApidogでAPI経由でエージェントメモリをテストする方法
ステートフルなエージェントAPIをテストするには、単一リクエストのアサーション以上のものが必要となる。複数の呼び出し間でコンテキストが引き継がれること、メモリに基づいた応答が期待通りに変化すること、そしてメモリが利用できない場合にシステムが正常に劣化することを検証する必要がある。

Apidogのテストシナリオはまさにこれを処理する。エージェントAPI用に設定する方法は以下の通り。
テスト1:コンテキストの引き継ぎ
3つの連続したステップでシナリオを作成する。
- 事実を導入するメッセージ(「私のプロジェクトはPostgreSQL 16を使用しています」)で
/agent/chatにPOSTする - その事実を思い出させるフォローアップ(「どのデータベースを最適化すべきですか?」)で
/agent/chatにPOSTする - ステップ2の応答をアサートする:
response.message.contentに「PostgreSQL」が含まれている必要がある
エージェントのメモリ層が機能していれば、ステップ2はエピソード記憶またはセマンティック記憶から事実を取得し、応答で使用する。そうでなければ、一般的な回答が返される。
テスト2:セッション分離
異なるsession_id値で同じ2ステップシーケンスを2回実行する。2番目のセッションの応答に最初のセッションからのコンテキストが含まれていないことをアサートする。これにより、共有メモリのバグを捕捉できる。これは、マルチテナントエージェントデプロイメントで最も一般的でデバッグが困難な問題の1つである。
テスト3:メモリ障害時の劣化
ApidogのSmart Mockを使用して、メモリバックエンドの障害をシミュレートする。モックを設定して、ベクトルストアのルックアップエンドポイントで503を返すようにする。その後、エージェントの会話を実行し、以下をアサートする: - エージェントがクラッシュせずに応答する - 応答に適切なフォールバック(「その質問に答えるのに十分なコンテキストがありません」)が含まれる - モックが削除された後もセッションを再開できる
テスト4:コンテキストウィンドウのオーバーフロー
30以上のメッセージを連続して送信し、ワーキングメモリをコンテキスト制限を超えて押し上げる。以下をアサートする: - エージェントがcontext_length_exceededエラーをスローしない(正常に切り捨てられるべきである) - 30ターン目の応答がエピソード取得を使用して依然として正しく回答する - response.usage内のトークンカウントが期待される範囲内に留まる
これら4つすべてを、Apidogで単一のテストシナリオとして実行できる。セッションIDと応答データに共有変数を使用して、これらを順次チェーンする。コンテキストウィンドウがモデルレベルでどのように機能するかの背景については、[internal: how-to-build-tiny-llm-from-scratch]を参照してください。
よくあるメモリ障害モード
サイレントなコンテキスト切り捨て:コンテキストウィンドウがいっぱいになり、古いメッセージが警告なしに消える。エージェントは不完全な履歴に基づいて回答する。response.usage.prompt_tokensをアサートし、それがモデルのコンテキスト制限を下回っていることを確認することで、これを捕捉できる。
セッションの混入:2つのユーザーセッションがメモリ名前空間を共有する。これはセッション分離テストで捕捉できる。
古いセマンティック記憶:数週間前に保存された知識が現在の事実と矛盾する。エージェントは自信を持って誤った情報を提供する。テストに「現在の日付」のアサーションを含めることでこれを捕捉できる。エージェントが価格やバージョン番号を引用する場合、それがテストコンテキストに読み込んだ値と一致することをアサートする。
埋め込みのドリフト:ある埋め込みモデルで構築されたベクトルストアは、別のモデルに切り替えると壊れてしまう。取得されたすべてのドキュメントはセマンティック的に誤りとなる。API経由で直接テストすることはできないが、取得されたコンテキストがクエリとセマンティック的に関連しているかどうかをチェックするアサーションを追加できる。
メモリインジェクションプロンプトインジェクション:保存および取得されるものを操作する悪意のあるユーザー入力。テストスイートに敵対的入力を含める。システムプロンプトのオーバーライドを含む「ユーザー設定」を保存し、エージェントがそれを無視することを確認する。より広範なAPIセキュリティテストのガイダンスについては、[internal: rest-api-best-practices]を参照してください。
結論
エージェントメモリは、インテリジェントに感じるアシスタントと、記憶喪失に感じるアシスタントとの違いである。ワーキングメモリ、エピソード記憶、セマンティック記憶、手続き記憶の4つのタイプは、それぞれ異なる役割を果たす。それらが実際のシステムでどのように保存および取得されるかを理解することで、バグがどこに潜んでいるか、そしてAPIテストで何をアサートすべきかを正確に知ることができる。
Hippoのようなツールは、この分野が原理に基づいたメモリアーキテクチャへと移行していることを示している。どのようなメモリシステムを構築しているにせよ、Apidogのテストシナリオは、特に大規模な場合にのみ現れる障害ケースなど、期待通りの動作を検証するためのテスト層を提供する。
よくある質問
エージェントにメモリを追加する最も簡単な方法は?最も簡単なアプローチは、会話履歴上のスライディングウィンドウである。プロンプトに最後のNターンを保持することだ。これはエピソード記憶ではないが、短いタスクには機能する。長期間実行されるエージェントには、ベクトルストアとセマンティック検索を追加する。
OpenAI Assistants APIはどのようにメモリを処理しますか?Assistants APIは、会話履歴をサーバーサイドに保存するスレッドオブジェクトを管理します。エージェントが外部知識にアクセスできるように、ファイル検索ツールやコードインタープリターツールを添付することもできます。メモリ管理は抽象化されており、これは便利ですが、デバッグをより困難にします。
エージェントメモリに最適なベクトルデータベースは?ローカル開発用にはChroma(インフラ不要)。本番環境用には、自己ホスト型が必要かマネージド型が必要かに応じてQdrantまたはPinecone。Hippoライブラリはプラグ可能なストレージバックエンドをサポートしている。Claude Codeが独自のメモリ層をどのように使用しているかについては、[internal: claude-code]を参照してください。
エージェントが過去のインタラクションを幻覚するのを防ぐにはどうすればよいですか?インタラクションログをメタデータ(タイムスタンプ、信頼度、ソース)とともに構造化された形式で保存します。過去のコンテキストを取得する際に、プロンプトにメタデータを含めます:「[日付]の会話によると、あなたはXについて言及しました。」この明示的な引用により、確信犯的な幻覚が減少します。
実行中のエージェントなしでエージェントメモリをテストできますか?はい。ApidogのSmart Mockを使用して、メモリに基づいた応答を含むエージェントのAPI応答をシミュレートできます。セッションIDまたはリクエストボディの内容に基づいて変化するモック応答を定義します。これにより、ライブエージェントなしで、フロントエンドまたは統合レイヤーのメモリ動作の処理をテストできます。
本番環境でのベクトルストレージのコストはどのくらいですか?Pineconeの無料ティアは、10万ベクトルを持つ1つのインデックスをサポートします。大規模な場合、Pineconeはp1.x1ポッド(100万個の768次元ベクトル)に対して約$0.096/時間を請求します。Qdrantのセルフホスト型は無料です。ほとんどのエージェントにとって、より大きなコストは埋め込み生成であり、ストレージではありません。MCPサーバー統合がエージェントメモリシステムとどのように相互作用するかについては、[internal: what-is-mcp-server]を参照してください。
RAGとエージェントメモリの違いは何ですか?RAG(検索拡張生成)は、クエリ時に固定された知識ベースから関連ドキュメントを取得します。エージェントメモリは動的であり、エージェントがインタラクションするにつれて成長し変化します。RAGシステムは「Xについてドキュメントには何と書かれているか?」と答えます。エージェントメモリシステムは「このユーザーについて私は何を知っていて、彼らと何をしてきたか?」と答えます。
