会話途中のシステムメッセージとツール変更
会話の途中でシステム指示やツールの利用可否を変更しても、それ以前のキャッシュ済みプレフィックスを無効化しないようにします。
システム指示は通常、会話内のすべてのメッセージより前にあるトップレベルの system フィールドに置かれます。この位置は prompt caching(プロンプトキャッシング)にとって非常に都合が良いものです。システムプロンプトは安定したプレフィックスの一部となるため、後続のターンはキャッシュにヒットします。一方で、セッションの途中になって初めて必要だと気づいた指示にとっては不向きな位置です。トップレベルの system フィールドを編集するとプロンプトの冒頭そのものが変わり、それ以降のすべてについてキャッシュが無効化されるためです。
会話途中のシステムメッセージはこのギャップを埋めます。トップレベルの system フィールドを編集する代わりに、新しい指示が関連するようになった会話内の位置に {"role": "system"} メッセージを追加します。キャッシュ済みプレフィックスは変わらないため、次のリクエストでも引き続きキャッシュから読み取られ、新しい指示は通常のユーザーテキストとしてではなく、システム指示として適用されます。
会話途中のツール変更
tools配列は、ハッシュ化されるリクエストプレフィックスの中で、トップレベルのsystemフィールドよりもさらに前に位置します。そのため、これを編集すると会話全体のプロンプトキャッシュが無効になります。会話途中のツール変更は、会話途中のシステムメッセージのツール版です。会話の全期間にわたってツールリストを固定する代わりに、ターンの合間にモデルへ提供するツールを変更できます。まずtoolsでツールセット全体を宣言し、次にtool_additionブロックとtool_removalブロックを使って、会話の特定の時点以降にツールをモデルへ提供したり、提供を取り下げたりします。tools配列自体は変わらないため、キャッシュ済みのプレフィックスはそのまま保たれます。会話途中のツール変更はベータ版で、Claude APIではinline-tools-2026-09-15ベータヘッダーを使用します。
tool_additionとtool_removalは、role: "system"メッセージのcontent配列に含めるコンテンツブロックで、同じメッセージ内でtextブロックと組み合わせることができます。このメッセージは、他の会話途中のシステムメッセージと同じ配置ルールに従います。ただし、一時停止されたターンの後には追加の制限が1つあります(制限事項を参照)。変更は、会話内のその時点以降に適用されます。各ブロックのtoolフィールドは、ツールを定義するのではなく参照します。{"type": "tool_reference", "name": "..."}は、リクエストのtools配列で宣言されたツールを名前で指定します。MCPコネクタのツールは、mcp_tool_reference(server_nameとname)で個別に参照することも、mcp_toolset_reference(server_name)でツールセット全体として参照することもできます。toolsで宣言されていない名前を参照すると、400エラーが返されます(Claude APIでは、error.details.error_codeがtool_reference_unresolvedに設定されます)。tool_additionブロックには、参照の代わりにツールの完全な定義を含めることもできます。ただし、mid-conversation-tool-changes-2026-07-01ヘッダーはこれに対応していません。
tools で宣言されたすべてのツールは、defer_loading: true を付けて宣言されていない限り、会話の開始時点からモデルに提供されます。defer_loading: true を付けると、tool_addition ブロックがそのツールを表に出すまで保留されたままになります。tool_addition は、以前の tool_removal で取り下げられたツールを再度提供することもできます。
次のリクエストは、tools で get_weather を宣言し、最初のユーザーターンの後に tool_removal ブロックでそれを取り下げます。このリクエストは inline-tools-2026-09-15 ベータヘッダーを送信します。
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
betas=["inline-tools-2026-09-15"],
# ツールセット全体を最初に宣言し、以後変更しないため、
# キャッシュされたプレフィックスはそのまま保持されます。
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
},
},
],
messages=[
{
"role": "user",
"content": "Say OK.",
},
# ここから先は get_weather を取り下げます。このブロックは
# `tools` を編集せずにツールを名前で参照するため、以前のターンは
# バイト単位で同一のまま保たれ、キャッシュも引き続きヒットします。
{
"role": "system",
"content": [
{
"type": "tool_removal",
"tool": {"type": "tool_reference", "name": "get_weather"},
},
],
},
],
)
for block in response.content:
if block.type == "text":
print(block.text)メッセージ内でツールを定義する(ベータ)
inline-tools-2026-09-15 ベータヘッダーを使用すると、tool_addition ブロックでツールを参照で指定する代わりに、完全な定義を含めて値として定義できます。これにより、会話の開始時点では不明なツールや、後でスキーマが変わるツールを、role: "system" メッセージを追加するだけで導入できます。tools 配列とそれ以前のすべてのメッセージは送信時のまま変わらないため、プロンプトキャッシングは引き続きヒットし、追加したメッセージだけが新しい入力として処理されます。唯一の例外は、遅延されていないツールを1つも含まない tools 配列の場合で、これについては後述のルールで説明します。このヘッダーは参照によるツールの追加と削除にも対応しているため、mid-conversation-tool-changes-2026-07-01 を併せて送信する必要はありません。
定義は、tool_definition タイプの tool オブジェクトでラップします。definition は tools のエントリと同じ形式で、カスタムツールや、Anthropic 定義のクライアントツールまたはサーバーツールなどを指定できます。cache_control や defer_loading を含む通常の設定も使用できます。ベータ期間中は、一部のツールタイプ(コンピュータ使用ツールなど)をまだメッセージ内で定義できず、その旨を示す 400 エラーが返されます。これらのツールは tools で宣言し、参照によって追加してください。たとえば、会話の途中でカスタムツールを定義するには次のようにします。
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"name": "db_query",
"description": "Run a read-only SQL query against the analytics database.",
"input_schema": {
"type": "object",
"properties": { "sql": { "type": "string" } },
"required": ["sql"]
}
}
}
}
]
}その位置以降、モデルは tools で宣言されたツールと同じ方法でそのツールを呼び出せます。同一の定義を再度送信しても何も変わらないため、クライアントは再試行時などに安全に再送信できます。
次のリクエストは、get_weather を tools に保持し、最初のユーザーターンの後に db_query を定義します。
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
betas=["inline-tools-2026-09-15"],
# `tools` には遅延されないツールを少なくとも1つ残してください。そうすれば、後で定義したツールが
# レンダリングされたプロンプトの先頭を変えることはありません。
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
},
},
],
messages=[
{"role": "user", "content": "How many orders shipped yesterday?"},
# ここから先は db_query を値で定義します。`tools` と
# それ以前のメッセージは送信時のまま変わらないため、キャッシュは引き続きヒットします。
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"name": "db_query",
"description": "Run a read-only SQL query against the analytics database.",
"input_schema": {
"type": "object",
"properties": {"sql": {"type": "string"}},
"required": ["sql"],
},
},
},
},
],
},
],
)
for block in response.content:
if block.type == "tool_use":
print(block.name, block.input)レスポンスの content には、新しいツールの tool_use ブロックが含まれます。例:
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "db_query",
"input": {
"sql": "SELECT COUNT(*) FROM orders WHERE shipped_at::date = CURRENT_DATE - 1"
}
}ツールのスキーマを変更する場合や、サーバーツールを新しいバージョンに移行する場合は、同じ名前で異なる定義を送信します。その位置以降は、新しい定義が以前の定義に置き換わります。別のタイプのツールと同じ名前を使用する定義を送信すると、error.details.error_code が tool_name_conflict に設定された 400 エラーが返されます。同じツールの新しいバージョンは、別のタイプとはみなされません。tool_removal では引き続き参照を指定します。削除したツールは、後で再び定義したり提供したりできます。
定義がレンダリングされる位置に関連して、次のルールがあります。
- 事前にわかっているツールは最初に宣言する。 最初のリクエストの時点でわかっているツールは
toolsに含めてください。まだモデルに見せたくない場合は、defer_loading: trueを指定し、後でtool_additionで参照します。値による定義は、最初のリクエストの時点で不明なツールや、後で変更されるツールだけに使用してください。 toolsには遅延されていないツールを少なくとも1つ残す。tools配列に遅延されていないツールが1つもない会話も受け付けられます。ただし、値によって最初にツールを定義すると、レンダリングされるプロンプトの先頭が変わるため、そのリクエストではキャッシュが完全にミスします。ツール検索ツールは、遅延されていないツールとしてカウントされます。- 日付付きのツールタイプには、それぞれのベータヘッダーが引き続き必要。 値によって定義するサーバーツールに独自のベータヘッダーが必要な場合は、会話内の以降のすべてのリクエストでそのヘッダーを送信してください。
cache_controlはブロックと定義のどちらか一方にのみ指定する。 また、cache_controlはリクエストのブレークポイント数の上限にカウントされます。遅延された定義にはcache_controlを指定できません。
次のいずれかの上限を超えると、error.details.error_code が available_tools_limit_exceeded に設定された 400 エラーが返されます。
- いずれかのメッセージの後で、利用可能な遅延ツールが 10,000 個を超えている。
- いずれかのメッセージの後で、最初のユーザーメッセージ以降に定義されたツールのうち利用可能なものが 10,000 個を超えている。
- 最初のユーザーメッセージ以降に送信され、いずれかのメッセージの後でまだ利用可能なツール定義の合計サイズが 4 MB(4,194,304 バイト)を超えている。
- レンダリングされたツールテキストのサイズが 4 MB(4,194,304 バイト)を超えている。
会話の途中で MCP サーバーを追加する(ベータ)
会話の途中で MCP コネクタのサーバーを追加するには、inline-tools-2026-09-15 に加えて mcp-client-2026-09-15 ベータヘッダーを送信します。これにより、tool_addition ブロックの definition に mcp_toolset を指定できるようになり、tools を編集せずにサーバーのツールを利用可能にできます。通常どおり mcp_servers にサーバーの接続情報を記載し、サーバーが利用可能になった位置にツールセットを追加します。
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": { "type": "mcp_toolset", "mcp_server_name": "calendar" }
}
}
]
}mcp_toolset オブジェクトは、tools に指定するものと同じで、default_config や configs も使用できます。tool_addition ブロックにサーバーの URL やトークンを含めることはありません。これらは mcp_servers に記載したままにします。
次のリクエストは、get_weather を tools に保持し、カレンダーサーバーを mcp_servers に記載し、最初のユーザーターンの後にサーバーのツールセットを追加します。
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
betas=["inline-tools-2026-09-15", "mcp-client-2026-09-15"],
mcp_servers=[
{
"type": "url",
"url": "https://mcp.example.com/calendar",
"name": "calendar",
"authorization_token": "YOUR_TOKEN",
},
],
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
},
},
],
messages=[
{"role": "user", "content": "What's on my calendar tomorrow?"},
# この時点以降、カレンダーサーバーのツールを利用可能にします。
# このブロックはサーバー名を指定するだけで、URLやトークンを保持することはありません。
{
"role": "system",
"content": [
{
"type": "tool_addition",
"tool": {
"type": "tool_definition",
"definition": {
"type": "mcp_toolset",
"mcp_server_name": "calendar",
},
},
},
],
},
],
)
# レスポンスはカレンダーサーバーの mcp_tool_listing ブロックから始まるため、
# content[0] を読むのではなく、各ブロックの type を確認してください。
for block in response.content:
match block.type:
case "mcp_tool_listing":
print(block.mcp_server_name, [tool.name for tool in block.tools])
case "text":
print(block.text)mcp-client-2026-09-15 を使用すると、API がサーバーのツールリストを取得したレスポンスは、取得したサーバーごとに 1 つずつ、mcp_tool_listing ブロックで始まります。コードで content[0] を読み取る場合は、これらのブロックをスキップしてください。アシスタントメッセージはこのブロックを含めて変更せずに送り返し、このブロックを含むすべてのリクエストで mcp-client-2026-09-15 を送信し続けてください。以降のリクエストでは、サーバーに再度問い合わせる代わりに、記録されたリストが使用されます。ツールセットを自分で固定するには、MCP サーバーのツールリストをピン留めするで説明されているように、そのリストを mcp_toolset の tools フィールドにコピーします。
mcp-client-2026-09-15 には mcp-client-2025-11-20 のすべての機能が含まれているため、両方を送信する必要はありません。これらの機能は Claude API で利用できます。MCP コネクタを使用するリクエストには、引き続き MCP コネクタのデータ保持の条件が適用されます。
会話途中のシステムメッセージを使用するタイミング
プロンプトキャッシングは、リクエストプレフィックスを tools、次に system、次に messages の順にハッシュ化します。キャッシュヒットには、キャッシュブレークポイントまでのプレフィックスが最近のリクエストとバイト単位で完全に一致する必要があります。
この順序により、トップレベルの system フィールドはハッシュ化されるプレフィックスのほぼ先頭に位置します。一文を追加するだけであっても、これを変更すると異なるハッシュが生成され、リクエストはシステムプロンプトおよびそれ以降のすべてのキャッシュ済みメッセージについてキャッシュミスとなります。
会話途中のシステムメッセージを使えば、代わりにメッセージ履歴の末尾に指示を追加できます。新しい指示より前のすべては変更されないため、既存のキャッシュエントリは引き続き一致し、新しいメッセージだけが新規入力として処理されます。
これが重要になる状況をいくつか挙げます。
- セッション途中のポリシーやペルソナの変更。 長いエージェントセッションで、数十のキャッシュ済みターンの後に新しい制約(「今後はすべての SQL をパラメータ化クエリとして書くこと」)が必要になる場合。トップレベルの
systemフィールドに追加すると、履歴全体が再処理されます。 - 権威を持たせる必要があるターンごとのコンテキスト。 鮮度に関する注記、セッションの期限、ツールの利用可否の変更などをシステムレベルの重みで注入したいが、キャッシュ済みプレフィックスに置くには変更頻度が高すぎる場合。
- 積み重なってほしくないターンごとのリマインダー。 ハーネスがツール結果のバッチごとにモデルを促し(「独立した読み取りはまとめてリクエストすること」「ユーザーはしばらくあなたからの応答を受け取っていません」)、モデルには最新のコピーだけを見せたい場合。ターンスコープのシステムメッセージは 1 ターンだけレンダリングされ、その後は履歴から何も削除することなくコストがゼロになります。
- アプリケーションが観測した状態変化。 Claude がオペレーターレベルの事実として扱うべき事柄にアプリケーションが気づいた場合。たとえば、ディスク上のファイルが変更された、ユーザーが自動承認設定を切り替えた、利用可能なツールが変わった、残りのトークン予算がしきい値を下回った、などです。
- エージェントループを中断すべきでないユーザー入力。 Claude が前のリクエストのためにまだツールを実行している間に、ユーザーがフォローアップを入力した場合。次のツール結果の後にそれをシステムメッセージとして中継すると、Claude は新しい入力を切り替えるべき新規リクエストとして扱うのではなく、すでに行っている作業に組み込むことができます。Claude Sonnet 5.5 と Claude Haiku 5.5 では、代わりに同じ
userメッセージ内の最後のtool_resultの後に、ユーザーの言葉をtextブロックとして追加してください。ツール結果の後への配置を参照してください。 - 継続的な許可を与えるモード切り替え。 セッションレベルのモードでは、会話途中のシステムメッセージを使って、マルチエージェントワークフローの自動起動のような高コストな機能に対する継続的な同意を与えることができます。数ターンごとに短いリフレッシャーを送り、モードがオフになったときには終了通知を送ります。具体例については、オーケストレーションモードを構築するを参照してください。
これらすべてのケースで、指示を通常の user メッセージに入れることもでき、Claude はユーザーターンで届いた指示にも従います。違いは優先度です。user メッセージはエンドユーザーからのものとして扱われ、system メッセージはアプリケーションオペレーターであるあなたからのものとして扱われます。両者が矛盾する場合はシステム指示が優先されるため、エンドユーザーが別のことを求めた場合でも維持されるべきオペレーターレベルの事実や制約には system ロールを使用してください。会話途中のシステムメッセージは、トップレベルの system フィールドを編集することによるキャッシュミスのコストを払うことなく、そのオペレーターレベルの優先度を保ちます。
仕組み
messages 配列に "role": "system" を持つメッセージを追加します。content には、user や assistant ターンと同様に、プレーンな文字列またはコンテンツブロックを使用します。指示は会話内のその位置以降に適用されます。指示が矛盾する場合、後のシステムメッセージが前のものより優先され、会話途中のシステムメッセージはそれに続くターンについてトップレベルの system フィールドより優先されます。
会話全体に適用すべき指示については、引き続きトップレベルの system フィールドを設定できます。会話途中のシステムメッセージは、後になって初めて関連するようになる指示、またはキャッシュ済みプレフィックスを無効化せずに追加したい指示のために取っておいてください。
role: "system" メッセージには、会話の途中で effort レベルを変更するための output_config.effort を含めることもできます。これは Claude API と Google Cloud 上の Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5.5、Claude Opus 5、Claude Sonnet 5.5、Claude Haiku 5.5でベータ版として提供されており、mid-conversation-output-config-2026-07-01 ベータヘッダーが必要です。Amazon Bedrock では、Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5.5 で、同じベータ値を使用してベータ版として提供されています。Claude Opus 5 は Amazon Bedrock ではこれをサポートしていません。メッセージごとのエフォート を参照してください。
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
# 自動 prompt caching(プロンプトキャッシング):各リクエストはそれまでの会話をキャッシュし、
# 次のリクエストは変更のないプレフィックスをキャッシュから読み取ります。
cache_control={"type": "ephemeral"},
system="You are a code review assistant. Be concise.",
messages=[
{
"role": "user",
"content": "Review process() in utils.py for performance issues.",
},
{
"role": "assistant",
"content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.",
},
{
"role": "user",
"content": "Now review the calling code that invokes process().",
},
# レビュアーはセッションの途中で、すべての提案が
# チームの厳格な型付けポリシーにも準拠する必要があると気づきます。ここに
# 指示を追加すると、以前のターンがバイト単位で同一に保たれるため、
# 前のリクエストでキャッシュされたプレフィックスは引き続きキャッシュから読み取られます。
{
"role": "system",
"content": "From now on, every suggestion must include explicit type annotations.",
},
],
)
for block in response.content:
if block.type == "text":
print(block.text)この例では、トップレベルの cache_control フィールドで自動キャッシングを有効にしています。プロンプトキャッシングはオプトインです。リクエストに cache_control フィールド(自動または明示的なブレークポイント)がない場合、何もキャッシュされず、すべてのリクエストが会話全体に対して通常の入力トークン料金を支払います。キャッシングが有効な場合、システムメッセージを追加してもすでにキャッシュ済みのターンは変更されないため、新しい指示を含むリクエストはそれらを再処理するのではなく、引き続きキャッシュから読み取ります。キャッシングには、会話がキャッシュ可能な最小プロンプト長を満たしている必要もあります。この例のように短いものはそれを下回るため、会話が長くなるまで cache_creation_input_tokens と cache_read_input_tokens は 0 のままです。
コンテンツ(text、tool_addition、または tool_removal ブロック)を含む会話途中のシステムメッセージは、user ターン(またはサーバーツール結果で終わる assistant ターン)の直後に置く必要があり、messages の最後のエントリであるか、直後に assistant ターンが続く必要があります。tool_result ブロックを含む user メッセージもこれに該当します。エージェントループでは、ツール結果の直後、Claude の次のターンの前にシステムメッセージを配置できます。コンテンツを含むメッセージをそれ以外の位置に置くと、assistant の tool_use ブロックとそれに応答する tool_result の間も含め、400 エラーが返されます。output_config.effort のみを設定する空の content を持つメッセージは、messages 内のどこにでも配置できます。連続する system メッセージはまとめて判定されるため、コンテンツを含むメッセージの隣にあるエフォートのみのメッセージは、コンテンツのルールに従います。
ツール結果の後への配置
エージェントループでは、システムメッセージはツール結果を届ける user メッセージの後に置きます。ほとんどのモデルでは、ここは、Claude が作業している間にユーザーが入力した内容をアプリケーションが中継できる場所でもあり、ターンを再開することなく新しいコンテキストが取り込まれます(Claude Sonnet 5.5 と Claude Haiku 5.5 については、このセクションの最後を参照してください)。
[
{ "role": "user", "content": "Run the test suite and fix any failures." },
{
"role": "assistant",
"content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" }
]
},
{
"role": "system",
"content": "The user sent the following message while you were working: also update the changelog before you finish."
}
]システムコンテンツは、ユーザーを上書きする命令としてではなく、コンテキストとして表現してください。事実を述べ(「ユーザーから新しい入力が届きました: X」「残りのトークン予算は現在 Y です」)、Claude にそれに基づいて行動させます。Claude はユーザーに不利に働くように見える指示に抵抗するよう訓練されており、その保護はシステムロールにも引き続き適用されるため、「ユーザーが言ったことは無視してください」のような表現は、何が変わったかを述べるよりも効果が低くなります。
このパターンは、会話自身のエンドユーザーからの入力を中継するためのものです。ツール出力、取得したドキュメント、その他のサードパーティコンテンツを渡すために使用しないでください。そうしたコンテンツは tool_result ブロックに保持してください(制限事項を参照)。
Claude Sonnet 5.5 と Claude Haiku 5.5 では、代わりにユーザーの言葉をユーザーターンで届けてください。これらのモデルはツール結果を介したプロンプトインジェクションに抵抗するよう訓練されているため、ツール結果の直後に置かれたシステムメッセージを信頼できないテキストとして扱い、無視する可能性があります。ユーザーの言葉は、同じ user メッセージ内の最後の tool_result の後に text ブロックとして追加してください。リマインダーなどのハーネスからの通知は、その user メッセージの後の別の会話途中のシステムメッセージに保持し、通知とユーザーの言葉を同じブロックに入れないでください。
[
{ "role": "user", "content": "Run the test suite and fix any failures." },
{
"role": "assistant",
"content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" },
{ "type": "text", "text": "Also update the changelog before you finish." }
]
}
]この動作の詳細については、Claude Sonnet 5.5 へのプロンプトおよび Claude Haiku 5.5 へのプロンプトを参照してください。
ターンスコープのシステムメッセージ
role: "system" メッセージを現在のターンにスコープするには、その clear_at フィールドを設定します。次の 2 つの値のいずれかを取ります。
"never"(デフォルト): メッセージは、それを含むすべてのリクエストでその位置にレンダリングされます。フィールドを省略した場合も同じです。"next_user_message": メッセージはターンスコープになります。そのテキストは、messages内でその後にrole: "user"メッセージが存在しない間だけレンダリングされます。ここではtool_resultブロックのみを持つユーザーメッセージもユーザーメッセージとして数えられます。後続のユーザーメッセージが存在するようになると、メッセージはクリアされます。配列には残りますが、そのリクエストおよびそれ以降のすべてのリクエストで何もレンダリングされず、入力トークンのコストもかかりません。
ターンスコープのシステムメッセージはベータ版です。ベータヘッダー mid-conversation-system-clear-at-2026-08-21 を含めてください。これがない場合、clear_at は不明なフィールドとして拒否されます。
{
"role": "system",
"clear_at": "next_user_message",
"content": "First privately list what you need next; then request every item that doesn't depend on another's result in this one response."
}主な用途は、ツールループにおけるターンごとのリマインダーです。モデルにリマインダーを見せたいときはその都度 tool_result メッセージの後にリマインダーを追加し、以前のコピーはすべてそのままにしておきます。モデルには最後のユーザーメッセージより後にあるコピーだけが見えるため、リマインダーが蓄積することはありません。messages 内のそれ以前の部分は何も変わらないため、プロンプトキャッシュは一致し続けます。Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5、Claude Haiku 5.5では、これにより後続の思考ブロックも有効なまま維持されます。以前のリマインダーを削除すると、それらのブロックより前の会話が変わって会話チェックに失敗しますが、クリアされたメッセージは配列に残り、その会話を変更しません。
次のリクエストは、エージェントループの後の段階のものです。messages[3] は、配列の最後のメッセージだった以前のリクエストでレンダリングされました。messages[5](後続のユーザーメッセージ)が存在するようになると、messages[3] はクリアされます。クリアされたメッセージは配列に残るため、messages[4] の思考ブロックより前の会話は変わりませんが、モデルはもはやそのテキストを見ません。messages[6] と messages[7] はどちらも順番にレンダリングされます。
{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"messages": [
{ "role": "user", "content": "Fix the failing test." },
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_01",
"name": "read_file",
"input": { "path": "test_auth.py" }
}
]
},
{
"role": "user",
"content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request independent reads in one turn."
},
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_02",
"name": "read_file",
"input": { "path": "auth.py" }
},
{
"type": "tool_use",
"id": "toolu_03",
"name": "read_file",
"input": { "path": "tokens.py" }
}
]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." },
{
"type": "tool_result",
"tool_use_id": "toolu_03",
"content": "...",
"cache_control": { "type": "ephemeral" }
}
]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request independent reads in one turn."
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "The shell exited with status 137."
}
]
}ターンスコープメッセージのルール:
- クリアされたメッセージはそのまま再送信してください。 クリアされたメッセージも会話履歴の一部です。現在の状態(新しいトークン数、タイムスタンプ)から再構築したり、冗長だとして削除したり、
clear_atの値を変更したりすることは、以前のメッセージの編集にあたります。その時点からプロンプトキャッシュがミスし、Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5、Claude Haiku 5.5では、それ以降に生成されたすべての思考ブロックが会話チェックに失敗します。 - テキストのみ。
contentは1つ以上のtextブロック(または文字列)です。ターンスコープのメッセージにtool_additionブロックやtool_removalブロックを含めると400エラーが返され、output_configを含めた場合も同様です。これらには、clear_atを指定しない別のrole: "system"メッセージを使用してください。 - ブロックに
cache_controlを指定できません。 クリアされたメッセージはキャッシュキーに含まれないため、そこにブレークポイントを置いても一致することはありません。例のように、代わりに直前のユーザーターンの最後のブロックにブレークポイントを置いてください。トップレベルの自動キャッシングフィールドは、ブレークポイントを選ぶ際にターンスコープのメッセージをスキップします。メッセージがクリアされるリクエストでは、再利用可能なキャッシュ済みプレフィックスはそのメッセージの前のユーザーターンで終わるため、再処理されるのは、そのメッセージと新しいユーザーメッセージの間にある1つのアシスタントターンだけです。 - クリアされているかどうかにかかわらず、配置ルールは引き続き適用されます。 ターンスコープのメッセージは、他の会話途中のシステムメッセージと同様に、
userターン(またはサーバーツールの結果で終わるassistantターン)の後に配置し、assistantターンの前に置くか、配列の末尾にする必要があります。配列の末尾にあるメッセージは常にレンダリングされます。直後に別のuserメッセージが続くメッセージは、クリアされたメッセージではなく400エラーになります。1回のツールラウンドの結果はすべて1つのユーザーメッセージにまとめ、リマインダーはその後に配置してください。 - アシスタントターンではクリアされません。 メッセージの後にあるプレフィル済みまたは一時停止されたアシスタントターンや、サーバー側のツールループでは、ユーザーメッセージが追加されません。そのため、その継続処理でもメッセージは引き続きレンダリングされます。クライアント側のツールループを通じてリマインダーを表示し続けるには、各
tool_resultメッセージの後にリマインダーを再度追加してください。 - トークンのカウントは、レンダリングされる内容に基づきます。 クリアされたメッセージは、
usage.input_tokensにもトークンカウントにも加算されません。 - インポートされた履歴。 一度に構築するトランスクリプト(few-shotの例や移行した会話など)では、後ろにすでにアシスタントターンとユーザーメッセージがあるターンスコープのメッセージは、最初のリクエストからクリアされ、一度もレンダリングされません。引き継ぐターンごとのリマインダーにとっては、これが正しい状態です。
clear_atを未設定のままにするのは、モデルがすべてのリクエストで参照すべきメッセージだけにしてください。
バリデーションエラーは次のとおりです。
messages.3.clear_at: Extra inputs are not permitted
messages.3.clear_at: clear_at is only permitted on role 'system' messages
messages.3.clear_at: Input should be 'next_user_message' or 'never'
messages.3: a turn-scoped system message supports text blocks only (clear_at: 'next_user_message')
messages.3: output_config is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: 'next_user_message')1つ目は、ベータヘッダーなしで返されるエラーです。Google Cloud と Claude in Amazon Bedrock では、Claude API と同様に anthropic-beta ヘッダーでベータ値を送信してください(ベータヘッダーを参照)。Amazon Bedrock の InvokeModel API では、代わりにリクエストボディの anthropic_beta 配列に含めてください。
SDK を通じて使用する場合は、messages 内の role: "system" エントリに clear_at を設定し、ベータヘッダーを送信します。次の例では、ユーザーターンの後にターンスコープのリマインダーを追加します。次のリクエストで後続のユーザーメッセージが存在するようになると、リマインダーは配列に残りますが、レンダリングされなくなります。
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Draft a short status update on the database migration for the team channel.",
},
# ターン単位のリマインダー:このターンでレンダリングされ、後続のユーザーメッセージが存在するとクリアされます。
{
"role": "system",
"clear_at": "next_user_message",
"content": "The reader is on call: keep this reply under 50 words.",
},
],
betas=["mid-conversation-system-clear-at-2026-08-21"],
)
for block in response.content:
if block.type == "text":
print(block.text)プロンプトキャッシングとの組み合わせ
会話途中のシステムメッセージとプロンプトキャッシングは、一緒に使用するように設計されています。
- キャッシングを明示的に有効にする。 キャッシングは、リクエストに
cache_control(トップレベルの自動キャッシングフィールド、またはコンテンツブロック上の明示的なブレークポイント)が含まれている場合にのみ行われます。会話途中のシステムメッセージはそれ自体ではキャッシュエントリを作成せず、キャッシングが有効でなければ保持すべき節約もありません。 - 安定したプレフィックスを通常どおりキャッシュする。 リクエスト間で変わらない最後のブロックに
cache_controlを置きます。それがトップレベルのsystemフィールドの末尾であれ、ツール定義の末尾であれ、メッセージ履歴内の安定した位置であれ同様です。 - ブレークポイントの後にシステムメッセージを追加する。 キャッシュ済みプレフィックスの後に来るため、プレフィックスのハッシュは変わらず、キャッシュは引き続きヒットします。
- 会話途中のシステムメッセージ自体もキャッシュ可能。 会話に入った時点で、安定した履歴の一部になります。次のターンでは、キャッシュブレークポイントをその先に移動でき(または自動キャッシングに任せることもでき)、システムメッセージは他のターンと同様にキャッシュから読み取られます。
すでに送信された会話途中のシステムメッセージを編集または削除することは避けてください。以前のメッセージに対する他の変更と同様に、その時点以降のキャッシュが無効になります。Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5、Claude Haiku 5.5では、以降のすべてのアシスタントターンの思考ブロックも無効になります。1ターンだけに適用すべきガイダンスには、ターンスコープのシステムメッセージを使用し、そのまま残しておいてください。指示を更新する必要がある場合は、古いものを書き換えるのではなく、新しいシステムメッセージを追加してください。連続するシステムメッセージは受け付けられ、単一のシステムセクションとして扱われます。このセクションは全体として同じ配置ルールに従います。
制限事項
- 最初のメッセージには使用できない。 コンテンツを含む
systemメッセージを、messagesの最初のエントリにすることはできません。会話の最初から適用する指示には、トップレベルのsystemフィールドを使用してください。 - 配置には制約がある。 コンテンツ(
text、tool_addition、またはtool_removalブロック)を含むsystemメッセージは、userターン(tool_resultブロックを含むuserターンも含む)またはサーバーツールの結果で終わるassistantターンの直後に置く必要があります。さらに、その後にassistantターンを続けるか、配列の末尾に置く必要があります。tool_useブロックとそのtool_resultの間に置くことはできません。それ以外の位置に置くと 400 エラーが返されます。ただし、例外が1つあります。一時停止されたassistantターン(サーバーツールの結果で終わるもの)の直後では、textブロックは受け付けられますが、tool_additionブロックとtool_removalブロックは受け付けられません。この場合は、まず一時停止されたターンを再開し、その後のsystemメッセージでツール変更を送信してください。contentが空で、output_config.effortだけを設定するメッセージは、その位置に何もレンダリングしません。このようなメッセージは、最初の位置や、assistantターンとuserターンの間など、messages内のどこにでも置くことができます。連続するsystemメッセージはまとめて判定されます。そのため、エフォートのみのメッセージの隣にテキストを含むメッセージを追加すると、グループ全体にコンテンツを含むメッセージのルールが適用されます。 - ターンスコープのメッセージはテキストのみで、変更せずに再送信する必要がある。
clear_at: "next_user_message"メッセージには、tool_addition、tool_removal、output_config、cache_controlを含めることはできません。また、クリアされた後も、以降のリクエストではmessages内にバイト単位で同一のまま残す必要があります。ターンスコープのシステムメッセージを参照してください。 - 信頼できないコンテンツには使用しない。 Claude はシステムメッセージの内容をオペレーターの指示として扱い、それに従います。生のツール出力、取得したドキュメント、Web コンテンツなど、会話の外部から得たテキストをシステムメッセージに直接含めないでください。含めると、そのテキストにオペレーターレベルの権限が与えられてしまいます。そのようなデータは
tool_resultブロックに含め、引き続きジェイルブレイクとプロンプトインジェクションの軽減のガイダンスに従ってください。
関連情報
キャッシングの仕組み、ブレークポイントの配置場所、キャッシュ使用量フィールドの読み方。
期待したキャッシュヒットが起こらなかったときに、2 つのリクエストがどこで分岐したかを正確に突き止めます。
メッセージ構造、マルチターン会話、および system フィールド。
効果的なプロンプトとシステム指示の書き方。
messages 配列内で tool_use および tool_result ブロックがどのように構造化されるか。
Was this page helpful?