DEV Community

Cover image for AIエージェントのメモリの仕組み (APIでテストする方法)
Akira
Akira

Posted on • Originally published at apidog.com

AIエージェントのメモリの仕組み (APIでテストする方法)

要するに

AIエージェントの失敗は知能不足ではなく、「忘れる」ことに原因があります。4つのメモリタイプがどのように保存され、API挙動にどのように影響するかを理解することで、より信頼性の高いエージェントを構築し、本番投入前にバグを特定できます。

今すぐApidogを試してみる

はじめに

多くのAIエージェントが失敗する主な理由は、モデル自体の問題ではなく、メモリ層の設計や実装にあります。過去の会話を思い出せない、セッション間でコンテキストが消える、自己矛盾するエージェントの多くはメモリ設計やテスト不足が原因です。

最近登場したオープンソースのエージェントメモリシステム Hippo は、生物学的にインスパイアされた設計で人間の記憶のように短期・長期・エピソードメモリを分離管理します。このような仕組みは、エージェントメモリを後回しにしがちな開発現場でのギャップを浮き彫りにしています。

💡 Apidogのテストシナリオを使えば、ステートフルな複数ターンのエージェント会話を本番前にテストできます。APIコール間のセッション状態検証、コンテキストのアサート、Smart Mockによるメモリ障害シミュレーションも可能です。本記事後半で具体的なテスト方法を解説します。より幅広いAPIテスト方法については [internal: api-testing-tutorial] を参照してください。

AIエージェントメモリとは何か?

エージェントメモリとは、AIシステムが現在の入力を超えて情報へアクセス・保持できる仕組みです。これがなければAPIコールはすべてステートレスとなり、モデルはプロンプトと応答以外何も覚えません。

主に4つのメモリタイプが存在し、それぞれ異なる役割を果たします。

エージェントメモリの4つのタイプ

ワーキングメモリ

ワーキングメモリはエージェントの「現在のコンテキスト」、つまりプロンプト内に含まれる全データです。多くのLLMベースのエージェントでは、これがコンテキストウィンドウに該当します(例:GPT-4oは128Kトークン、Claude 3.5 Sonnetは200K、Gemini 1.5 Proは1M)。

  • 特徴: 高速・高精度だが、トークンごとにコストが発生し上限もある。
  • 注意点: 上限到達時は古いコンテキストが警告なく破棄され、長期タスクでバグの原因になります。

エピソード記憶

エピソード記憶は、過去のインタラクションや決定のログです。エージェントの日記のようなもの。

  • 実装例: ベクトルDB(Chroma, Pinecone, Qdrant)やイベントログ。
  • 取得方法: セマンティック検索で関連エピソードのみプロンプトに注入。
  • Hippoの特徴: タイムスタンプと減衰重み付きのシーケンスで、直近の出来事ほど取得しやすくなっています。

セマンティック記憶

セマンティック記憶は、事実やドメイン知識、ユーザーの好みなど「知っていること」を保存します。

  • 実装例: システムプロンプトへの事前ロード、過去会話からの知識抽出(ナレッジグラフ)、RAGによる外部知識取得など。

手続き記憶

手続き記憶は「やり方」や「スキル」を保持します。行動シーケンスやツール利用パターンなど。

  • 実装例: システムプロンプト内のfew-shot例、行動計画のテンプレートライブラリ。
  • 注意: 実装が難しく、本番システムでは省略されがち。

実際のシステムでのメモリの保存方法

理想的には4タイプそれぞれに専用ストアを割り当てますが、現実のシステムは以下のような構成が一般的です。

  • コンテキストウィンドウ(ワーキングメモリ): エージェントフレームワークが管理し、会話終了時に期限切れ。
  • 外部ベクトルストア(エピソード+セマンティック記憶): Chroma/Pinecone/Qdrantでインタラクションや知識チャンクの埋め込み管理。各ターンで検索・注入。
  • 構造化DB(セマンティック+手続き記憶): PostgreSQLやSQLiteでユーザー設定や学習済みアクションを管理。
  • インメモリキャッシュ(ワーキングメモリのオーバーフロー): Redisや辞書型ストアで直近コンテキストを高速取得。

Hippoは3層メモリシステムを明示的なハンドオフロジックで実装しており、最近使われなかったワーキングメモリはエピソード記憶に統合、さらに要約されてセマンティック記憶に移行します。これは人間の記憶統合プロセスに近い設計です。

エージェントメモリがAPIの挙動に与える影響

APIを実装・利用する際、メモリ設計はAPI挙動と直結します。主な観点は以下です。

  • セッションID: 多くのエージェントAPIはセッションIDやスレッドIDで呼び出し間のメモリを紐付けます(例:OpenAI Assistants APIのthread_id)。ID管理ミスによるセッション混入バグに注意。
  • リクエストペイロードサイズ: メモリ注入型エージェントでは会話の継続でペイロードが肥大化。クライアント側のサイズ制限に注意。
  • 取得レイテンシ: ベクトルストアクエリは1ターン50~200ms加算。応答速度への影響を計測・アサートしましょう。
  • 失敗時の状態不整合: タスク途中でツール呼び出しが失敗した場合、部分的なログが残り次ターンでバグ化しやすい。状態チェックポイントを設ける設計が有効。

ApidogでAPI経由でエージェントメモリをテストする方法

ステートフルなエージェントAPIの本番品質テストには、複数ターン・セッション・障害ケースの検証が不可欠です。Apidogでは、これをテストシナリオで簡単に実現できます。

