Claude Media
Compactionの発動しきい値の決め方 — モデル別の比率で考える

Compactionの発動しきい値の決め方 — モデル別の比率で考える

サーバーサイドcompactionのtrigger.valueをどう決めるか、モデルのコンテキストウィンドウに対する比率と予算管理の計算例で考えます。

trigger.valueが閾値そのもの

しきい値方式のcompaction(Compaction at a token thresholdと呼ばれるもの)では、context_management.editsにcompact_20260112を指定します。このときtriggerのvalueが、要約を発動させる入力トークン数です。既定値は15万トークン、指定できる最小値は5万トークンで、typeに使えるのはinput_tokensだけです。この1つの数字で、会話がどこまで育ってから要約に切り替わるかが決まります。

curl https://api.anthropic.com/v1/messages \
    --header "x-api-key: $ANTHROPIC_API_KEY" \
    --header "anthropic-version: 2023-06-01" \
    --header "anthropic-beta: compact-2026-01-12" \
    --data '{
        "model": "claude-opus-5",
        "max_tokens": 4096,
        "messages": [{"role": "user", "content": "Hello, Claude"}],
        "context_management": {
            "edits": [
                {"type": "compact_20260112", "trigger": {"type": "input_tokens", "value": 150000}}
            ]
        }
    }'

閾値を低くすると要約が頻繁に起き、アクティブなコンテキストは小さく保たれます。高くすれば1回のリクエストで多くの文脈を持てますが、コンテキストウィンドウの上限に近づくリスクも増えます。しきい値方式のページには、閾値の推奨値は書かれていません。判断の材料は、モデルのウィンドウサイズ、要約にかかるコスト、直近のやり取りをどこまで原文で残したいかの3つです。

そもそも閾値を決める方式が必要か

compactionには、閾値方式のほかにオンデマンド方式があります。公式の比較表では、オンデマンド方式が使える場面ではそちらを使うよう案内されています。両方がベータの間は、オンデマンドのほうが一般的な用途をカバーするとも書かれています。

くらべる

閾値方式とオンデマンド方式

trigger.valueを使う

閾値方式

入力トークンがtrigger.valueに届いた時点で、APIがリクエストの途中で要約します。書き足すコードは通常のリクエストへのパラメータ1つです。要約はそのリクエストの中で走るため、バックグラウンド実行はできません。

要約のタイミングを自分で決める

オンデマンド方式

要約を依頼するリクエストを自分で送り、返ってきたブロックをmessagesの先頭に差し替えます。ループを自前で書く必要がありますが、バックグラウンドで要約を走らせたり、直近のターンを原文のまま残したりできます。ベータヘッダーはcompact-2026-09-04で、トップレベルのcompactionパラメータを使います。

要約の発動時期をアプリ側で握りたい、要約中に会話を止められない、といった条件に当てはまるなら、閾値の設計より先にオンデマンド方式を検討する余地があります。手順はオンデマンドで要約する方法にまとめています。閾値方式で直近のターンを残す場合は、pause_after_compactionで止めてから再挿入する形になります。

閾値は窓の何%かで見る

閾値の数字は、モデルのコンテキストウィンドウに対する比率に直すと意味がつかめます。しきい値方式の対応モデルは13種類で、Claude Fable 5.1・Claude Mythos 5.1・Claude Opus 5.5・Claude Sonnet 5.5をはじめ、Opus 4.6・Sonnet 4.6までが並びます。コンテキストウィンドウの一覧では、この13種類はすべて100万トークンです。

数字

対応モデルの窓と閾値

  • 最小値

    5万

    窓の5%

  • 既定値

    15万

    窓の15%

いずれもトークン数。比率は100万トークンの窓に対する値

200kトークンの窓を持つClaude Sonnet 4.5などは、しきい値方式の対応モデルに含まれません。

窓に対する比率と、予算管理で使う回数の見積もりを並べると、閾値ごとの性格が見えてきます。公式の予算管理の例は、compactionの回数に閾値を掛けた値でおおまかな累積消費を見ます。次の表は、その式を300万トークンの予算に当てはめたものです。

