生成AIの基礎

AIのコンテキスト管理術:長い対話でも情報を失わない設計

AIのコンテキスト管理術:長い対話でも情報を失わない設計

この記事の要点

Claudeの「コンテキストウィンドウ」の仕組みと、長時間の対話・マルチエージェント処理で情報を失わない設計方法を解説。ロスト・イン・ザ・ミドル問題の回避策や、重要情報を保持する実践的なテクニックを紹介します。

結論

AIとの対話が長くなるほど、コンテキストウィンドウへの情報の積み上がりが精度を下げます。この問題は「コンテキストを適切に設計する」ことで大幅に軽減できます。重要な数値・日付・事実を会話の要約に埋もれさせず別ブロックとして維持する、詳細探索をサブエージェントに分離する、重要情報を文書の冒頭に配置するという3つの設計が核心です。


コンテキストウィンドウとは何か

Claudeが1回の処理で参照できる情報量には上限があります。この上限が「コンテキストウィンドウ」です。

コンテキストウィンドウに入るもの:

  • 会話の履歴(ユーザーの発言・Claudeの回答)
  • ツールの実行結果(注文情報・顧客データなど)
  • システムプロンプト・指示
  • 処理対象のドキュメント

対話が続くほど、また多くのツールを使うほど、この枠が埋まっていきます。枠が満杯に近づくと、古い情報から削除されたり、重要な情報が希薄化したりして精度が落ちます。


「ロスト・イン・ザ・ミドル」問題

コンテキスト管理で最も見落とされやすい問題が、長い入力の中間部分にある情報が処理されにくいという現象です。

研究で確認されているパターンとして、AIは入力の「冒頭」と「末尾」の情報を比較的確実に参照しますが、大量の情報が中間に積み上がると、その部分の情報が出力に反映されにくくなります。

実際に起きる問題の例:

  • 5件の調査レポートをまとめて渡したとき、3番目のレポートだけ内容が薄い
  • 長い顧客対応の記録の中間にあった「返金済み」という情報を見落として再度返金処理をしようとする
  • 複数サブエージェントの調査結果をまとめたとき、中間に位置するエージェントの発見が最終レポートに入っていない

重要情報を失わない3つの設計

設計1: 重要な事実を「ケースファクト」として分離する

長い対話の中で重要な数値・日付・顧客情報が出てきたとき、それを会話の要約に溶け込ませてはいけません。要約は「顧客が怒っていた」のような定性情報に圧縮され、「返金額: 4,800円」「注文番号: #45678」「対応期限: 6月10日」という定量情報が失われます。

推奨するのは、定量情報を独立した「ケースファクト」ブロックとして、要約と切り離して保持する設計です。

通常の会話要約(問題あり):
「顧客は注文が届かないと不満を述べ、返金を要求している」

ケースファクトブロック(推奨):
---
[ケースファクト]
顧客ID: CUS-23456
注文番号: #45678
注文日: 2026-05-28
金額: 4,800円
問題: 6月3日時点で未着
顧客の要求: 返金
対応期限: 2026-06-10
---

[会話要約]
顧客は配送の遅延に不満を表明。返金を要求している。

このケースファクトブロックをシステムプロンプトに毎回含めることで、会話がどれだけ長くなっても重要な数値情報が常に参照可能な状態になります。

設計2: 詳細探索をサブエージェントに分離する

コードベースの大規模調査・大量文書の解析のような詳細作業は、主エージェントが直接行うとコンテキストウィンドウが詳細情報で埋まります。後半の実装フェーズで「以前に発見した○○のクラス」を参照しようとしても、コンテキストが長くなりすぎて矛盾した回答が返ってくるようになります。

この問題への対処が、詳細探索をサブエージェントに分離して、要約だけを主エージェントに返す設計です。

悪い設計:
主エージェントがコードベース全体を探索
→ ファイルの全内容がコンテキストに積み上がる
→ 後半の実装フェーズでコンテキストが飽和して精度低下

良い設計:
主エージェント: 「src/payment/以下の決済フローを調査してください」
         ↓ サブエージェントに委譲
