システム指示は通常、会話内のすべてのメッセージより前にあるトップレベルの system フィールドに配置されます。この位置はプロンプトキャッシングに適しています。システムプロンプトは安定したプレフィックスの一部であるため、後続のターンはキャッシュにヒットします。しかし、セッションの途中で必要だと判明した指示には不向きな位置です。トップレベルの system フィールドを編集すると、プロンプトの冒頭部分が変わり、それ以降のすべてのキャッシュが無効化されてしまうためです。
会話途中のシステムメッセージは、このギャップを埋めます。トップレベルの system フィールドを編集する代わりに、新しい指示が関連するようになった会話内の位置に {"role": "system"} メッセージを追加します。キャッシュされたプレフィックスは変わらないため、次のリクエストでも引き続きキャッシュから読み取られ、新しい指示は通常のユーザーテキストとしてではなく、システム指示として適用されます。
このページでは2つの機能について説明します。一般提供されている会話途中のシステムメッセージと、Claude Opus 5で導入されたベータ機能である会話途中のツール変更です。後者は同じアプローチを tools 配列に適用するものです。
tools 配列は、ハッシュ化されるリクエストプレフィックス内でトップレベルの system フィールドよりもさらに前に位置するため、これを編集すると会話全体のプロンプトキャッシュが無効化されます。Claude Opus 5で導入されたベータ機能である会話途中のツール変更は、会話途中のシステムメッセージのツール版に相当します。会話の全期間にわたってツールリストを固定する代わりに、ターン間でモデルに提供するツールを変更します。まず tools で完全なツールセットを宣言し、その後 tool_addition および tool_removal ブロックを使用して、会話内の特定の時点以降、モデルにツールを提供したり、取り下げたりします。tools 配列自体は変更されないため、キャッシュされたプレフィックスはそのまま維持されます。
tool_addition と tool_removal は role: "system" メッセージの content 配列内のコンテンツブロックであり、同じメッセージ内で text ブロックと混在させることができます。このメッセージは、他の会話途中のシステムメッセージと同じ配置ルールに従い(制限事項を参照)、変更は会話内のその時点以降に適用されます。各ブロックの tool フィールドはツールを定義するのではなく参照します。{"type": "tool_reference", "name": "..."} はリクエストの tools 配列で宣言されたツールを名前で指定し、MCPコネクタのツールは mcp_tool_reference(server_name と name)で個別に、または mcp_toolset_reference(server_name)でツールセット全体として参照できます。tools で宣言されていない名前を参照すると、400エラーが返されます。
tools で宣言されたすべてのツールは、defer_loading: true で宣言されていない限り、会話の開始時からモデルに提供されます。defer_loading: true を指定すると、tool_addition ブロックがそのツールを表示するまで保留されます。tool_addition は、以前の tool_removal で取り下げられたツールを再度提供することもできます。
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
betas=["mid-conversation-tool-changes-2026-07-01"],
# ツールセット全体は最初に宣言され、以降変更されないため、
# キャッシュされたプレフィックスはそのまま維持されます。
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)会話途中のツール変更はベータ版です。使用するには、リクエストにベータヘッダー mid-conversation-tool-changes-2026-07-01 を含めてください。Claude Fable 5、Claude Mythos 5、Claude Opus 4.8、およびClaude Opus 5で、Claude API、Amazon Bedrock、Google Cloud上で利用できます。
プロンプトキャッシングは、リクエストプレフィックスを tools、system、messages の順にハッシュ化します。キャッシュヒットには、キャッシュブレークポイントまでのプレフィックスが最近のリクエストとバイト単位で完全に一致する必要があります。
この順序により、トップレベルの system フィールドはハッシュ化されるプレフィックスの冒頭近くに位置します。一文を追加するだけでも、変更があれば異なるハッシュが生成され、リクエストはシステムプロンプトおよびそれ以降にキャッシュされたすべてのメッセージについてキャッシュミスとなります。
会話途中のシステムメッセージを使用すると、代わりにメッセージ履歴の末尾に指示を追加できます。新しい指示より前のすべてが変更されないため、既存のキャッシュエントリは引き続き一致し、新しいメッセージのみが新規入力として処理されます。
これが重要となる状況をいくつか挙げます。
system フィールドに追加すると、履歴全体が再処理されてしまいます。これらすべてのケースで、指示を通常の user メッセージに入れることもでき、Claudeはユーザーターンで届いた指示にも従います。違いは優先度です。user メッセージはエンドユーザーからのものとして扱われ、system メッセージはアプリケーションオペレーターであるあなたからのものとして扱われます。両者が矛盾する場合、システム指示が優先されます。そのため、エンドユーザーが異なることを求めても維持されるべきオペレーターレベルの事実や制約には system ロールを使用してください。会話途中のシステムメッセージは、トップレベルの system フィールドを編集することによるキャッシュミスのコストを払うことなく、そのオペレーターレベルの優先度を維持します。
messages 配列に "role": "system" のメッセージを追加します。content には、user や assistant ターンと同様に、プレーンな文字列またはコンテンツブロックを使用します。指示は会話内のその時点以降に適用されます。指示が矛盾する場合、後のシステムメッセージが前のものより優先され、会話途中のシステムメッセージはそれ以降のターンにおいてトップレベルの system フィールドより優先されます。
会話全体に適用すべき指示には、引き続きトップレベルの system フィールドを設定できます。会話途中のシステムメッセージは、後になって初めて関連するようになる指示や、キャッシュされたプレフィックスを無効化せずに追加したい指示のために取っておいてください。
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
# 自動プロンプトキャッシング:各リクエストはそれまでの会話をキャッシュし、
# 次のリクエストは変更されていないプレフィックスをキャッシュから読み取ります。
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のままです。
会話途中のシステムメッセージは、user ターン(またはサーバーツール結果で終わる assistant ターン)の直後に配置する必要があり、messages の最後のエントリであるか、直後に assistant ターンが続く必要があります。tool_result ブロックを含む user メッセージもこれに該当します。エージェントループでは、ツール結果の直後、Claudeの次のターンの前にシステムメッセージを配置できます。assistant の tool_use ブロックとそれに応答する tool_result の間を含め、それ以外の位置に配置すると400エラーが返されます。
エージェントループでは、システムメッセージはツール結果を届ける user メッセージの後に配置します。ここは、Claudeが作業している間にユーザーが入力した内容をアプリケーションが中継できる場所でもあり、ターンを再開することなく新しいコンテキストを取り込めます。
[
{ "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 ブロックに保持してください(制限事項を参照)。
会話途中のシステムメッセージとプロンプトキャッシングは、併用することを前提に設計されています。
cache_control(トップレベルの自動キャッシングフィールド、またはコンテンツブロック上の明示的なブレークポイント)が含まれている場合にのみ発生します。会話途中のシステムメッセージはそれ自体でキャッシュエントリを作成せず、キャッシングが有効でなければ維持すべき節約もありません。cache_control を配置します。それがトップレベルの system フィールドの末尾であっても、ツール定義の末尾であっても、メッセージ履歴内の安定した位置であっても構いません。すでに送信した会話途中のシステムメッセージを編集または削除することは避けてください。以前のメッセージへの他の変更と同様に、その時点以降のキャッシュが無効化されます。指示を更新する必要がある場合は、古いものを書き換えるのではなく、新しいシステムメッセージを追加してください。連続するシステムメッセージは受け入れられ、単一のシステムセクションとして扱われ、全体として同じ配置ルールに従います。
system メッセージを messages の最初のエントリにすることはできません。冒頭から適用される指示には、トップレベルの system フィールドを使用してください。system メッセージは、user ターン(tool_result ブロックを含む user ターンを含む)またはサーバーツール結果で終わる assistant ターンの直後に配置する必要があり、assistant ターンの前に来るか、配列の末尾である必要があります。tool_use ブロックとその tool_result の間に配置することはできません。それ以外の位置に配置すると400エラーが返されます。tool_result ブロックに保持し、引き続きジェイルブレイクとプロンプトインジェクションの軽減に従ってください。キャッシングの仕組み、ブレークポイントの配置場所、キャッシュ使用状況フィールドの読み方。
期待したキャッシュヒットが発生しなかった場合に、2つのリクエストがどこで分岐したかを正確に特定します。
メッセージ構造、マルチターン会話、および system フィールド。
効果的なプロンプトとシステム指示の書き方。
messages 配列内での tool_use および tool_result ブロックの構造。
Was this page helpful?