閾値窓に対する比率300万トークンに達するまでのcompaction回数
5万窓に対する比率5%300万トークンに達するまでのcompaction回数60回
10万窓に対する比率10%300万トークンに達するまでのcompaction回数30回
15万(既定)窓に対する比率15%300万トークンに達するまでのcompaction回数20回
30万窓に対する比率30%300万トークンに達するまでのcompaction回数10回
50万窓に対する比率50%300万トークンに達するまでのcompaction回数6回

回数は300万 ÷ 閾値の単純な割り算で、実際の要約の長さや再要約の挙動は含みません。閾値を下げるほど回数が増え、そのたびに会話全体が要約の入力になります。予算管理の例ではTRIGGER_THRESHOLD = 100_000が使われています。予算を超えそうなときに締めくくりを促す実装は、compactionの回数で予算を制御する方法で組み立てています。

発動の流れと、1回では終わらない点

閾値を決める前に、要約が起きたあとの流れを押さえておきます。

手順

閾値に届いたときにAPIが行うこと

  1. 1

    入力トークンが閾値に達する

    APIが、入力トークン数がtrigger.valueに届いたことを検出します。

  2. 2

    会話全体を要約する

    その時点の会話を要約し、compactionブロックとして返します。

  3. 3

    要約を土台に続きを生成する

    同じリクエストの中で、圧縮された文脈からレスポンスを続けます。

  4. 4

    次のリクエストで古い内容を捨てる

    レスポンスをそのままmessagesに追加すると、compactionブロックより前の内容をAPIが落とし、要約から会話を続けます。

この流れは会話が続く限り繰り返されます。要約を起点にトークンが再び積み上がり、閾値に達すれば次のcompactionが起きます。閾値は会話全体で1回だけ働くスイッチではなく、繰り返し発動する周期を決める値です。低い閾値は周期を短くして毎回の要約対象を小さく保ち、高い閾値は周期を伸ばして要約の呼び出し回数を減らします。

サーバーツールを使うリクエストでは、発動の判定が各サンプリングイテレーションの開始時に行われます。出力が長くなるタスクでは、1回のリクエストの中でcompactionが複数回起きることもあります。想定より発動回数が増えたように見えるのは、この判定の仕組みによるものです。

usage.iterationsで発動を確かめる

設定した閾値が意図どおりに働いているかは、レスポンスのusage.iterationsで見られます。compactionが起きたリクエストには、type: "compaction"のエントリとtype: "message"のエントリが並びます。

{
  "usage": {
    "input_tokens": 23000,
    "output_tokens": 1000,
    "iterations": [
      {"type": "compaction", "input_tokens": 180000, "output_tokens": 3500},
      {"type": "message", "input_tokens": 23000, "output_tokens": 1000}
    ]
  }
}

このレスポンスでは、トップレベルのusageの値と、課金対象になる値がずれます。

数字

同じリクエストの2通りの数え方

  • トップレベル(入力)

    23,000

    messageイテレーションだけ

  • iterations合算(入力)

    203,000

    180,000 + 23,000

  • iterations合算(出力)

    4,500

    3,500 + 1,000

公式ドキュメントのレスポンス例の数値から計算

トップレベルの値は、compaction以外のイテレーションの合計です。消費量や課金を集計するコードは、usage.iterationsの全エントリを足す必要があります。compactionのベータを有効にすると、発動しなかったリクエストでもiterationsが付きます。compactionエントリが現れるのは、そのリクエストで新たに要約が走ったときだけです。以前のcompactionブロックを再び適用するだけなら、要約の追加コストはかかりません。

最後のイテレーションのトークン数は、compaction後の実効的なコンテキストの大きさを表します。この例では23,000トークンまで縮んだことが分かります。compactionエントリのinput_tokensは、要約に渡された入力の大きさです。trigger.valueと見比べれば、どの大きさで要約が走ったかの目安になります。

頻度とコストのトレードオフ

compactionには追加のサンプリングステップがあり、レート制限と課金の両方に影響します。閾値を下げるほど要約の回数が増え、要約のたびに会話全体の入力トークンと要約文の出力トークンが課金対象になります。

