powered by TechFeed
表示モード
Deep Dive

AIエージェントがタスクの途中で止まる原因はコンテキスト上限 — ウィンドウを「ストレージ」として使わないための6ステップ設計

6月18日、Redis公式ブログにてJim Allen Wallaceが「AI Agent Context Limit: 6-Step Recovery Playbook」と題した記事を公開した。AIエージェントがコンテキスト上限に達した際に取るべき6段階の対処手順について詳しく紹介されている。なお、本記事はRedisの公式ブログであり、Step6では自社製品Redis Irisへの言及がある点をあらかじめ断っておく。

6月18日、Redis公式ブログにてJim Allen Wallaceが「AI Agent Context Limit: 6-Step Recovery Playbook」と題した記事を公開した。AIエージェントがコンテキスト上限に達した際に取るべき6段階の対処手順について詳しく紹介されている。なお、本記事はRedisの公式ブログであり、Step6では自社製品Redis Irisへの言及がある点をあらかじめ断っておく。


AIエージェントがタスクの途中で「完了」と誤判定して止まってしまう。原因の一つとして挙げられるのがコンテキストウィンドウの上限だ。これはプロンプトの工夫で回避できるモデル側の問題ではなく、アーキテクチャの問題である。

コンテキストウィンドウとは、モデルが1回の推論で参照できるテキスト全体(トークン単位で測定)のことで、いわばモデルの短期記憶に相当する。システムプロンプト、会話履歴、ツール定義、ツール実行結果、RAGで注入したドキュメントなどがすべてここに積み上がる。ウィンドウが大きくなっても問題は消えない。トークン数が増えると精度や想起率が低下する「コンテキスト腐敗(context rot)」が起き(参考:Lost in the Middle: How Language Models Use Long Contexts)、さらに重要な情報が中央に位置すると見落とされる「lost-in-the-middle問題」も生じる(同論文にて報告)。

記事が示す6ステップは、「ツール出力の刈り込み→履歴の圧縮→状態の外部化→必要時のみ取得→サブタスクの分離→ストレージ層の最適化」という流れで構成されており、コンテキストの肥大化を上流から順に断ち切る設計になっている。


Step 1(最重要):ツール出力をウィンドウに入れる前に刈り込む

エンジニアが最初に手を付けるべきはここだ。エージェントがツールを呼び出すたびに、その返り値がそのままコンテキストに書き込まれる。検索結果、APIレスポンス、ファイル内容、ログダンプ……。Model Context Protocol(MCP)で接続されたエージェントでは、ツール定義と結果だけで50,000トークン以上消費することもある。

具体的な対策は以下のように重ね掛けできる。

  • ハードなトークン上限とページネーション:長くなりうるツールレスポンスに上限を設ける。Claude Codeのデフォルト25,000トークン上限はページネーションや範囲選択と組み合わせて機能する。
  • 動的なツールフィルタリング:現在のタスクに関係するツールだけをロードする。ツールリスト自体もトークンを消費するためだ。
  • 参照渡し(インライン展開しない):500行のファイルをエージェントが書いたなら、チャット履歴にはファイルの中身ではなくファイルパスのみを残す。

Step 2:古いターンを要約・圧縮する

ツール出力を絞ったあと、次に膨らむのが会話履歴だ。ウィンドウの上限に近づいたら古いターンを要約し、その要約から新しいウィンドウを再初期化する「コンパクション」を行う。一部のフレームワークはこれを自動化しており、たとえばDeep Agentsはウィンドウの**85%**に達した時点で自動コンパクションを実行する。

ただし圧縮は非可逆であることを意識する必要がある。要約はエラー文字列や正確なファイルパス、過去の決定の厳密な言い回しといった具体情報を落とす。元記事ではフィデリティのレベルを以下のように整理している。

種別 トークン 情報量
生の履歴 完全
コンパクト版(compacted history) 要約済みの古いターン+直近の生ターンを組み合わせたもの
要約 要点のみ

「コンパクト版」は元記事でのcompacted historyに対応し、古いターンを要約しつつ直近の生ターンを保持するハイブリッドな状態を指す。「冗長性を除いた大部分」という表現は筆者による意訳であるため、厳密には元記事の定義を参照されたい。

