ブログ • AI / API

Claude API 2026 の新変化:Conversation Compaction とは何か?AI Agent はどう長コンテキストと圧縮後の状態を JSON で保存するのか?

Agent が長く走るほど、Messages 配列は長くなる。ツール結果、思考ブロック、ユーザーの往復が、コンテキストウィンドウを埋める。2026 年、Messages API はこれを公式機能にした:Conversation Compaction。

Compaction は、クライアントで自分で書いた要約を貼り戻すことではない。API が type: "compaction" の JSON を発行する。次のリクエストはこのブロックを messages に原状のまま戻さねば、セッションは圧縮後の状態から続かない。

本稿では次を扱う:

まずこれだけ:保存するのは「会話全文」ではない。最新の compaction ブロックと、その後ろでまだ食われていないターンだ。ブロック内の content、signature、encrypted_content は契約であり、注釈ではない。以下、「二通りの圧縮 → ブロックの形 → 保存リスト → 入れ替え規則」で分解する。

Compaction が圧縮するのはどの区間か

公式の位置づけは明確だ。サーバ側圧縮は長い会話と Agent ワークフローの推奨であり、クライアントで要約コードを書く必要はない。ウィンドウが古い内容で埋まると応答品質は落ちる。圧縮はより前の内容を要約に替え、有効なコンテキストを先へ進める。説明は

Claude API Compaction。

閾値圧縮を入れると、API は四段階で動く:入力 token が発火値に達する;要約を作る;compaction ブロックを書き、圧縮後のコンテキストで返答を続ける。次に assistant 応答の全体を messages に足すと、API はこのブロックより前の内容を捨て、要約から会話を続ける。

ロスがある。使ったツール引数、言い回しそのもの、初期の思考は一字一句残らない。残るのは目標、決定、あとで使う事実だ。「messages 配列ごとデータベースに入れる」こととは別だ。Agent 技術スタックでコンテキストがどう増えるかは

2026 AI Agent 技術スタック。

二通りの道:閾値圧縮とオンデマンド圧縮

2026 年は beta が二系統ある。同じリクエストに混ぜない。公式は compaction パラメータを context_management と一緒に送れないと書く。

経路 Beta ヘッダ JSON に書くもの ブロックが出る場所
閾値圧縮 compact-2026-01-12 context_management.edits に compact_20260112 通常の返答の先頭。後ろに text が続いてもよい
オンデマンド圧縮 compact-2026-09-04 トップレベル compaction: {"type":"summarize"} 単独の1件。stop_reason は compaction。通常の返答は無い

閾値圧縮の発火は既定で input_tokens 150000、下限は 50000。任意の pause_after_compaction:要約を書き終えたら先に止まり、直近ターンや指示的なメッセージをブロック後ろに差し戻してから生成を続けられる。カスタム instructions は既定の要約プロンプトを丸ごと置き換え、最長 16384 文字。

オンデマンド圧縮は 9 月ラインの要点だ。いつ圧縮するかはあなたが決める。要約リクエストはバックグラウンドで走らせ、会話は完全な履歴のまま続けてよい。直近数ターンの原文を要約の後ろに残すこともできる。署名付きブロックは messages の先頭に置かねばならない。要約済みのメッセージをブロックの前から外さないと 400 になり、エラー名は compaction_block_misplaced。Bedrock と Google Cloud にオンデマンド経路は無い。

圧縮前後の Messages JSON

圧縮前から見る。普通の user / assistant ターンだ。

オンデマンド圧縮リクエスト(公式ドキュメントからの抜粋)
{
  "model": "claude-opus-5",
  "max_tokens": 4096,
  "messages": [
    {
      "role": "user",
      "content": "I am building a recipe app. Help me name the main entities in the data model."
    },
    {
      "role": "assistant",
      "content": "Start with Recipe, Ingredient, and Step."
    },
    {
      "role": "user",
      "content": "Good. Now suggest field names for Recipe."
    }
  ],
  "compaction": { "type": "summarize" }
}

戻りは署名済み compaction ブロック1つだけ。stop_reason は compaction。以降の毎回のリクエストで、このブロックは先頭に置き、後ろには「今回の要約が食わなかった」ターンだけを付ける。

圧縮後の続き:ブロックが先頭、古いメッセージは除去済み
{
  "model": "claude-opus-5",
  "max_tokens": 2048,
  "messages": [
    {
      "role": "assistant",
      "content": [
        {
          "type": "compaction",
          "content": "Summary of the conversation: the user is designing the data model for a recipe app...",
          "signature": "EuYBCkQY..."
        }
      ]
    },
    {
      "role": "assistant",
      "content": "For Recipe, use title, description, servings..."
    },
    {
      "role": "user",
      "content": "Now do the same for Ingredient."
    }
  ]
}

