Claude Platform Docs
Messages上下文管理

對話中途的系統訊息與工具變更

在對話進行到一半時變更系統指令或工具可用性,而不會使其之前的快取前綴失效。

系統指示通常位於頂層 system 欄位中,排在對話中每則訊息之前。這個位置非常適合「prompt caching」(提示快取):「system prompt」(系統提示)是穩定前綴的一部分,因此後續回合都能命中快取。但如果您在工作階段進行到一半才發現需要某些指示,這個位置就不理想了,因為編輯頂層 system 欄位會變更提示的最開頭,並使其後所有內容的快取失效。

對話中途的系統訊息正好能解決這個問題。您不必編輯頂層 system 欄位,而是在對話中新指示開始適用的位置附加一則 {"role": "system"} 訊息。已快取的前綴保持不變,因此下一個請求仍會從快取讀取它。新指示也仍會作為系統指示套用,而不會被當成一般的使用者文字。

對話中途的工具變更

tools 陣列在雜湊的請求前綴中位置比頂層 system 欄位更早,因此編輯它會使整個對話的提示快取失效。對話中工具變更是對話中系統訊息在工具方面的對應功能。您不必在對話的整個生命週期中固定工具清單,而是可以在輪次之間變更提供給模型的工具:預先在 tools 中宣告完整的工具集,然後使用 tool_addition 和 tool_removal 區塊,從對話中的特定位置起向模型提供某個工具或將其撤回。tools 陣列本身永遠不會變更,因此已快取的前綴保持完整。對話中工具變更處於 beta 階段,在 Claude API 上使用 inline-tools-2026-09-15 beta 標頭。

tool_addition 和 tool_removal 是 role: "system" 訊息之 content 陣列中的內容區塊,並且可以與 text 區塊混合放在同一則訊息中。該訊息遵循任何對話中系統訊息的放置規則,另外在暫停的輪次之後還有一項額外限制(請參閱限制),而變更會從對話中的該位置起生效。每個區塊的 tool 欄位是參照工具,而非定義工具:{"type": "tool_reference", "name": "..."} 指名在請求的 tools 陣列中宣告的工具,而 MCP connector 工具可以使用 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 宣告,這會使其保持隱藏,直到 tool_addition 區塊將其呈現出來。tool_addition 也會重新提供先前被 tool_removal 撤回的工具。

以下請求在 tools 中宣告 get_weather,然後在第一個使用者回合之後使用 tool_removal 區塊將其撤回。該請求會傳送 inline-tools-2026-09-15 beta 標頭。

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)

在訊息中定義工具(beta)

使用 inline-tools-2026-09-15 beta 標頭時,tool_addition 區塊可以依值定義工具,攜帶其完整定義,而不是依參照指名。這讓您可以透過附加一則 role: "system" 訊息,引入在對話開始時未知的工具,或其結構描述稍後會變更的工具。tools 陣列和每則較早的訊息都與傳送時完全相同,因此提示快取仍會命中,只有附加的訊息會作為新輸入處理。唯一的例外是沒有任何非延遲工具的 tools 陣列,這在下方規則中說明。此標頭也涵蓋依參照新增和移除工具,因此您不需要另外傳送 mid-conversation-tool-changes-2026-07-01。