要約に使うのは、リクエストで指定したモデルそのものです。要約だけ安価なモデルに切り替えるオプションはありません。高価なモデルで低い閾値を設定すると、要約1回ごとのコストも高くなります。

逆に閾値を上げる方向のリスクは、ウィンドウの上限に届くことです。入力だけで窓を超えるとステータス400のinvalid_request_error(「prompt is too long」)が返ります。Claude 4.5以降のモデルでは、入力とmax_tokensの合計が窓を超えてもリクエスト自体は受理されます。生成の途中で上限に届くと、stop_reasonがmodel_context_window_exceededになって止まります。4.5より前のモデルでは、検証エラーが返ります。

閾値は、要約のコストと上限到達のリスクの間で決める値です。Claude Codeの/compactで似た文脈のエラーに出会った場合は、Error during compactionの意味と対処を参照してください。こちらはClaude Codeの機能で、本記事のtrigger.valueはAPIのパラメータです。

閾値選びでつまずきやすい点

  • 高く取りすぎて精度が落ちる: 窓に対して文脈が大きいまま長く続くと、トークンが増えるにつれて精度と再現率が下がるcontext rotの影響を受けます。公式のcompactionの説明も、会話が育つと応答の質が下がるため、アクティブな文脈を小さく保つ目的を挙げています。閾値は、窓を使い切らないための値というより、質が落ち始める前に畳むための値として考えます。Effective context engineeringが扱う長時間エージェントの設計と合わせて読むと整理しやすくなります
  • 要約の中でツールが呼ばれて失敗する: リクエストにtoolsが含まれると、要約の内部ステップでモデルがツールを呼ぶことがあります。その場合はcompactionブロックのcontentがnullになります。閾値を下げて発動頻度を上げるほど、この失敗に当たる回数も増えます。instructionsで「ツールを呼ばずテキストだけで答える」と指定する対策が、公式に示されています
  • 要約に残る情報はモデルによって違う: Claude Fable 5.1・Claude Mythos 5.1・Claude Opus 5.5・Claude Sonnet 5.5では、compactionブロックより前のthinkingブロックは引き継がれません。要約が、それ以前の作業について残る唯一の手がかりになります。instructionsを自分で書く場合は、要約が保持すべき内容を明示します。カスタム指示は既定のプロンプトに追加されるのではなく、完全に置き換わります。書き方は要約プロンプトのカスタマイズで扱っています
  • 直近のターンを残すときのthinking: pause_after_compactionで止めて直近のターンを再挿入する場合、Fable 5.1・Opus 5.5・Sonnet 5.5では再挿入するターンのthinkingを外すよう、公式の比較表に書かれています。オンデマンド方式の直近のターンを残すcompactionは、この点の扱いが異なります

ツールランナーのcompaction_controlとの混同

compactionという言葉は2か所で使われます。本記事の対象は、context_management.editsにcompact_20260112を指定するサーバー側のcompactionです。

これとは別に、TypeScriptとRubyのSDKのツールランナーには、クライアント側のcompaction_controlがあります。こちらにもcontextTokenThresholdという閾値があり、既定は10万トークンです。ただし、compaction_controlはTypeScriptとRubyで非推奨で、将来のバージョンで削除される予定です。Python SDKはv1.0で削除済みで、Go・Java・C#・PHPのツールランナーには最初から含まれません。

ツールランナーでサーバー側のcompactionを使うには、リクエストのcontext_managementにcompact_20260112のエディットを渡します。ランナーでcompact_before_next_turn()のようなオンデマンド用のヘルパーを使う場合は、context_managementのcompactionエディットのどちらか一方だけを使います。閾値の選び方を調べていてcontextTokenThresholdに行き当たったときは、廃止予定の別機能の話です。

まとめ

閾値は、要約の回数が増えるコストと、窓や質の限界に近づくリスクのどちらを重く見るかで決まります。迷うなら、最初は既定値の15万から始め、usage.iterationsで実際の発動を見てから動かす進め方があります。

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