Claude Media
redacted_thinkingブロックとは — 読めない思考をそのまま返送する

redacted_thinkingブロックとは — 読めない思考をそのまま返送する

redacted_thinkingは、安全上の理由で編集された思考が暗号化されて返るブロックです。dataフィールドの扱い、signatureとの違い、ツール併用時にtypeで絞って落とさないための実装を扱います。

redacted_thinkingは、Claudeの思考の一部が安全上の理由で編集されたときに、通常のthinkingブロックの代わりに返るブロックです。中身はdataフィールドに暗号化されて入り、人が読める本文はありません。読めないブロックですが、ツールを使う会話では捨てずに、受け取ったまま次のリクエストへ戻す必要があります。

redacted_thinkingは何を返すブロックか

通常のthinkingブロックは、思考の本文とsignatureを持ちます。redacted_thinkingは、思考のうち安全上の理由で編集された部分を、暗号化したまま運ぶブロックです。形は次のとおりです。

{
  "type": "redacted_thinking",
  "data": "..."
}

dataは不透明な暗号化データです。解釈も加工もできません。扱いはthinkingブロックのsignatureと同じで、ツールを使うマルチターンの会話ではAPIへ変更せずに戻します。

「一部が」という点に注意が必要です。このブロックが返るのは、推論の一部が安全上の理由で編集されたときです。どの内容がどんな条件で編集されるかは、Thinkingのページに記載がありません。発生を予測して分岐を書くより、いつ届いても素通しで戻せる実装にしておく設計が現実的です。

thinking・omitted・redactedの違い

読める本文がないブロックは、原因が2種類あります。名前が似ているため混同されやすいので、並べておきます。

見分けるものtypeの値本文中身の所在起きる条件
通常のthinkingtypeの値thinking本文設定によって返る中身の所在signature起きる条件thinkingが有効なとき
display省略typeの値thinking本文thinkingが空文字中身の所在signature起きる条件display: "omitted"を指定、または省略が既定のモデル
安全上の編集typeの値redacted_thinking本文なし中身の所在data起きる条件推論の一部が安全上の理由で編集されたとき

display: "omitted"は、呼び出し側が選ぶ表示設定です。ブロックのtypeはthinkingのままで、thinkingフィールドが空になります。redacted_thinkingは別のtypeを持つ別のブロックです。Thinkingのページにも、この2つは別物だという注記があります。

フィールドが空で届いたときの原因切り分けは、thinkingのdisplay: summarizedとはにまとめています。typeがthinkingなら表示設定の話、redacted_thinkingなら安全上の編集の話です。

dataとsignatureはどう違うか

どちらも暗号化された不透明な値で、解釈してはいけない点は同じです。違いは、どのブロックのどの情報を運ぶかにあります。

  • signature: 通常のthinkingブロックが持つ。完全な思考の暗号化された内容を運び、ブロックがClaudeの生成物であることをAPIが検証するのに使う
  • data: redacted_thinkingブロックが持つ。編集された思考の暗号化された内容そのもの

signatureは、thinkingブロックに読める本文があってもなくても付きます。dataは、読める本文がないredacted_thinkingの中身そのものです。どちらも、中身を読んだり書き換えたりする対象ではありません。

ツール併用時はなぜ変更せず返すのか

ツールを使うとき、Claudeはツール呼び出しの手前でいったん応答の組み立てを止め、結果を待ちます。結果を返すと同じ応答の続きを組み立てるので、それまでの推論が手元に残っていなければなりません。ツール結果はuserメッセージとして届きますが、全体は一続きの推論の流れです。

ここで求められる条件が、最新のアシスタントメッセージの中の連続するthinking系ブロックの並びが、モデルが生成した元の並びと一致することです。並べ替え、編集、一部の削除はできません。この条件にはredacted_thinkingブロックも含まれます。