將定義包裝在類型為 tool_definition 的 tool 物件中。definition 是一個 tools 項目,例如自訂工具或 Anthropic 定義的用戶端或伺服器工具,並帶有其一般設定,包括 cache_control 和 defer_loading。在 beta 期間,某些工具類型(包括電腦使用工具)尚無法在訊息中定義,並會傳回說明此情況的 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` 中至少保留一個非延遲載入的工具,如此一來,之後才定義的工具
    # 就不會改變轉譯後提示的開頭部分。
    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"
  }
}

要變更工具的結構描述,或將伺服器工具移至較新版本,請以相同名稱傳送不同的定義。新定義會從該位置開始取代先前的定義。重複使用不同類型工具名稱的定義會傳回 400 錯誤,且 error.details.error_code 設為 tool_name_conflict。同一工具的較新版本不算是不同類型。tool_removal 仍然接受參照,且已移除的工具之後可以再次定義或重新提供。

根據定義的呈現位置,衍生出以下幾項規則:

  • 預先宣告您已知的內容。 您在第一個請求時就已知的工具應放在 tools 中;如果模型還不應看到它,請搭配 defer_loading: true 和稍後的 tool_addition 參照。只有在第一個請求時未知或稍後會變更的工具,才依值定義。
  • 在 tools 中至少保留一個非延遲工具。 tools 陣列中沒有非延遲工具的對話仍會被接受,但它依值定義的第一個工具會變更所呈現提示的開頭,這會在該請求上造成一次完整的快取未命中。工具搜尋工具算作非延遲工具。
  • 帶日期的工具類型保留各自的 beta 標頭。 如果您依值定義的伺服器工具需要自己的 beta 標頭,請在對話中之後的每個請求上傳送該標頭。
  • cache_control 放在區塊上或定義中,不可兩者皆放, 並計入請求的斷點上限。延遲的定義不能攜帶 cache_control。

當超過以下任一限制時,請求會傳回 400 錯誤,且 error.details.error_code 設為 available_tools_limit_exceeded:

  • 在任何訊息之後可用的延遲工具超過 10,000 個。
  • 在第一則使用者訊息之後定義、且在任何訊息之後可用的工具超過 10,000 個。
  • 在第一則使用者訊息之後傳送、且在任何訊息之後仍可用的工具定義總計超過 4 MB(4,194,304 位元組)。
  • 呈現的工具文字大於 4 MB(4,194,304 位元組)。

在對話中途新增 MCP 伺服器(beta)

若要在對話進行到一半時新增 MCP 連接器伺服器,請將 mcp-client-2026-09-15 beta 標頭與 inline-tools-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?"},
        # 從此處開始,讓 calendar 伺服器的工具可供使用。
        # 此區塊僅指明伺服器名稱,絕不包含 URL 或權杖。
        {
            "role": "system",
            "content": [
                {
                    "type": "tool_addition",
                    "tool": {
                        "type": "tool_definition",
                        "definition": {
                            "type": "mcp_toolset",
                            "mcp_server_name": "calendar",
                        },
                    },
                },
            ],
        },
    ],
)

# 回應會以 calendar 伺服器的 mcp_tool_listing 區塊開頭,
# 因此請檢查每個區塊的類型,而非直接讀取 content[0]。
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 在產生回應時擷取了伺服器的工具清單,該回應會以 mcp_tool_listing 區塊開頭,每個被擷取的伺服器各一個。如果您的程式碼讀取 content[0],請略過這些區塊。請原封不動地傳回助理訊息(包括此區塊),並在每個攜帶它的請求上持續傳送 mcp-client-2026-09-15。之後的請求便會使用記錄下來的清單,而不會再次詢問伺服器。若要自行固定工具集,請將該清單複製到 mcp_toolset 的 tools 欄位中,如固定 MCP 伺服器的工具清單所述。

mcp-client-2026-09-15 包含 mcp-client-2025-11-20 的所有功能,因此您不需要同時傳送兩者。這些功能可在 Claude API 上使用。使用 MCP 連接器的請求仍適用其資料保留條款。

何時使用對話中途的系統訊息

提示快取會依序對請求前綴進行雜湊:先是 tools,接著是 system,然後是 messages。快取命中要求前綴在快取斷點之前與最近的某個請求逐位元組完全相符。

這個順序意味著頂層 system 欄位位於雜湊前綴的最開頭附近。對它的任何變更,即使只是附加一個句子,都會產生不同的雜湊值,而該請求對於系統提示以及其後每一則已快取的訊息都會錯失快取。

對話中途的系統訊息讓您可以改為在訊息歷史的末端加入指令。新指令之前的所有內容都保持不變,因此現有的快取項目仍然相符,只有新訊息會被當作新的輸入處理。

以下是幾個這一點很重要的情境:

  • 工作階段中途的政策或角色變更。 一個長時間的代理工作階段在數十個已快取的輪次之後需要一項新的限制(「從現在起,所有 SQL 都寫成參數化查詢」)。將它加入頂層 system 欄位會重新處理整個歷史。
  • 必須具有權威性的逐輪次上下文。 您想要以系統層級的權重注入一則時效性備註、工作階段截止時間或工具可用性變更,而它變動得太頻繁,不適合放在快取前綴中。
  • 不應堆積的逐輪次提醒。 某個執行框架(harness)在每批工具結果之後提醒模型(「將獨立的讀取請求一起發出」、「使用者已經有一段時間沒有收到您的回覆了」),並希望模型只看到最新的那一份。輪次範圍的系統訊息只會在一個輪次中呈現,之後不耗費任何成本,且不需要從歷史中刪除任何內容。
  • 您的應用程式觀察到的狀態變更。 您的應用程式注意到某件 Claude 應視為操作者層級事實的事情:磁碟上的檔案已變更、使用者切換了自動核准設定、可用工具已變更,或剩餘的 token 預算降到某個門檻以下。
  • 不應中斷代理迴圈的使用者輸入。 使用者在 Claude 仍在為先前的請求執行工具時輸入了後續內容。在下一個工具結果之後將其作為系統訊息轉達,可讓 Claude 將新輸入融入它已在進行的工作中,而不是將其視為需要切換過去的新請求。在 Claude Sonnet 5.5 和 Claude Haiku 5.5 上,請改為將使用者的話語作為 text 區塊附加在同一則 user 訊息中最後一個 tool_result 之後。請參閱放置於工具結果之後。
  • 授予常設權限的模式切換。 工作階段層級的模式可以使用對話中途的系統訊息,對某項昂貴的能力(例如自動啟動多代理工作流程)授予常設同意,每隔數個輪次附上簡短的提醒,並在模式關閉時發出退出通知。如需完整範例,請參閱建構編排模式。

在上述所有情況中,您都可以將指令放在一般的 user 訊息中,而 Claude 確實會遵循在使用者輪次中送達的指令。差別在於優先順序:user 訊息被視為來自終端使用者,而 system 訊息被視為來自您,也就是應用程式操作者。當兩者衝突時,系統指令優先,因此對於即使終端使用者要求不同內容也應成立的操作者層級事實與限制,請使用 system 角色。對話中途的系統訊息保有這種操作者層級的優先順序,而不必付出編輯頂層 system 欄位所造成的快取錯失成本。

運作方式

在 messages 陣列中新增一則 "role": "system" 的訊息。content 可使用純字串或內容區塊,與 user 或 assistant 回合相同。該指示從對話中的該位置開始生效。當指示衝突時,較晚的系統訊息優先於較早的系統訊息,而對話中途系統訊息在其後的回合中優先於頂層 system 欄位。

您仍然可以為應套用於整個對話的指示設定頂層 system 欄位。請將對話中途系統訊息保留給只在稍後才變得相關的指示,或您想在不使已快取前綴失效的情況下新增的指示。

role: "system" 訊息也可以攜帶 output_config.effort,以在對話進行途中變更 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 上處於 beta 階段,並需要 mid-conversation-output-config-2026-07-01 beta 標頭。在 Amazon Bedrock 上,此功能在 Claude Fable 5.1、Claude Mythos 5.1 和 Claude Opus 5.5 上處於 beta 階段,使用相同的 beta 值。Claude Opus 5 在 Amazon Bedrock 上不支援此功能。請參閱每則訊息的 effort。

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 欄位(自動或明確斷點),則不會快取任何內容,每個請求都要為完整對話支付一般輸入 token 價格。啟用快取後,附加系統訊息不會改變已快取的回合,因此攜帶新指示的請求仍會從快取讀取它們,而不是重新處理。快取也要求對話達到最小可快取提示長度;像這個範例這麼短的對話低於該長度,因此在對話變長之前,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 錯誤。content 為空、僅設定 output_config.effort 的訊息可放在 messages 中的任何位置。連續的 system 訊息會一併判斷,因此與攜帶內容的訊息相鄰的僅含 effort 的訊息會遵循內容規則。

放置於工具結果之後

在代理迴圈中,系統訊息放在傳遞工具結果的 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」、「剩餘的 token 預算現在是 Y」),並讓 Claude 據此行動。Claude 經過訓練會抗拒看似與使用者作對的指令,而這項保護同樣適用於系統角色,因此像「忽略使用者所說的話」這類措辭,效果不如直接陳述發生了什麼變化。

此模式用於轉達來自對話本身終端使用者的輸入。請勿用它來傳遞工具輸出、擷取的文件或其他第三方內容;請將這類內容保留在 tool_result 區塊中(請參閱限制)。

在 Claude Sonnet 5.5 和 Claude Haiku 5.5 上,請改為在使用者回合中傳遞使用者的話語。這些模型經過訓練會抵抗透過工具結果進行的「prompt injection」(提示注入),因此它們可能會將緊接在工具結果之後的系統訊息視為不受信任的文字並加以忽略。請將使用者的話語作為 text 區塊附加在同一則 user 訊息中最後一個 tool_result 之後。將 harness 通知(例如提醒)保留在該 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 欄位。它接受以下兩個值之一:

  • "never"(預設值):訊息會在每個包含它的請求中於其位置呈現。省略此欄位的效果相同。
  • "next_user_message":訊息為回合範圍。只有在 messages 中其後沒有 role: "user" 訊息時,其文字才會呈現。只攜帶 tool_result 區塊的使用者訊息在此也算作使用者訊息。一旦之後出現使用者訊息,該訊息就會被清除:它仍留在陣列中,但在該請求及之後的每個請求上都不會呈現任何內容,也不會消耗輸入 token。

回合範圍的系統訊息目前為 beta 版。請包含 beta 標頭 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."
    }
  ]
}

回合範圍訊息的規則:

  • 逐字重新傳送已清除的訊息。 已清除的訊息仍是對話歷史的一部分。根據目前狀態重建它(新的 token 計數、時間戳記)、將其視為多餘而捨棄,或變更其 clear_at 值,都屬於對較早訊息的編輯。提示快取會從該位置開始未命中,而在 Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5 和 Claude Haiku 5.5 上,其後產生的每個思考區塊都會無法通過對話檢查。
  • 僅限文字。 content 是一個或多個 text 區塊(或字串)。在輪次範圍訊息上使用 tool_addition 和 tool_removal 區塊會傳回 400 錯誤,output_config 也是如此。這些內容請使用另一則不含 clear_at 的 role: "system" 訊息。
  • 其區塊上不可有 cache_control。 已清除的訊息永遠不會成為快取鍵的一部分,因此放在其上的中斷點永遠無法相符。請改將中斷點放在前一個使用者輪次的最後一個區塊上,如範例所示。頂層自動快取欄位在選擇中斷點時會略過輪次範圍訊息。在清除某則訊息的請求中,可重複使用的已快取前綴會在其之前的使用者輪次結束,因此只有該訊息與新使用者訊息之間的那一個助理輪次會被重新處理。
  • 放置規則仍然適用,無論是否已清除。輪次範圍訊息必須跟在 user 輪次(或以伺服器工具結果結尾的 assistant 輪次)之後,並位於 assistant 輪次之前或作為陣列的結尾,與任何對話中系統訊息相同。作為陣列結尾的訊息一律會呈現。直接接著另一則 user 訊息的訊息會導致 400 錯誤,而不是被清除:請將一輪工具的所有結果放在同一則使用者訊息中,並將提醒放在其後。
  • 助理輪次不會清除它。 訊息之後的預填或暫停助理輪次,或伺服器端工具迴圈,都不會新增使用者訊息,因此該訊息在該延續中仍會呈現。若要在用戶端工具迴圈中持續顯示提醒,請在每則 tool_result 訊息之後再次附加它。
  • Token 計數依呈現內容而定。 已清除的訊息不會增加 usage.input_tokens 或 token 計數。
  • 匯入的歷史。 在您一次建構的對話紀錄中(少樣本範例、遷移的對話),若輪次範圍訊息之後已有助理輪次和使用者訊息,它會從第一個請求起就被清除,且永遠不會呈現。對於您要沿用的每輪提醒而言,這是正確的狀態。只有在模型應於每個請求中都看到的訊息上,才不設定 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')

第一個是未包含 beta 標頭時傳回的錯誤。在 Google Cloud 和 Claude in Amazon Bedrock 上,請在 anthropic-beta 標頭中傳送 beta 值,與 Claude API 相同(請參閱 Beta 標頭)。使用 Amazon Bedrock InvokeModel API 時,請改將其放在請求主體的 anthropic_beta 陣列中。

透過 SDK,請在 messages 中的 role: "system" 項目上設定 clear_at,並傳送 beta 標頭。以下範例在使用者回合之後附加一則回合範圍提醒;在下一個請求中,一旦存在較晚的使用者訊息,該提醒仍保留在陣列中,但不再呈現:

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 可以是頂層的自動快取欄位,也可以是內容區塊上的明確斷點。對話中途系統訊息本身不會建立快取項目;若未啟用快取,也就沒有可保留的節省效益。
  • 照常快取穩定的前綴。 將 cache_control 放在各次請求之間保持不變的最後一個區塊上。這個位置可以是頂層 system 欄位的結尾、工具定義的結尾,或是訊息歷史中的某個穩定位置。
  • 在斷點之後附加系統訊息。 由於系統訊息位於已快取的前綴之後,因此不會改變前綴雜湊,快取仍會命中。
  • 對話中途系統訊息本身也可被快取。 系統訊息一旦進入對話,就會成為穩定歷史的一部分。在下一個回合中,您可以將快取斷點移到它之後(或依賴自動快取來完成此操作),系統訊息就會像其他任何回合一樣從快取中讀取。

請避免編輯或移除已傳送的對話中系統訊息。與對較早訊息的任何其他變更一樣,這會使從該位置開始的快取失效。在 Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5 和 Claude Haiku 5.5 上,這也會使之後每個助理回合中的思考區塊失效。對於只應套用於單一回合的指引,請使用回合範圍系統訊息並將其保留在原處。如果指示需要演進,請附加新的系統訊息,而不是改寫舊的訊息。連續的系統訊息會被接受並視為單一系統區段,整體遵循相同的放置規則。

限制

  • 不可作為第一則訊息。 攜帶內容的 system 訊息不能是 messages 中的第一個項目。對於從一開始就適用的指示,請使用頂層 system 欄位。
  • 放置位置受到限制。 攜帶內容(text、tool_addition 或 tool_removal 區塊)的 system 訊息必須緊接在 user 回合(包括攜帶 tool_result 區塊的 user 回合)或以伺服器工具結果結尾的 assistant 回合之後,並且必須位於 assistant 回合之前或作為陣列的結尾。它不能位於 tool_use 區塊與其 tool_result 之間。放在其他位置會傳回 400 錯誤。有一個例外:緊接在暫停的 assistant 回合(以伺服器工具結果結尾的回合)之後,不接受 tool_addition 和 tool_removal 區塊,但接受 text 區塊;請先恢復暫停的回合,然後在下一則 system 訊息中傳送工具變更。content 為空、僅設定 output_config.effort 的訊息在其位置不會呈現任何內容,並且可放在 messages 中的任何位置,包括第一個位置,或 assistant 回合與 user 回合之間。連續的 system 訊息會一併判斷,因此在僅含 effort 的訊息旁新增攜帶文字的訊息,會使整組訊息都須遵循內容規則。
  • 回合範圍訊息僅限文字,且須逐字重新傳送。 clear_at: "next_user_message" 訊息不攜帶 tool_addition、tool_removal、output_config 或 cache_control,且一旦被清除,在之後的請求中必須逐位元組保留在 messages 中。請參閱回合範圍系統訊息。
  • 不適合放置不受信任的內容。 Claude 會將系統內容視為營運者指示並加以遵循。請勿將來自對話外部的文字,例如原始工具輸出、擷取的文件或網頁內容,直接放入系統訊息中;這樣做會賦予該文字營運者層級的權限。請將這些資料保留在 tool_result 區塊中,並持續遵循減輕越獄與提示注入的指引。

快取的運作方式、斷點的放置位置,以及如何解讀快取用量欄位。

當您預期的快取命中沒有發生時,找出兩個請求究竟在哪裡產生分歧。

訊息結構、多輪對話,以及 system 欄位。

撰寫有效的提示與系統指令。

tool_use 與 tool_result 區塊在 messages 陣列中的結構方式。

Was this page helpful?