具体情報が落ちると、エージェントが作業の途中経過を見て「完了済み」と誤判定するリスクが高まる。対策として、圧縮前にフル履歴をファイルに書き出しておき、詳細が必要なときに外部から参照できるようにするパターンが有効だ。これが次のステップにつながる。


Step 3:永続的な状態をウィンドウの外に出す

同じ情報を何度も要約しているなら、それはそもそもウィンドウに置くべきではない。コンテキストウィンドウはワーキングメモリであり、ストレージではない。

モデル自体はステートレスであり、推論のたびにゼロから始まる。したがって「モデルに記憶を持たせる」のではなく、「モデルの周りに記憶インフラを構築する」という設計思想が正しい。アクティブな作業セットだけをウィンドウに置き、過去の決定・ユーザー設定・処理済み結果などはすべて外部ストアに置いて、各ターンの冒頭に必要なものだけを取得する構成が、プロダクション品質のエージェントの基本アーキテクチャだ。

ウィンドウを大きくしても外部ストレージは不要にならない。長いコンテキストはワーキングメモリを拡張するが、セッション横断の永続ストレージや、数ヶ月分の履歴からの選択的取得を提供するわけではない。


Step 4:必要なときだけ取得する(Just-in-Time Retrieval)

状態を外部に出したら、次は毎ターン全履歴を引き回すのをやめる。エージェントがステップの途中で必要なものを判断し、外部ストアからそのレコードだけ取得して使い、次のステップではウィンドウから外れる——このジャストインタイム取得パターンがポイントだ。

RAG(Retrieval-Augmented Generation)はここで機能する。クエリをベクトルエンベディング(意味の数値表現)に変換し、意味的に類似したドキュメントのみをプロンプトに注入する手法だ。

実践上の注意点:

  • ウィンドウを予算として扱う:各ステップで今必要な情報に絞る。
  • 注入前に関連性を確認する:弱いマッチでもノイズになる。
  • 大きなペイロードは段階的にロードする:SQL系ワークロードなどで全データを一度に注入しない。

Step 5:トークンを多く消費するサブタスクを分離する

どれだけ刈り込んでもトークンを食うタスクは存在する。そういった処理は、独立したコンテキストウィンドウで動くサブエージェントに委譲する。オーケストレーターは高レベルの計画を保持し、サブエージェントが詳細作業を行って圧縮済みのサマリーだけを返す。この手法は「コンテキスト隔離(context quarantine)」と呼ばれる。

ただしこのパターンはコストがかかる。リサーチのような並列化しやすい読み取り専用タスクには効果的だが、コーディングのように密に結合したタスクでは、調整オーバーヘッドや変更の競合がむしろ問題を増やす。

また、コンテキスト上限に近づくとエージェントがタスクを早期に終了させようとする「コンテキスト不安(context anxiety)」という挙動が現れることが知られている。サブタスクのコンテキストを上限から余裕を持たせることで、このリスクを下げられる。


Step 6:ストレージ層のコストと速度を適正化する

Step 3〜5の外部ストア戦略は、そのストアが低レイテンシかつコスト効率に優れている場合にのみ機能する。フェッチが遅ければコンテキスト問題をレイテンシ問題に置き換えるだけだ。

本ステップはRedis公式ブログという性質上、自社製品の紹介となっている。記事ではRedis Irisが紹介される。コンテキスト取得、エージェントメモリ、セマンティックキャッシュ、既存RDBとのデータ同期を1つのマネージドサービスに統合したものだ。コスト面では、SSDベースの階層型ストレージエンジン「Redis Flex」によりメモリコストを最大**80%**削減できるとしている。


まとめ

6ステップの一貫したテーマは「ウィンドウはワーキングスペース、永続データは外部ストア」という原則だ。問題が起きてから対処するのではなく、コンテキスト使用量を計装して上限に達する前にプロアクティブに動くことが推奨されている。

詳細はAI Agent Context Limit: 6-Step Recovery Playbookを参照していただきたい。