ツールを使わない会話では扱いが緩みます。整理は次のとおりです。

  • 必須: ツール利用のターンの中では、thinkingブロックを戻す
  • 推奨: ターンをまたぐときは、すべてを戻す
  • 許容: ツールを使わないなら、過去のターンのthinkingは省いてよい

なお、過去のターンのブロックをAPIが残すか外すかはモデルごとに異なります。自分で間引かなくても、APIが自動で処理します。

typeで絞ると黙って落ちる

実装で最も起きやすい失敗は、content配列を型で絞る処理です。ツール結果を戻す前にthinkingだけを残そうとすると、redacted_thinkingが黙って捨てられます。block.type == "thinking"だけで絞るとredacted_thinkingが落ち、マルチターンのプロトコルが壊れます。

次のコードは、往復の例に沿った考え方を、フィルタを挟みたくなる場面に当てはめた書き方です。

# 悪い例: thinking だけ残すと redacted_thinking が消える
kept = [b for b in response.content if b.type in ("thinking", "tool_use")]
 
# 良い例: 受け取った content をそのまま積み戻す
messages.append({"role": "assistant", "content": response.content})

どうしても型で絞る必要があるなら、thinkingとredacted_thinkingを両方含めます。ただし、ツール併用の往復例はresponse.contentをそのまま戻す書き方です。絞る処理を挟むほど、並びを崩す余地が増えます。

往復コードのどこでブロックを触るか

往復の例では、tool_useブロックから取り出すのはIDだけです。応答のcontent配列そのものは、手を入れずに次のリクエストへ載せます。

# 1回目: ツール付きでthinkingを有効にして呼ぶ
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=16000,
    thinking={"type": "adaptive"},
    tools=[weather_tool],
    messages=[{"role": "user", "content": "What's the weather in Paris?"}],
)
 
# IDだけを取り出す。contentは加工しない
tool_use_block = next(b for b in response.content if b.type == "tool_use")
 
# 2回目: アシスタントのcontentをそのまま積み、ツール結果を続ける
continuation = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=16000,
    thinking={"type": "adaptive"},
    tools=[weather_tool],
    messages=[
        {"role": "user", "content": "What's the weather in Paris?"},
        {"role": "assistant", "content": response.content},
        {"role": "user", "content": [{
            "type": "tool_result",
            "tool_use_id": tool_use_block.id,
            "content": "Current temperature: 88°F",
        }]},
    ],
)

next(...)で型を絞っているのはIDを探す箇所だけで、messagesに積むのは絞る前のresponse.contentです。thinkingが先頭に来ても、redacted_thinkingが混ざっても、この書き方なら並びが崩れません。thinkingブロックはtool_useブロックと一緒に戻す必要があります。

ストリーミングで受けるとき

ストリーミングでは、thinkingブロックはthinking_deltaイベントで流れ、content_block_stopの直前にsignature_deltaが1回届きます。Thinkingのページが説明しているイベント列はこのthinkingブロックのものです。redacted_thinkingのイベント形式は、このページに記載がありません。

自分でデルタをつなぎ直すと、署名つきのブロックを正しく組み直す責任を負います。SDKには完成したメッセージを組み立てるヘルパーがあり、Pythonならstream.get_final_message()、TypeScriptならstream.finalMessage()です。ストリーミングの場合も、組み立て済みのメッセージのcontentをそのまま次のリクエストへ積めば、往復の考え方は変わりません。

履歴を保存・圧縮するとき

保存して再送する構成では、ブロックの並びとtypeを変えない形で持たせるのが前提です。content配列を取り出した順に保存し、textとtool_useだけを抜き出して持つ作りにすると、再送時に並びが元と違ってしまいます。

履歴を圧縮するときは、Claude Fable 5.1以降の移行ガイドに具体的な指示があります。直近のターンを要約の後ろにそのまま残す方式では、そのターンのthinkingとredacted_thinkingブロックを取り除くか、prefix_mismatch_behavior: "drop_block"を設定します。残すのはtextとtool_useです。そのブロックは完全な履歴を前提に作られているため、要約の後ろに置くと検証に失敗するからです。要約1件と次のユーザーターンだけを送る単純な圧縮なら、思考ブロックが残らず、この問題は起きません。

