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の値 | 本文 | 中身の所在 | 起きる条件 |
|---|---|---|---|---|
| 通常のthinking | typeの値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が含まれているかを最初に確かめる