Claude Media
Computer Useでプロンプトキャッシュを保つスクリーンショット管理

Computer Useでプロンプトキャッシュを保つスクリーンショット管理

Computer Useの長時間ループはスクリーンショットを急速に積み上げ、プロンプトキャッシュを壊しがちです。バッチ単位の間引きとcache_controlの置き方をまとめます。

Computer Useの長時間ループでスクリーンショットがキャッシュを壊す

Computer Useの1回のスクリーンショットは、おおよそ1,000〜1,800入力トークンを消費します。エージェントループが数十ターン続くだけで、会話履歴に積み上がったスクリーンショットの総量は無視できない大きさになります。加えてAPIのリクエスト上限も効いてきます。1回のリクエストに含まれる画像が20枚を超えると、そのリクエスト内の全画像に厳しめのサイズ制限がかかります。スクリーンショット履歴をそのまま持ち続けるループは、数十ターンでこの20枚に到達します。

対処は大きく2つです。各スクリーンショットを縦横2000px以内にリサイズしてサイズそのものを抑えるか、古いスクリーンショットを間引いて1リクエストあたりの画像枚数を20枚以下に保つか。どちらか、あるいは両方を組み合わせます。ただし間引き方を誤ると、今度はプロンプトキャッシュを壊してコストとレイテンシが悪化します。

なお「2000px以内」はスクリーンショット履歴を管理するうえでの実務的な目安であり、モデルごとの正確な上限とは別物です。実際の画像サイズ制限は、Claude Opus 4.7以降(computer_toolset_20260801対応モデルをすべて含む)は長辺2576px・視覚トークン総数4784まで、それより前のモデルは長辺1568px・約1.15メガピクセルまでと、モデルの世代で分かれています。2000pxという目安値は、この2系統の上限の間に収まる安全側の値です。正確な上限で運用したい場合は、モデルごとの実際の制限値を基準にリサイズ処理を組みます。

cache_controlブレークポイントの置き方

プロンプトキャッシュを効かせるには、system promptとツール定義の直後に1つ、直近ターンのtool_resultブロックの末尾に最大3つまでcache_controlのブレークポイントを置きます。直近3ターン分のブレークポイントは、ターンが進むごとに前へスライドさせます。

batch action(1ターンで複数のcomputer use操作をまとめて返す仕組み)を使う場合は注意が必要です。複数のブロックにマーカーを置いても、それらは1つのブレークポイントとして扱われますが、上限の4つには変わらずカウントされます。1ターンにつき1つのマーカーを使うのが安全です。

現行のツールセットcomputer_toolset_20260801は、tools配列のツール定義エントリ自体にもcache_controlを指定できます。system promptの直後に置くブレークポイントとは別に、ツール定義そのものにブレークポイントを立てられる仕組みで、ツール定義が大きい構成(text editor toolやbash toolを併用する場合など)ではこちらも活用できます。

古いスクリーンショットは「まとめて」間引く

最も陥りやすい失敗が、毎ターン1枚ずつスクリーンショットを間引く実装です。毎ターンの間引きはプレフィックスを毎ターン変え、キャッシュを毎回無効化します。せっかくcache_controlを置いても、間引きのタイミングが揃っていなければ意味がありません。

公式ドキュメントが示す妥当な既定値は、直近3枚のスクリーンショットを残し、25ターンごとにまとめて間引く方法です。25ターンの間はプレフィックスがバイト単位で同一に保たれるため、間引きのタイミング以外ではキャッシュがそのまま効き続けます。スクリーンショットが2000pxを超えるサイズで運用している場合は、1リクエストの画像枚数が20枚以下に収まるよう、間引く間隔を調整します。25ターンという間隔は固定の必須値ではなく、自分のタスクの平均画像サイズから逆算して短くしたり長くしたりできる目安です。

リサイズと間引き、どちらを優先するか

リサイズと間引きは目的が違います。リサイズはスクリーンショット1枚あたりのトークン消費とサイズ制限への抵触を抑える対策で、ターン数が伸びても履歴に残る画像の総量そのものは減りません。間引きは履歴に残す画像の枚数を制限する対策で、1枚あたりのサイズには手を付けません。長時間ループでは両方が必要になるのが実際のところです。

優先順位としては、まずリサイズで1枚あたりのコストを下げてから、間引きの間隔(既定は25ターン)を決めるのが素直な順番です。リサイズだけで済ませようとすると、ターン数が伸びるにつれて画像の総枚数がいずれ20枚制限に達し、その時点で全画像がまとめて厳しいサイズ制限の対象になります。間引きだけに頼ると、間引くまでの25ターンの間は大きな画像がそのまま残り続け、無駄なトークン消費が起きます。両方を組み合わせることで、キャッシュを保ちながら履歴のサイズと枚数の両方を制御できます。実装の順序としては、スクリーンショットを取得した直後にリサイズ処理を通し、間引きは別のタイマーやターンカウンターで独立に走らせる構成にすると、2つの処理が互いの前提を壊しません。片方だけを後から足す設計にすると、既存のターンカウンターとリサイズ処理の呼び出し順序が絡み合い、あとから間引きだけを差し込むのが難しくなります。