閾値圧縮のブロックは、より「返答の内側」に挟まる。assistant の content 配列は先に compaction、そのあと text。何度も圧縮したら最後のブロックが正であり、今のプロンプトの最終状態を表す。API はこのブロックを見ると、それより前のコンテンツブロックを無視する。全体を回送してもよいし、古いメッセージを自分で捨て、このブロックから後ろだけ送ってもよい。

フィールド 何か 変えてよいか
type 固定 compaction できない
content 要約テキスト。失敗時は null 字を変えない。空文字列は不正
signature オンデマンド圧縮が返す署名 原状のまま回送する
encrypted_content 不透明なメタデータ。SDK の型は verbatim 回送を求める あれば原状のまま残す。解析しない。
cache_control 任意。要約だけに cache ブレークポイントを付ける 自分で付ける。発行フィールドではない

SDK は encrypted_content を「以前の圧縮が残した不透明なメタデータであり、verbatim で round-trip せねばならない」と書く。クライアントで分解せず、要約本文としても見せない。失敗ブロックの content が null のとき、サーバは空操作として扱う。回送はできるが、有効な要約にはならない。

session 復元のために保存すべきフィールド

Agent が再起動すると、メモリ上の messages は消える。復元すべきは「圧縮前の会話全文」ではなく、圧縮後もリクエストを続けられる状態だ。

  1. 1
    最新の compaction ブロック

    JSON ブロック全体。content、signature、encrypted_content を含む。複数あるときは最新の1つだけでよい。再圧縮すると古い要約とその後ろをまとめて食う。

  2. 2
    ブロック後ろの messages

    今回の要約が覆わなかった user / assistant ターンを、元の順で。バックグラウンド圧縮のあいだに伸びたターンもここにある。

  3. 3
    当時の system と tools

    オンデマンド圧縮では、要約リクエストに会話の残りと同じ system と tools を付ける。thinking を残すモデルでは、ブロック後ろのターンの thinking が無効にならないかは、この二項目を変えたか、および tail が要約されたメッセージに密着しているかで決まる。

  4. 4
    使っている beta はどちらか

    閾値圧縮は引き続き compact-2026-01-12 を付ける。オンデマンド圧縮のブロックは、以降の毎回のリクエストに compact-2026-09-04 を付ける。ヘッダが違うと、ブロックは認識されないことがある。

最小の session 保存形(例示であり、公式 schema ではない)
{
  "beta": "compact-2026-09-04",
  "model": "claude-opus-5",
  "system": "You are a coding agent.",
  "tools": [],
  "compaction_block": {
    "type": "compaction",
    "content": "Summary of the conversation: ...",
    "signature": "EuYBCkQY...",
    "encrypted_content": "..."
  },
  "tail": [
    {
      "role": "assistant",
      "content": "For Recipe, use title, description..."
    },
    {
      "role": "user",
      "content": "Now do the same for Ingredient."
    }
  ]
}

リクエストを組み直すとき、messages[0] にはこのブロックを持つ assistant を置く(または最初のメッセージの最初の content にブロックを入れる)。それから tail を連結する。圧縮前の古い user メッセージをブロックの前に戻さない。

これは権限評価と同じ層ではない。あちらは tool call が走ってよいかを見る。こちらはウィンドウが食われたあと、状態が残っているかを見る。権限の記事は

Claude Managed Agents はどう Tool Call の許否を自動判定するのか。

Claude はどう AI 研究開発ワークフローに関わるのか。

バックグラウンド圧縮と末尾を残すときの入れ替え

オンデマンド圧縮のリクエストは、受け取ったメッセージだけを要約する。だから古いターンだけを圧縮に出し、直近数ターンの原文はローカルに残し、戻ってきたブロックをそれらのターンの前に差し込める。公式名は keep-tail。

バックグラウンド圧縮(async)はさらに進む。要約が走っているあいだ、会話は完全な履歴のまま先へ行く。戻ってきたら履歴全体を1ブロックに置き換えてはいけない。先頭から「当時圧縮に送った分」だけを外し、返ってきた assistant メッセージを入れ、そのあと伸びたターンはそのまま残す。

バックグラウンド圧縮の入れ替え(公式の例示)
if response.stop_reason == "compaction":
    compaction_message = {
        "role": "assistant",
        "content": response.content,
    }
    history = [compaction_message] + history[sent_count:]
# sent_count = number of messages sent in the compaction request

途中で、すでに履歴にあるメッセージを変えない。入れ替えはブロックが届いたあとの最初のリクエストで行う。そうすれば要約中に生まれた thinking はまだ有効だ。ブロックが戻らなければ完全な履歴のままにし、あとで再試行する。