サブエージェント: 全ファイルを詳細に調査(このコンテキストは捨てる)
         ↓ 要約だけを返す
主エージェント: 「決済フロー: stripe連携が3か所、Webhookは1か所、決済エラー処理はpaymentController.tsに集中」

主エージェントのコンテキストには要約だけが入るため、後続の実装で参照する情報が圧縮されたままになります。

マルチエージェントでのサブエージェント活用についてはマルチエージェント設計の実践パターンで詳しく説明しています。

設計3: 重要情報を文書の冒頭に配置する

複数の調査結果や複数の文書をまとめてClaudeに渡すとき、最も重要な情報を冒頭に、詳細を後ろに置く設計がロスト・イン・ザ・ミドル問題の軽減に効果があります。

改善前(中間に重要情報):
[詳細データA: 3,000トークン]
[重要なサマリー: 500トークン]  ← 中間にある
[詳細データB: 3,000トークン]

改善後(冒頭に重要情報):
[全体サマリー: 500トークン]  ← 冒頭に移動
[詳細データA: 3,000トークン]
[詳細データB: 3,000トークン]

また、複数の調査結果を渡すときは、各セクションに明示的なヘッダーをつけます。

## 財務状況(2026年第1四半期)
[財務データ]

## 顧客満足度調査(N=1,200)
[調査データ]

## 競合分析
[競合データ]

構造化されたヘッダーがあることで、Claudeが各セクションの役割を把握しやすくなり、参照精度が上がります。


ツール実行結果の肥大化を防ぐ

エージェントがツールを繰り返し呼び出すと、各ツールの実行結果がコンテキストに積み上がります。特に問題になるのが、1回の呼び出しで大量のフィールドを返すAPIです。

例えば、注文情報取得APIが40個のフィールドを返すとして、実際に使うのが5個だけだとします。この40フィールドが毎回コンテキストに追加されると、10回の注文照会で400フィールド分のトークンが消費されます。

解決策は、ツール実行後に必要なフィールドだけに絞り込むことです。

注文照会の結果(40フィールド → 5フィールドに絞り込み後):
{
  "order_id": "#45678",
  "status": "配送中",
  "estimated_delivery": "2026-06-07",
  "total_amount": 4800,
  "item_count": 2
}

この絞り込みはPostToolUseフックで自動化できます。ツールが返した生データをエージェントに渡す前に、必要フィールドだけに変換します。エージェント側の設計なしにツール結果を自動的にスリム化できます。


スクラッチパッドで文脈を跨いで情報を保持する

長時間にわたる大規模コードベースの探索では、セッションが長くなるにつれて「1時間前に発見したクラスの構造」のような情報が薄れてきます。Claudeが「一般的なパターンとして」のような曖昧な言い方をし始めたら、コンテキストの劣化のサインです。

この問題への対処がスクラッチパッドファイルです。

exploration_notes.md:
# コードベース調査メモ

## 発見した主要クラス
- PaymentProcessor: src/payment/processor.ts(L45)
  - Stripe APIとの接続を管理
  - 失敗時はRetryQueueに追加する仕組み
  
- OrderService: src/orders/service.ts(L23)
  - 注文の作成・更新・キャンセルの中心ロジック
  - PaymentProcessorに依存

## 未確認の依存関係
- RetryQueueの実装箇所が未特定

このファイルをエージェントが随時更新し、次の質問の前に参照することで、セッションが長くなっても発見した事実が失われません。


セッション再開時の注意点

中断したセッションを再開するとき、判断すべき選択肢があります。

セッション再開(—resume)を選ぶ場合:

  • 前の調査結果がまだ有効(ファイルを変更していない)
  • 同じ問題に引き続き取り組む
  • 少量の追加作業だけで完了できる

新セッションに要約を渡す方法を選ぶ場合:

  • 前のセッション以降にファイルを大幅に変更した
  • ツール実行結果が古くなっている可能性がある
  • 前のセッションのコンテキストが混在すると判断を混乱させる恐れがある

