Preserved thinkingとは — Messages APIのthinking block保護策
Claude Fable 5.1とOpus 5.5で有効になった蒸留対策の仕組みと、システムプロンプトやツール改変が原因で起きる400エラーの回避策をまとめます。
Preserved thinkingとは
Preserved thinkingは、Messages APIが送り返されたthinkingブロックを再利用してよいかを検証する仕組みです。Claude Fable 5.1とClaude Opus 5.5から有効になりました。APIはthinkingブロックのsignatureを見て、そのブロックより前のsystemプロンプト・tools・messagesが、そのブロックを生成したときと一字一句変わっていないかを確認します。変わっていれば、そのブロックとそれ以降のthinkingブロックは無効になります。
狙いは蒸留(distillation)対策です。会話の前の部分を書き換えて、暗号化されたthinkingブロックをClaudeに復号・出力させる手口が、他モデルの学習用データを不正に抽出する蒸留キャンペーンで広く使われてきました。Preserved thinkingは、この書き換えそのものを検知して弾くことで攻撃を難しくします。
何がチェックされるのか — prefixの3要素
APIが比較する対象は「そのthinkingブロックが生成されたときの直前の状態」で、次の3つに限定されます。
- 直近のリクエストで送った
systemプロンプト toolsの一覧- そのブロックより前にある全
message
サーバー側のcompaction(コンパクション)を使っている場合は、直近のcompactionブロック以降がチェック対象になります。逆にeffort・max_tokens・output_config・tool_choice・metadata・cache_controlはこのprefixに含まれず、変更してもthinkingブロックは無効になりません。
thinkingブロック自体は先頭から・末尾から・全部を削除しても構いません。ただし途中の1件だけを抜くと、それ以降のブロックがすべて無効になります。一度抜いたブロックを後から元に戻す操作も、抜けていた間に生成されたブロックを無効にします。「削除は端からのみ、途中を虫食いにしない」がこの仕組みの基本ルールです。
無効になったときAPIはどう振る舞うか
無効なthinkingブロックへの対応はthinking.block_binding.prefix_mismatch_behaviorで選びます。
"error"(既定): 最初に失敗したブロックを名指しした400のinvalid_request_errorでリクエストを拒否します"drop_block": 失敗したブロックとそれ以降のthinkingブロックを落として、リクエストは成立させます。落とされたブロックは課金されず、その代わりモデルはそのターンを過去の推論なしで答えます。プロンプトキャッシュもその編集地点から作り直されます
このフィールドと、応答に含まれるinput_transformations配列(どのブロックが落とされたかを示す)は、どちらもthinking-binding-controls-2026-08-01ベータヘッダーが必要です。ヘッダーを付けずにblock_bindingを送ると、block_binding: Extra inputs are not permittedという400エラーになります。
400になったときの手順は公式ドキュメントが2段階で示しています。まず400のメッセージ自体が、無効になった最初のブロックの位置(messages.1.content.0のようなcontentのパス)と、原因がsystemかtoolsかmessagesかを名指しします。同じボディを再送しても同じ理由で失敗し続けるので、ベータヘッダーを付けてprefix_mismatch_behavior: "drop_block"で一度リトライしつつ、直近数ターン分の送信リクエストを記録しておき、連続する2回のリクエスト同士で名指しされた位置までのsystem・tools・messagesを突き合わせて、どこで内容が変わったかを特定します。特定できたら、その編集を後述の「編集せずに同じことをする方法」の該当パターンに置き換えます。
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: thinking-binding-controls-2026-08-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"thinking": {
"type": "adaptive",
"block_binding": {
"prefix_mismatch_behavior": "drop_block"
}
},
"messages": [
{"role": "user", "content": "1071と462の最大公約数は?"}
]
}'"drop_block"はエラーを見えなくするだけで、原因になった編集そのものは直りません。ブロックが落とされた分の課金は発生しませんが、Claudeが落とされた推論を再構築しようとしてトークン消費が増えることがあります。落とされたブロックが多いセッションや、長いセッションで繰り返し起きる場合ほど増加幅は大きくなる、と公式ドキュメントは注記しています。
なぜこの変更が必要なのか
Claudeのthinkingブロックは暗号化されて返されます。会話の前の部分(システムプロンプト・ツール定義・過去メッセージ)を書き換えてから同じthinkingブロックを送り返すと、Claudeにその暗号化された推論を復号・出力させられてしまうケースがありました。これは大量の偽アカウントを使った産業規模の蒸留キャンペーンで実際に使われてきた手口です。
抽出した推論で別モデルを訓練すると、そのモデルはClaudeの能力の一部を引き継ぐ一方で、Anthropicがサイバー攻撃や兵器開発のような悪用を防ぐために組み込んだ安全策までは引き継ぎません。Preserved thinkingは、既存の蒸留対策(蒸留検知の分類器や、上位モデルから下位モデルへのセッション・推論の転送制限)に加える形の対策です。
対象になるモデルとアカウント
| 対象 | 2026年8月31日(UTC)以降に作成したアカウント | それより前のアカウント |
|---|---|---|
| Claude Fable 5.1 | 2026年8月31日(UTC)以降に作成したアカウント既定で強制("error") | それより前のアカウントprefix_mismatch_behaviorを明示したリクエストのみ強制 |
| Claude Opus 5.5 | 2026年8月31日(UTC)以降に作成したアカウント既定で強制("error") | それより前のアカウントprefix_mismatch_behaviorを明示したリクエストのみ強制 |
| Claude Mythos 5.1・それ以前のモデル | 2026年8月31日(UTC)以降に作成したアカウントprefixチェックを実行しない | それより前のアカウントprefixチェックを実行しない |
対象はClaude Platform組織のほか、Amazon Bedrock・Google Cloud Vertex AI・Microsoft Foundryの各アカウントも同じ基準です。古いアカウントでも、prefix_mismatch_behaviorを設定したリクエストを送れば新しいアカウントと同じ挙動を先取りして確認できます。設定せずにベータヘッダーだけ送ると、失敗したブロックはinput_transformationsにthinking_mismatch_allowedとして記録されつつモデルには渡り、リクエスト自体は失敗しません。
モデルをまたぐ場合の扱いも決まっています。Claude Fable 5.1とMythos 5.1は互いと、それより前のモデルのthinkingブロックを読めます。Claude Opus 5.5はOpus 5以前のOpus・Sonnet・Haikuのブロックを読めますが、FableやMythosのブロックは読めません。Fable 5.1・Mythos 5.1からOpus 5.5へ、あるいはOpus 5.5からそれ以外のモデルへ切り替えると、切り替え後のターンはそれまでの推論なしで実行されます(エラーにはならず、黙って落とされます)。
実装のどこが「編集」に当たるか
公式ドキュメントは、連続する2回のリクエストを比較して何が無効化を起こすかを一覧にしています。実装で踏みやすいのは次の5パターンです。
- システムプロンプトを毎回組み直す: 現在時刻・モードフラグ・再読み込みしたプロジェクト指示・後から接続したMCPサーバーの情報などを
systemに埋め込み直すと、会話全体のthinkingが無効になります - 最初のuserメッセージでコンテキストを再描画する: 作業ディレクトリ・ブランチ・日付・メモリなどを
messages[0]に埋めて毎回作り直す実装は同じ問題を起こします - 古いtool_resultをその場で削る・縮める: 画像の再エンコードも含め、過去のツール結果を書き換えるとそれ以降のthinkingが無効になります
tools配列を直接編集する: ツールの追加・削除・改名・スキーマ変更はすべて無効化の対象です- クライアント側でターンを間引く・要約する: 古いターンを消して直近のターンだけをそのまま送る自前のコンテキスト圧縮も、残したターンのthinkingを無効にします
逆に、末尾へのメッセージ追加・cache_controlマーカーの位置変更・effortやoutput_configの変更・同じバイト列を返す署名付きURLの入れ替えは、prefixの対象外なので無効化を起こしません。
編集せずに同じことをする方法
公式ドキュメントは、上記の編集それぞれに「prefixを変えずに同じ効果を得る」代替パターンを挙げています。
- 指示の追加:
systemを書き直す代わりに、role: "system"のメッセージを会話の途中に追加する(Mid-conversation system messages、ベータヘッダー不要) - 変化する情報: 環境情報を毎回描き直す代わりに、変わった値だけを直近のuserターンに追記する
- ツールの入れ替え:
toolsを編集する代わりに、tool_addition・tool_removalブロックを載せたsystemメッセージを追加する(ベータヘッダーinline-tools-2026-09-15、または旧mid-conversation-tool-changes-2026-07-01) - effortの変更: トップレベルの
output_config.effortを変える代わりに、ターンごとのoutput_configをsystemメッセージに載せて送る(ベータヘッダーmid-conversation-output-config-2026-07-01) - 古いターンの間引き: クライアント側の要約の代わりに、on-demand compactionでAPI側に要約させ、その署名付きブロックを差し替える(ベータヘッダー
compact-2026-09-04)。あるいはcontext editingのclear_tool_uses_20250919のようなサーバー側の間引きを使う
どのパターンでも共通する前提は、アシスタントターンをAPIが返した通りに一字一句送り返すことです。空のthinkingフィールドを持つブロックも省略せずに送り返す必要があります。シリアライザが未知のブロック型や空フィールドを落とす実装だと、それだけで以降の全ターンのthinkingが無効になります。
一番シンプルで確実な圧縮方法は、会話全体を1つのuserメッセージに要約し、それより前のターンを一切送り返さないことです。送り返すthinkingが無いのでチェック自体が発生せず、Claudeは要約から推論をやり直します。
Claude Code・Claude Agent SDK利用者への影響
Claude Code・Claude Cowork・claude.ai・Claude Agent SDKでリクエストを組み立てている場合、この変更で何かを直す必要はありません。これらの製品は内部でthinkingブロックの送り返しを適切に処理しています。影響を受けるのは、自前のハーネスやMCPサーバー統合でMessages APIを直接叩いている実装です。
利用形態別の影響早見表
| 利用形態 | 影響度 | 理由 |
|---|---|---|
| Claude Code / Claude Cowork / claude.ai / Claude Agent SDKをそのまま使う | 影響度ほぼ影響なし | 理由各製品がthinkingの送り返しを内部で処理する |
自前ハーネスでsystem・toolsを固定しmessagesに追記するだけ | 影響度ほぼ影響なし | 理由prefixを変えない実装なのでチェックに引っかからない |
| 自前ハーネスでクライアント側の要約・コンテキスト圧縮を実装 | 影響度条件次第 | 理由古いターンを書き換える圧縮ロジックはthinkingを無効にする。on-demand compactionへの移行か、圧縮時にthinkingブロックを外す対応が要る |
| プロキシ・ゲートウェイとしてAPIとの間に立つ実装 | 影響度条件次第 | 理由呼び出し元のanthropic-betaやblock_bindingを転送しないと、ユーザーが"drop_block"を選べなくなる |
| 2026年8月31日以降に作成したアカウントでFable 5.1・Opus 5.5を使う | 影響度条件次第 | 理由蒸留耐性そのものはAnthropic側の効果で、読者側は既定の"error"で400を受ける立場になる。prefixを編集する実装は"drop_block"の指定か実装修正が要る |
thinkingの一貫性はプロンプトキャッシュにも効く
Preserved thinkingが求める「systemとtoolsを固定しmessagesを追記のみにする」実装規律は、そのままプロンプトキャッシュのヒット率を保つ規律とも重なります。prefixを書き換える編集はキャッシュを再構築させる編集でもあるため、thinkingの無効化を避ける設計に寄せるほど、副次的にキャッシュのヒット率も安定します。thinking blocks cannot be modifiedエラーも、送り返した履歴のthinkingブロックを書き換えると起きる点は共通していますが、こちらは最後のassistantターンのブロックを直接改変したときのエラーで、仕組みは今回のprefixチェックとは別物です。
まとめ
Preserved thinkingは、Claude Fable 5.1とOpus 5.5のMessages APIに入った、蒸留対策のためのprefix検証です。system・tools・過去のmessagesを書き換えずに追記だけで会話を進めている実装は何もする必要がありません。逆に、システムプロンプトの再構築・古いツール結果の書き換え・自前のコンテキスト圧縮を行っている自前ハーネスやプロキシは、2026年8月31日以降に作成したアカウントでFable 5.1・Opus 5.5を使い始める前に、thinking-binding-controls-2026-08-01ベータヘッダーで自分の実装がprefixを変えていないか確認しておく価値があります。Extended thinkingとAdaptive thinkingの違いを先に押さえておくと、どのモデルでこのチェックが働くかも理解しやすくなります。