閾値圧縮で pause_after_compaction を入れると、応答はしばしばこのブロックだけになり、stop_reason も compaction になる。残したい原文をブロックの後ろに足して、次のリクエストを送る。注意:Claude Fable 5.1 では、古い assistant ターンをブロックの後ろに差し戻すなら、その中の thinking / redacted_thinking を外すか、thinking-binding-controls-2026-08-01 を付けて prefix_mismatch_behavior: "drop_block" を設定する。そうしないと 400 になりうる。それらの思考ブロックは完全な履歴に対して生成されており、圧縮後の会話とは噛み合わない。

prompt cache との重ね方

圧縮と prompt caching は併用できる。compaction ブロックに cache_control: {"type":"ephemeral"} を付け、要約だけをキャッシュしてよい。システムプロンプト末尾にもう一つブレークポイントを置く。圧縮が起きてもシステムプロンプトのキャッシュは当たり、書き直すのは要約の区間だけになる。

課金ではトップレベルの usage だけを見ない。圧縮イテレーションの token は usage.iterations に記されることがある。保存側が見るのは相変わらずブロックと tail であり、usage をセッション復元の契約にしてはいけない。

JSONNote でブロックと履歴を照合する

圧縮前後の JSON の体積差は大きく、フィールドは目視では追えない。デバッグでは位置を見る。文章の上手さは見ない。

  1. 1
    まず保存ファイルをフォーマットする

    session JSON を JSON フォーマット に入れ、compaction_block.type が compaction であり、signature が残っていることを確認する。

  2. 2
    次にブロックの形を検証する

    JSON Schema で最小 schema を書く。type の列挙は compaction だけ。content は string または null を許す。signature / encrypted_content があれば string として扱う。空文字列は禁止。

  3. 3
    圧縮前後の messages を比べる

    JSON Diff で、先頭から消えたターンとブロック後ろに増えたものを見る。オンデマンド圧縮のあと、ブロックの前に要約済みの user メッセージが残ってはいけない。

  4. 4
    振り返りでは署名をマスクする

    要約本文は人に見せてよい。署名と不透明フィールドは Hash 共有 の前にマスクする。セッションを続ける材料なので、普通のテキストとして出さない。

よくある質問

Conversation Compaction は会話全体を消すのか?

消さない。API はすでに圧縮された古いメッセージを要約で置き換える。要約は type が compaction のコンテンツブロックに入る。このブロックを原状のまま回送しなければ、セッションは要約から続けられない。

session を復元するには、最低どの JSON を残すのか?

少なくとも最新の compaction ブロック(content、signature、encrypted_content を含む)、ブロック後ろの全部の messages、および当時の system と tools。署名や不透明フィールドを落とすと、次のリクエストは繋がらない。

閾値圧縮と 9 月のオンデマンド圧縮はどう違うのか?

閾値圧縮は compact-2026-01-12 を使い、通常のリクエスト内で token 数で発火する。オンデマンド圧縮は compact-2026-09-04 を使い、compaction: {type: summarize} を単独で送り、署名付きブロックを返す。そのブロックは messages の先頭に置かねばならない。

自分で書いた要約テキストは compaction ブロックの代わりになるか?

同じ契約としては使えない。プラットフォームが認めるのは、自分が発行したブロックだ。自分で書いた user テキストは別のメッセージにすぎず、signature も無く、API にブロックより前の古い内容を捨てさせることもできない。

compaction ブロックの content を書き換えて戻してよいか?

変えない。公式は原状のまま回送することを求める。content が空文字列は不正。content が null は圧縮失敗を意味し、サーバは空操作として扱う。signature や encrypted_content を変えると、後続リクエストは失敗するか、要約を失う。

まとめ

Conversation Compaction は「ウィンドウが弾けそう」を、回送できる JSON ブロックに収める。閾値圧縮は通常のリクエスト内で自動で起きる。9 月のオンデマンド圧縮は、いつ圧縮するか、バックグラウンドでよいか、直近ターンの原文を残すかをあなたが決める。

session の復元は、最新の compaction ブロックとその後ろの tail であり、圧縮前の全文ではない。content、signature、encrypted_content は原状のまま保存し、原状のまま送る。ブロックの位置が違えば、API はあの履歴をまだ持っているふりをしない。

ブロックと tail を二つの契約として読む。人が見張る長いタスクでは、要約の instructions に残すべき実体と未決の問題を書く。割り込みを減らしたい Agent は、オンデマンド圧縮でバックグラウンドにブロックを入れ替える。メモリに自分で書いた説明だけを残さない。

← ブログに戻る