Apidog Test Scenario

テスト1:コンテキストの引き継ぎ

  1. 事実を伝えるメッセージ(例:「私のプロジェクトはPostgreSQL 16を使用しています」)を /agent/chat にPOST
  2. その事実を問うメッセージ(例:「どのデータベースを最適化すべきですか?」)を同じエンドポイントにPOST
  3. ステップ2の応答に「PostgreSQL」が含まれることをアサート

例(擬似コード):

// ステップ1
POST /agent/chat
{ "session_id": "A", "message": "私のプロジェクトはPostgreSQL 16を使用しています" }

// ステップ2
POST /agent/chat
{ "session_id": "A", "message": "どのデータベースを最適化すべきですか?" }

// アサーション
expect(response.message.content).toContain("PostgreSQL")
Enter fullscreen mode Exit fullscreen mode

テスト2:セッション分離

異なるsession_idで上記シナリオを2回実行し、2つ目のセッションの応答に1つ目のセッションの情報が混入していないことをアサートします。これでメモリのネームスペース分離バグを検知できます。

テスト3:メモリ障害時の劣化

Smart Mockでベクトルストアのエンドポイントを503にモックし、メモリ障害状態を再現します。

  • エージェントがクラッシュせず適切なフォールバック応答を返すこと
  • 「十分なコンテキストがありません」等のメッセージが含まれること
  • モック解除後、同じセッションで再開できること

テスト4:コンテキストウィンドウのオーバーフロー

30回以上連続でメッセージを送信し、ワーキングメモリの制限を超える状況を作ります。

  • context_length_exceededエラーが発生しないこと
  • 30ターン目でもエピソード記憶から情報取得できること
  • response.usage のトークン数が想定範囲内であること

これらを1つのテストシナリオで連鎖させ、共有変数でセッションID等を管理できます。LLM側のコンテキストウィンドウ実装詳細については [internal: how-to-build-tiny-llm-from-scratch] も参照してください。

よくあるメモリ障害モード

  • サイレントなコンテキスト切り捨て: コンテキスト上限で古い履歴が消える。response.usage.prompt_tokens をアサートして制限未満であることを確認。
  • セッションの混入: セッション分離テストで検知可能。
  • 古いセマンティック記憶: 過去の知識が現状と矛盾。テストで「現在の日付」やバージョン番号を明示的にチェック。
  • 埋め込みのドリフト: 埋め込みモデル変更時の取得異常。取得コンテキストのセマンティック一致度をアサートする。
  • メモリインジェクション: 悪意あるユーザー入力による保存・取得操作。敵対的入力をテストスイートに含め、システムプロンプトの上書きが無視されることを確認。

APIセキュリティテスト全般は [internal: rest-api-best-practices] 参照。

結論

エージェントメモリ(ワーキング・エピソード・セマンティック・手続き)は、知的なアシスタントと単なる「忘れっぽい」アシスタントの分水嶺です。各メモリタイプの保存・取得方法を理解し、テストで明確にアサートすることで、バグの温床を可視化できます。

Hippoのようなツールはメモリアーキテクチャの進化を示しています。どんなメモリシステムでも、Apidogのテストシナリオで大規模環境特有の障害ケースまで検証しましょう。

よくある質問

Q: エージェントにメモリを追加する最も簡単な方法は?

A: 会話履歴のスライディングウィンドウ(プロンプトに直近Nターンを保持)が手軽です。短期タスク向け。長期運用にはベクトルストア+セマンティック検索も組み合わせましょう。

Q: OpenAI Assistants APIはどのようにメモリを処理しますか?

A: サーバーサイドでスレッドオブジェクトとして会話履歴を管理。ファイル検索・コードインタープリターの添付で外部知識も利用可能。メモリ管理は抽象化されており、便利ですがデバッグは少し難しくなります。

Q: エージェントメモリに最適なベクトルデータベースは?

A: ローカル開発はChroma、本番はQdrant(セルフホスト)またはPinecone(マネージド)が推奨です。Hippoはプラグイン式ストレージをサポート。Claude Codeの独自メモリ層については [internal: claude-code] 参照。

Q: エージェントが過去インタラクションを幻覚するのを防ぐには?

A: インタラクションログをタイムスタンプや信頼度とともに構造化保存し、プロンプト注入時に明示的な引用を付与します(例:「[日付]の会話によると…」)。

Q: 実行中のエージェントなしでエージェントメモリをテストできますか?

A: 可能です。ApidogのSmart MockでセッションIDやリクエスト内容ごとに異なる応答を返すよう設定し、メモリ挙動をフロント・統合レイヤーで検証できます。

Q: 本番環境でのベクトルストレージのコストは?

A: Pinecone無料ティアは10万ベクトル/1インデックス。本番はp1.x1ポッド(100万ベクトル/768次元)で$0.096/時間程度。Qdrantセルフホストは無料。多くの場合、ストレージより埋め込み生成コストが支配的です。MCPサーバー統合との関係は [internal: what-is-mcp-server] 参照。

Q: RAGとエージェントメモリの違いは?

A: RAGは静的ナレッジベースからドキュメントを取得しますが、エージェントメモリはインタラクションを通じて動的に成長・変化します。RAGは「ドキュメントには何と書かれている?」、エージェントメモリは「このユーザーについて私は何を知っていて何をしてきたか?」に答えます。

Top comments (0)