プレフィックスチェックに失敗せずにツールや指示を変更する
Claudeが以前の思考を保持できるように、指示、ツール、リマインダー、要約を送信したり、保存した会話を再開したり、他の人のリクエストを中継したりします。
ツール、指示、その他のコンテキストを更新するには、送信済みのものはすべてそのままにして、更新を末尾に追加し、そこに残します。「preserved thinking」(保持された思考)を持つモデルでは、送信済みの内容を変更すると、その後の思考が無効になり、リクエストが失敗する可能性があります。
保持された思考を備えたモデルは、Claude Fable 5.2、Claude Mythos 5.2、Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5.5、Claude Sonnet 5.5、Claude Haiku 5.5です。
アシスタントのターンを正確にそのまま送り返す
各レスポンスのcontent配列全体を、テキストが空の思考ブロックも含めて、順序どおりに送り返してください。テキストが空のブロックも完全なブロックです。そのsignatureに推論が暗号化されて保持されているためです。fallbackブロックを含むターンには、独自のルールがあります。
シリアライザー、フィルター、ストリームパーサーによって、これが壊れることがあります。
指示を変更する
systemはすべてのリクエストで同じに保ちます。独自の指示は末尾のrole: "system"メッセージに入れ、何かが変わったときにだけ送信します。Claudeはそれをオペレーターであるあなたからの指示として扱います。会話の残りの間はそのまま残してください。後で削除したり言い換えたりすると、その後の思考が無効になるためです。ユーザーの言葉には独自のルールがあります。
毎ターン付ける必要があるリマインダーは別です。自動的にクリアされるものを送信してください。
システムメッセージは、最新のユーザーメッセージの後に置きます。ツール結果を含むユーザーメッセージであっても同様です。テキストブロックまたはツールブロックを含むシステムメッセージは、Claudeのターンの直後、またはユーザーメッセージの直前にあると400エラーになります。そのため、Claudeのターンが最後にある場合は、次のユーザーメッセージが配置されるまで待ちます。
システムメッセージはClaudeが指示に従うことを保証するものではないため、読み取り専用モードなどの制限は、ツールを実行するコード内で適用してください。一部のモデルはシステムメッセージを受け付けません。
他の人が編集できるテキスト
他の人が編集できるAGENTS.mdやCLAUDE.mdのようなファイル、または保存されたメモリを、Claudeが信頼することをユーザーが期待するかどうかを考えてください。期待しない場合は、最初のバージョンも含め、そのテキストをtool_resultブロック内でのみ送信します。理由については、間接的なプロンプトインジェクションを参照してください。
そのようなテキストをシステムメッセージやユーザーメッセージのテキストに入れないでください。また、新しい会話ではsystemにも入れないでください。
そのようなファイルを読み込んだとき、またはファイルが変更されたときは、テキストを含めずに、ツールで読み取るようClaudeに指示します。あるいは、次のユーザーメッセージの後に、ツール呼び出しとその結果を自分で追加します。つまり、tool_useブロックを持つassistantメッセージと、その後にテキストを保持するtool_resultブロックを持つuserメッセージです。手順については、ツール呼び出しを自分で書くを参照してください。
ユーザーがClaudeに従ってほしいと期待するファイルは、ユーザーメッセージに入れることができます。あなただけが管理する指示ファイルは、システムメッセージに入れることができます。一度読み込み、更新された各バージョンを追加します。
日付、ファイル、その他のコンテキストを更新する
systemと最初のメッセージは一度だけ構築し、すべてのリクエストで変更せずに送信します。
更新された値は、これから送信するユーザーメッセージの中の独立したテキストブロックに、ツール結果の後に入れます。
{
"role": "user",
"content": [
{ "type": "text", "text": "Environment update: the current branch is now release-2." },
{ "type": "text", "text": "Run the tests again." }
]
}値が変わったときにだけ記述し、そのまま残してください。
コードがメッセージに追加するコンテキストは、そのメッセージと一緒に保存します。そうしないと、次のリクエストで同じ思考の前に異なる内容が送信されることになります。
ツールを追加、削除、またはオフにする
toolsはすべてのリクエストで同じに保ちます。そこでツールを追加、変更、または削除すると(遅延ツールを除く)、会話内にすでにある思考が無効になります。toolsはそのすべてより前に来るためです。説明文の1文を言い換えるだけでも十分に無効になります。
ツールを追加または削除するには、tool_additionまたはtool_removalブロックを持つシステムメッセージと、ケースに応じたベータヘッダーを追加します。MCPサーバーやプラグインが接続されたときも同様にします。
1つのリクエストでツールをオフにするには、tool_choice: {"type": "none"}を設定し、toolsは元のままにします。
古いターンをトリミングまたは要約する
最近のターンをその思考とともに残すには、残した思考の条件のもとで、オンデマンドのコンパクションを使ってAPIに要約を書かせます。返されたコンパクションブロックでmessagesを始め、それが要約するメッセージを削除します。
独自のコードで要約を書く場合、または要約なしで古いターンを削る場合は、残したターンの思考を削除するか、"drop_block"を送信してください。新たに削るたびに残したターンの思考が再び無効になるため、削る頻度は少なくし、大きな単位で行ってください。代わりに古いツール結果をクリアするには、コンテキスト編集を使用します。
会話を保存、再開、またはフォークする
送信したものと受信したものを保存し、まさにそれを送信します。再開された会話は通常の次のリクエストです。system、tools、および以前のmessagesは、それまでと同じ値である必要があります。フォークの場合は、分岐の指示を最初の新しいユーザーメッセージ、またはその後のシステムメッセージに入れます。思考は異なる履歴を持つ会話に移すことはできません。その会話は代わりに要約から開始してください。
システムプロンプトやツールを変更するリリースは、すでに実行中の会話における変更になります。コードを追記のみにする修正も、変更になり得ます。実行中の各会話には、最後に成功したリクエストのsystemとtoolsを送信し続けてください。その最新の思考はそのバージョンの後に生成されたためです。以前のバージョンに戻すと、その思考が無効になります。
新しい会話では更新されたsystemとtoolsを使用します。リリースで安全のためにツールを削除したり指示を変更したりする場合は、実行中の会話にも適用してください。tool_removalブロックまたはシステムメッセージを追加します。
シークレット、個人データ、または注入されたテキストを削除する
安全性とプライバシーは、思考を有効に保つことよりも優先されます。メッセージに削除しなければならないシークレットや個人データが含まれている場合は、そのテキストを削除してください。それを繰り返しているすべてのメッセージと要約からも削除します。
注入された指示を含むツール結果については、その内容を「Removed.」のような短い注記に置き換えます。tool_resultブロック自体は残してください。そのtool_useにはそれが必要だからです。コンパクションブロックがそのテキストを保持している場合は、ブロックを削除し、独自の要約から開始します。
次に、テキストが最初に現れた場所以降のすべてのthinkingブロックとredacted_thinkingブロックを削除します。systemまたはtoolsに含まれていた場合は、そのすべてが対象です。各ブロックがテキストを繰り返している可能性があり、その中身を読んだり編集したりすることはできません。ここでは"drop_block"を送信するだけでは不十分です。保存された履歴にそれらのブロックが残るためです。会話はその推論なしで続行されます。
注入された結果の後、後続のターンがすでにそれに基づいて行動している可能性があります。それ以降に行われたツール呼び出しを確認し、必要なものを元に戻してください。
技術的な詳細
コードがアシスタントのターンを変更してしまう原因
- シリアライザーが未知のブロックタイプを削除したり、ブロックを並べ替えたり、結合したり、分割したりします。これにより、後続のすべてのブロックの前にあった内容が変わります。
- コードが空に見える思考ブロックをスキップします。すべてスキップすると、Claudeはその推論を失います。一部だけスキップすると、その欠落によって後続の思考が無効になります。
- 独自のストリームパーサーが、テキストを受け取らなかった思考ブロックを削除します。SDKのストリームヘルパーはそれを保持します。
思考を省く
省いた推論はClaudeから失われます。省くのは最も古いブロック、最も新しいブロック、またはすべてのブロックにし、途中のものは省かないでください。各ブロックは自身がどのブロックの後に生成されたかを記録しているため、欠落があるとその後のブロックが無効になります。ターン内で間に他のブロックを挟まない思考ブロック同士はまとめてプレフィックスチェックされるため、すべて省くか、まったく省かないかのどちらかにしてください。一度省いたブロックは、省いたままにします。
ツール呼び出しが開いている間は、そのターンの思考を送り返して、Claudeが推論を持ったままそのラウンドを終えられるようにします。
ツールループ内での指示
メッセージは次の順序で並べます。
[
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_01",
"name": "run_tests",
"input": { "path": "tests/" }
}
]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "2 failed, 48 passed" }
]
},
{
"role": "system",
"content": "Plan mode is off. You can edit files."
}
]ツール呼び出しを自分で書く
最初のリクエストでファイルを読み取るツールを宣言するか、後でシステムメッセージで追加し、そのツールへのClaudeの呼び出しにコードが応答するようにします。次のユーザーメッセージの後に、そのツールのtool_useブロックを持つassistantメッセージを追加します。その直後に、一致するtool_use_idを持ちファイルのテキストを保持するtool_resultブロックを含むuserメッセージを追加します。Claudeはその後に応答します。
[
{ "role": "user", "content": "Run the tests again." },
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_app_agents_md_1",
"name": "read_file",
"input": { "path": "AGENTS.md" }
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_app_agents_md_1",
"content": "The file's text"
}
]
}
]両方をそのまま残し、新しいバージョンごとに、新しいidを持つ新しいペアを追加します。
ツールループ内でのユーザーの言葉と更新された値
Claudeが作業している間にユーザーが入力した内容を渡す場合は、tool_resultブロックを運ぶユーザーメッセージを送信する前に追加します。最後のtool_resultの後のテキストブロックにしてください。
あなた自身から来る値は、代わりにシステムメッセージに入れることができます。ツール結果の後では、Claude Sonnet 5.5とClaude Haiku 5.5は、システムメッセージ内のユーザーの言葉をプロンプトインジェクションとして無視する可能性があります。Claude Sonnet 5.5は、あなた自身の指示やリマインダーがすべてのツール結果の後に来る場合、それらについても同様に無視する可能性があります。
ターンがまだ結果のないサーバーツールも呼び出した場合、またはプログラマティックツール呼び出しを使用した場合は、ツール結果を含むユーザーメッセージはtool_resultブロックのみを保持する必要があります。その場合は、テキストを次のユーザーメッセージに追加します。
システムメッセージを受け付けないモデル
Claude APIでは、保持された思考を持つすべてのモデルがシステムメッセージを受け付けます。受け付けないモデルについては、モデルがシステムメッセージを受け付けない場合を参照してください。
1ターン分のリマインダーを送信する
リマインダーはターンスコープのシステムメッセージとして送信します。clear_at: "next_user_message"を設定し、ベータヘッダーmid-conversation-system-clear-at-2026-08-21を送信します。これはtool_resultブロックを運ぶユーザーメッセージの後に置きます。
{
"role": "system",
"clear_at": "next_user_message",
"content": "Run the linter before you report that a task is done."
}次のユーザーメッセージで(tool_resultブロックのみを含むものであっても)、APIがそれをクリアするため、Claudeはそれを読まなくなります。Claude Sonnet 5.5では、すべてのツール結果の後に送信しないでください。削除しなければならないものを含んでいる場合を除き、クリアされたかどうかにかかわらず、すべてのリマインダーをmessagesに残してください。削除したり言い換えたりすると、その後の思考が無効になります。
ヘッダーなしの場合は、通常のシステムメッセージを送信してそのまま残します。クリアされることはないため、リマインダーは蓄積していきます。システムメッセージを受け付けないモデルでは、ユーザーメッセージ内のテキストブロックを使用します。
ツールの変更に必要なブロックとベータヘッダー
各ヘッダーを受け付けるプラットフォームについては、会話途中のシステムメッセージとツール変更を参照してください。
- 最初の時点ですべてのツールがわかっている場合: 最初のリクエストですべてを宣言し、後で提供するものには
defer_loading: trueを付けます。その後、システムメッセージのtool_additionまたはtool_removalブロックでツール名を指定します。ベータヘッダー:inline-tools-2026-09-15またはmid-conversation-tool-changes-2026-07-01。 - 後からツールを知る場合、またはスキーマが変わるツールがある場合: システムメッセージの
tool_additionブロックでツールを定義します。ベータヘッダー:inline-tools-2026-09-15。 inline-tools-2026-09-15ヘッダーのないプラットフォームで、後からツールを知る場合:defer_loading: trueを付けてツールをtoolsの末尾に追加し(これは変更にはなりません)、その後名前で提供します。ベータヘッダー:mid-conversation-tool-changes-2026-07-01。- Claude APIで、MCPコネクター経由でMCPサーバーを後から接続する場合: その
mcp_toolsetをtool_additionブロックで定義します。ベータヘッダー:inline-tools-2026-09-15およびmcp-client-2026-09-15。
MCPサーバーのツールリストが変わる可能性がある場合は、MCPサーバーのツールリストを固定するを参照してください。
このシステムメッセージは、宣言済みのツールを名前で提供し、別のツールを定義しています。これにはinline-tools-2026-09-15が必要です。
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": { "type": "tool_reference", "name": "search_tickets" }
},
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"name": "get_weather",
"description": "Get the current weather in a city.",
"input_schema": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}
}
]
}defer_loadingを持つツールと、それを示す400エラー
defer_loading: trueを持つツールは、メッセージまたはツール検索結果がそれを参照するまで、Claudeのコンテキストと「prefix check」(プレフィックスチェック)の対象外になります。それまでは、追加、更新、削除しても変更にはなりません。参照された後は変更になります。defer_loadingのオン・オフを切り替えることも、toolsの変更とみなされます。
遅延されないツールを少なくとも1つ宣言してください。そうしないと、リクエストがdefer_loadingを示す400エラーになる可能性があります。
古い結果や画像を短縮またはクリアする
ツール結果や画像は、最初に送信する前に短縮またはダウンスケールしてください。コードがすでに送信したものをクリア、短縮、または再エンコードすると、その後の思考が無効になります。後で古いツール結果(その中の画像を含む)をクリアするには、コンテキスト編集を使用します。clear_tool_uses_20250919タイプの編集を含むcontext_managementと、ベータヘッダーcontext-management-2025-06-27を送信します。完全なリクエストとそのオプションについては、コンテキスト編集を参照してください。
URLで送信するファイル
URLによるファイルの場合、APIは取得したバイトを比較します。そのため、署名付きURLの有効期限が切れても、同じファイルの新しいURLであれば問題ありません。URLの背後にあるコンテンツが変わる可能性がある場合は、最初のリクエストからfile_idまたはbase64を送信してください。
独自のコードで古いターンを要約または削る場合
独自の要約や削除の後、残したターンの思考はプレフィックスチェックに失敗します。その思考が続いていたメッセージがなくなっているためです。その思考を削除するか、"drop_block"を送信してください。Claudeはそれがなくてもターンを読み取ります。
ライブラリ、プロキシ、ゲートウェイ
他の人のリクエストがあなたのコードを通過する場合、あなたの書き換えによって彼らの履歴が変わり、彼らはその変更を確認したり修正したりできない可能性があります。400エラーを隠さないでください。呼び出し元のために復旧する場合は、その旨を伝えてください。彼らの履歴には依然として変更が残っているためです。
anthropic-betaの値とthinking.block_bindingは、送信されたとおりに渡してください。ゲートウェイが既知のフィールドのみを許可している場合は、thinking.block_bindingとヘッダー値thinking-binding-controls-2026-08-01を追加してください。そうしないと、ユーザーは"drop_block"を選択できません。- ベータヘッダーを削除して設定だけを転送しないでください。そのリクエストは400エラーになります。
- テキストが空の思考ブロックと
input_transformations配列を呼び出し元に返してください。 role: "system"メッセージはその位置のままにしてください。systemに移動すると、会話内にすでにある思考が無効になります。prefix_mismatch_behaviorを"error"に設定してテストしてください。これにより、保持された思考を持つすべてのモデルでエラーが返されます。
次のステップ
保持された思考とは何か、思考ブロックが何に結び付けられているか、そしてモデルやアカウントの切り替えについて。
失敗している会話を復旧し、思考の除外によるコストを確認します。
システムメッセージとツールの変更をどこに置くか、そしてどのモデルとプラットフォームがそれらを受け付けるか。
このページは役に立ちましたか?