強制ツール選択とredacted_thinking

tool_choiceでツール利用を強制する場合、応答はツール呼び出しから始まり、thinkingブロックがありません。その応答には、戻すべきredacted_thinkingもありません。Claude Opus 5.5、Claude Sonnet 5.5、Claude Fable 5.1、Claude Mythos 5.1は、強制ツール選択そのものを400エラーで拒否します。考えさせてからツールを呼ばせたいときはtool_choice: {"type": "auto"}を使い、プロンプトでツールを使う場面を指定します。

戻したブロックは課金とキャッシュにどう効くか

戻したブロックが全部入力トークンになるわけではありません。ターンをまたいで全部を戻すと、APIが自動で選別し、モデルに実際に見せたブロックの分だけを入力として課金します。

選別の既定はモデルで分かれます。

  • 過去のターンのthinkingを全部保持する: Claude Opus 4.5以降のOpus、Claude Sonnet 4.6以降のSonnet、Claude Haiku 5.5、Claude Fable 5.1など
  • 直近のターンだけ保持する: それより古いOpusとSonnet、Claude Haiku 4.5までのHaiku

保持するモデルでは、長い会話ほど思考ブロックがコンテキストを占めます。ツール結果を返すリクエストでは、それまでの履歴が思考ブロックごとキャッシュされ、読み出し時に入力トークンとして数えられます。cache_controlを付けなくても自動で起きる挙動です。thinkingの設定やeffortの値を変えると、キャッシュは新しい接頭辞から始まります。

間引きたいときは、自前でredacted_thinkingを削るより、コンテキスト編集のclear_thinking_20251015戦略を使うのが筋です。型で絞る処理を足さずに済みます。

表示側での扱い

画面にthinkingの本文を出しているアプリでは、redacted_thinkingに出せる本文がありません。この点は仕様なので、表示処理を分けておくと安全です。

  • UIでは、type == "thinking"の本文だけを描画する
  • redacted_thinkingは描画せず、履歴の保持だけ行う
  • ログに残すときは、dataの長さやブロックの有無までに留める

dataは不透明なフィールドで、解釈や加工を想定していません。表示用に読み解く対象にはなりません。

400エラーが出たときの切り分け

redacted_thinkingを落とすと、ツール結果を戻すリクエストが400で拒否されます。メッセージには「thinking or redacted_thinking blocks in the latest assistant message cannot be modified」という文が含まれます。トラブルシューティングのページでは、原因の筆頭が、型でブロックを絞ってredacted_thinkingを落としているケースです。エラーの説明には、thinkingフィールドが空のブロックも含めて、受け取ったままの形で戻すことと書かれています。

文言が似た別の400エラーもあります。署名の検証に失敗するエラーは、システムプロンプトやツール定義など先行する内容が変わったときに出ます。切り分けと直し方はthinking blocks cannot be modifiedエラーの原因と直し方で扱っています。

会話の途中でモデルを切り替えるときは、別の確認が要ります。Claude Fable 5.1以降は、thinkingとredacted_thinkingの両方のブロックについて、署名からそれを作ったモデルを調べます。読めないブロックはエラーなしで落とされ、課金もされません。仕組みはPreserved thinkingとはに詳しく書いています。

まとめ

redacted_thinkingは、読めないからこそ素通しにするブロックです。判断の軸は3つあります。

  • 空のthinkingフィールドか、redacted_thinkingかは、typeを見れば区別できる
  • ツール併用の会話では、response.contentを加工せず積み戻す
  • 型で絞る処理を書いたら、redacted_thinkingが含まれているかを最初に確かめる
この記事を共有:XはてブLinkedIn