Claude Fable 5.1ではクライアント側の間引きを避ける

Claude Fable 5.1を使う場合、この間引き戦略に例外が入ります。クライアント側で古いスクリーンショットを削除すると、それより後のすべてのthinkingブロックが無効化されるためです。Fable 5.1ではスクリーンショットを削除せず、縦横2000px以内へのリサイズで容量を抑え、古いスクリーンショットを会話から落とす処理はサーバー側のtool result clearing(clear_tool_uses_20250919、ベータ機能のcontext editing)に任せます。

どうしてもクライアント側で間引く必要がある場合は、それ以降prefix_mismatch_behavior: "drop_block"を設定したままにします。間引きのたびにClaudeは、その間引かれたスクリーンショット以降に生成したthinkingを持たずに応答を続けます。

context editingにはtool result clearingとは別に、thinkingブロック自体を古い順に消すthinking block clearing(clear_thinking_20251015)というベータ機能もあります。役割が異なるので混同しないようにします。tool result clearingが消すのはスクリーンショットを含むtool_resultの中身、thinking block clearingが消すのはClaudeが生成したthinkingの中身です。Fable 5.1のスクリーンショット間引きに使うのは前者のtool result clearingで、両者は組み合わせて使うこともできます。いずれもベータ機能のため、有効化にはcontext-management-2025-06-27ベータヘッダーをリクエストに付ける必要があります。

実装例: 25ターンごとのバッチ間引き

会話履歴のスクリーンショットを25ターンごとにまとめて間引く最小実装です。

def prune_screenshot_history(messages, turn_count, keep_last=3, prune_interval=25):
    """25ターンごとにスクリーンショットをまとめて間引く。
    毎ターン呼ぶのではなく、turn_countが間隔の倍数のときだけ実行する。
    """
    if turn_count % prune_interval != 0:
        return messages  # 間引きのタイミングでなければプレフィックスをそのまま保つ
 
    image_positions = [
        i for i, m in enumerate(messages)
        if m["role"] == "user"
        and any(block.get("type") == "tool_result" for block in m["content"])
    ]
    keep_from = image_positions[-keep_last:] if len(image_positions) > keep_last else image_positions
 
    pruned = []
    for i, m in enumerate(messages):
        if i in image_positions and i not in keep_from:
            # 画像を除いたtool_resultだけ残す(テキストは保持)
            pruned.append(strip_images(m))
        else:
            pruned.append(m)
    return pruned

cache_controlのブレークポイントは、この間引き処理とは別に、system promptとツール定義の直後、および直近3ターンのtool_result末尾に立て直します。

{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01A9r5kQm2LxWc7vT3nZ4bJs",
      "content": [{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": "..."}}],
      "cache_control": {"type": "ephemeral"}
    }
  ]
}

よくある落とし穴

  • 毎ターン1枚ずつ間引く: プレフィックスが毎回変わり、キャッシュが常にミスします。間引きは一定間隔でまとめて行います
  • Fable 5.1でクライアント側の間引きをそのまま流用する: 他モデル向けの間引きロジックを流用すると、それ以降のthinkingブロックがまとめて無効化されます。モデルごとに戦略を分けます
  • 20枚制限を見落とす: リサイズだけで安心し、間引きを一切しないと、長いループでリクエストの画像枚数がいずれ20枚を超え、その時点で全画像が厳しいサイズ制限の対象になります
  • モデル世代ごとのサイズ上限を混同する: 「2000px」という目安値をすべてのモデルの正確な上限だと思い込むと、Opus 4.7以降の高解像度枠(長辺2576px)を無駄に切り捨てたり、逆に旧モデルの実際の上限(長辺1568px)を超えて拒否エラーを受け取ったりします
  • ツール定義のcache_controlを付け忘れる: text editor toolやbash toolを併用する構成でツール定義が大きい場合、ツール定義自体にブレークポイントを置き忘れると、system prompt側のブレークポイントだけでは狙った範囲までキャッシュが効きません

まとめ

Computer Useの長時間ループでプロンプトキャッシュを保つ鍵は、スクリーンショットの間引きを「毎ターン」ではなく「一定間隔でまとめて」行うことです。直近3枚を残して25ターンごとに間引くのが妥当な既定値で、Claude Fable 5.1ではクライアント側の間引きを避け、サーバー側のtool result clearingに任せます。リサイズと間引きは役割が違うため、両方を組み合わせて初めて履歴のサイズと枚数の両方を制御できます。ツール定義自体へのcache_controlも忘れずに設定すると、system prompt側だけでは届かない範囲までキャッシュを効かせられます。プロンプトキャッシュの基本的な仕組みはAnthropic APIのPrompt Cachingを理解する、自分でエージェントループを組む基礎はClaude Agent SDK入門を参照してください。

この記事を共有:XはてブLinkedIn