再開せず新セッションを始める場合は、前のセッションでの主要な発見を「調査サマリー」としてまとめて新セッションに渡します。ツール実行結果の詳細より、整理された文章のサマリーの方が確実に参照されます。

ファイルを変更した後にセッションを再開するときは、どのファイルを変更したかを明示的に伝えます。「src/payment/processor.tsを変更しました。この部分を再確認してください」のように伝えることで、再探索が必要な範囲を絞れます。


マルチエージェントでの情報保全

複数のエージェントが協調するシステムでは、エージェント間の情報受け渡しにも設計が必要です。

避けるべきパターン: 生の長文をそのまま渡す

サブエージェントが生成した詳細な分析テキストをそのままコーディネーターに渡すと、次のエージェントへの受け渡しでどんどん情報が積み上がります。最後に統合するエージェントのコンテキストがパンクします。

推奨パターン: 構造化データで渡す

{
  "source": "web_search_agent",
  "topic": "AI in music production",
  "key_findings": [
    {"claim": "音楽制作AIのグローバル市場は2028年までに3倍に", "source_url": "...", "year": 2024},
    {"claim": "プロ作曲家の43%が生成AIツールを週次で使用", "source_url": "...", "year": 2024}
  ],
  "coverage_gaps": ["ライブパフォーマンスへの影響は未調査"],
  "confidence": "high"
}

構造化データで渡すことで、受け取る側のエージェントが必要な情報だけを抽出でき、余分な説明文がコンテキストを圧迫しません。出典情報も保持されるため、最終レポートで引用元を示せます。

情報の出典保全についてはClaudeエージェントループ入門でも関連する設計を解説しています。


Claude Codeでの/compactコマンド

Claude Codeを使った長時間のコーディングセッションでは、/compactコマンドが有効です。現在のコンテキストを要約して圧縮し、重要な情報を維持しながらトークン使用量を削減します。

使い時のサインは次の通りです。

  • Claudeが「先ほど説明した通り」と言いながら違う内容を話している
  • 以前に特定したクラスや関数の場所を「再確認してください」と言われる
  • 応答が遅くなってきた(コンテキストが大きくなっているサイン)

/compactを実行するタイミングの目安は、大きなフェーズが一段落したときです。「コードベースの調査が完了した」「バグ修正が完了して次のリファクタリングに移る」のような区切りで実行します。作業の途中で圧縮すると、その時点で参照中の情報が要約されて精度が落ちる場合があります。


まとめ

コンテキスト管理で押さえるべき実践ポイントをまとめます。

  • 重要な数値・日付・固有名詞はケースファクトブロックとして要約から分離して保持する
  • 詳細探索はサブエージェントに分離して、要約だけを主エージェントに返す
  • 複数文書を渡すときは重要情報を冒頭に配置し、明示的なセクションヘッダーをつける
  • ツール結果は必要なフィールドだけに絞り込んでコンテキストを節約する
  • 長期セッションではスクラッチパッドファイルで発見事実を永続化する
  • マルチエージェントでの情報受け渡しは構造化データで行い、出典情報を保持する

これらの設計を組み合わせることで、長時間の対話や大規模な調査作業でも、AIの参照精度を高い水準に保てます。

よくある質問

コンテキストウィンドウとは何ですか?

AIが一度に参照できる情報量の上限です。会話の履歴・ツール実行結果・指示が全て含まれ、上限を超えると古い情報から削除されます。長い対話や大量のデータ処理ではこの管理が精度に直結します。

「ロスト・イン・ザ・ミドル」問題とは何ですか?

長い入力の中間部分にある情報が、AIに正確に処理されにくい傾向のことです。冒頭と末尾の情報は比較的確実に処理されますが、大量の文書の中間に埋まった重要な数値や事実は見落とされやすくなります。

コンテキストが増えすぎたとき、Claude Codeではどうすればよいですか?

/compactコマンドを使うと、現在のコンテキストを要約して圧縮します。長期の調査セッションで詳細な発見が積み上がりすぎたときに有効です。