思考區塊的前綴檢查
前綴檢查比對的內容、哪些模型會執行它、請求未通過時會發生什麼,以及如何處理 400 錯誤與沒有錯誤的情況。
每個將思考區塊傳回給具備「preserved thinking」(保留思考)的模型的請求,都會經過「prefix check」(前綴檢查)。如果在 Claude 產生某個區塊之後,system、tools 或較早的訊息有所變更,前綴檢查就會失敗。如果位於其他思考區塊之間的某個思考區塊被省略或移動,前綴檢查也會失敗。
未通過前綴檢查可能會也可能不會導致 400 錯誤,視模型而定,因此請處理兩種情況。
前綴檢查會影響誰
如果下列任一項成立,您就不需要做任何變更:
- 由 Claude Code、claude.ai 或 Claude Managed Agents 管理您的對話歷史。
- 由 Claude Agent SDK 管理歷史,且您提供給 SDK 的系統提示保持不變。
- 您的程式碼遵循僅附加整合的三項習慣,且途中沒有任何東西改寫其請求。
- 您沒有呼叫任何具備保留思考的模型。
如果您的請求會經過程式庫、代理伺服器或閘道,請比對它送出的內容與您送出的內容。如果您自己運行這類元件,請參閱程式庫、代理伺服器和閘道,了解應該原樣傳遞哪些內容。
哪些內容必須保持不變,以及原因
請讓您的整合成為「append-only」(僅附加)。三項習慣即可做到:
- 將每個助理輪次完全按照 API 傳回的樣子送回,包括文字為空的思考區塊。
- 每個對話只建構一次
system和tools,並且每次都送出同一份。 - 將每項更新放在結尾的新訊息中,並讓它留在那裡。
每個思考區塊的推理,都是針對它之前的確切內容:system、tools 以及每一則較早的訊息。這些內容就是該區塊的前綴,也是前綴檢查所比對的對象。
前綴檢查與提示快取類似,不同之處在於,一項變更會使其後的思考失效,而不僅僅是未命中快取。
以一個在系統提示中放入今天日期的應用程式為例。到了午夜,日期改變,對話中既有思考的前綴也隨之改變。那些思考會因此失效,下一個請求就可能失敗。僅附加的應用程式會讓系統提示維持原樣,並在結尾的訊息中說明新的日期。
一項變更只會使已經位於其後的思考失效。位於它之前的思考,以及 Claude 之後產生的思考,都會保持有效。
如果您的程式碼會變更系統提示、工具或歷史
| 如果您的程式碼… | 該怎麼做 |
|---|---|
| 以日期、模式或指示檔案重新建構系統提示 | 停止變更 system。將您自己的指示以系統訊息附加(即 messages 中的一個 role: "system" 項目),並在最新的輪次中說明新的值。對於其他人可以編輯的文字,請改為參閱其他人可以編輯的文字。 |
| 新增、移除或改寫某個工具,或在 MCP 伺服器連線時增加工具 | 停止變更 tools,並在系統訊息中新增或移除工具。 |
| 修剪、收合或摘要較舊的輪次,並讓最新的輪次保持不變 | 讓 API 撰寫摘要,或移除保留的輪次的思考。 |
其他原因,例如略過文字為空的思考區塊,或重新建構已儲存的對話,各有其修正方式:請參閱變更工具或指示而不使前綴檢查失敗。若要找出您的原因,請讓代理檢查您的程式碼。
前綴檢查失敗時各模型的行為
在 Claude API 和部分雲端平台上,當 prefix_mismatch_behavior 未設定時,未通過前綴檢查的結果取決於模型:
| 具備保留思考的模型 | 結果 |
|---|---|
| Claude Fable 5.2 | 400 錯誤 |
| Claude Mythos 5.2 | 400 錯誤 |
| Claude Mythos 5.1 | 400 錯誤 |
| Claude Fable 5.1 | 可能出現 400 錯誤 |
| Claude Opus 5.5 | 可能出現 400 錯誤 |
| Claude Sonnet 5.5 | 可能出現 400 錯誤 |
| Claude Haiku 5.5 | 可能出現 400 錯誤 |
表格中標示「可能出現 400 錯誤」的地方,有兩種情況:未通過前綴檢查的請求可能會得到 400 錯誤,也可能不會得到錯誤。沒有傳回錯誤時,未通過前綴檢查的區塊會傳到模型。Claude 會像讀取任何其他輸入一樣讀取它們,您需要為它們付費,而 Claude 會依據針對已經變更之內容的推理來工作。
在這些模型上,您可以檢查請求會得到哪種情況,但仍請處理兩種情況。
將 prefix_mismatch_behavior 保持未設定的 Message Batches 項目不會得到錯誤,且 API 可能會捨棄未通過前綴檢查的區塊。
處理兩種情況
若要讓每個請求都得到單一結果,請讓您的整合成為僅附加,或設定 prefix_mismatch_behavior。否則,您的程式碼必須處理兩種行為。
- 僅附加: 遵循三項習慣,您的程式碼就不會讓請求未通過前綴檢查。
- 此設定: 在每個請求上使用
"error",每次失敗都會是 400 錯誤,而您可以在程式碼中捕捉它。 - 兩種行為: 如果您將此設定保持未設定,請捕捉 400 錯誤,並留意傳到 Claude 的未通過前綴檢查的思考。
發生 400 錯誤後,請在該對話之後的請求中送出 "drop_block" 以進行復原。這有其代價:請參閱捨棄思考的代價。請勿為了隱藏錯誤而在您所有的對話中送出它。
技術細節
前綴檢查如何運作
具備保留思考的模型會在每個思考區塊的 signature 中記錄其前綴的指紋。API 參考文件將前綴檢查稱為對話檢查(conversation check),而 400 錯誤會指出未通過前綴檢查的區塊 is bound to a different conversation。
哪些模型會執行前綴檢查
前綴檢查會在 Claude API 和部分雲端平台上執行。它會在送往具備保留思考的模型之一的請求上,檢查由這類模型所產生的思考區塊。在 Claude API 上,其他模型(例如 Claude Opus 5)不會執行它,它也不涵蓋這些模型的區塊。
什麼算是變更
- 每個區塊都會與其自身的記錄比對。 API 會將此請求中某個區塊之前的內容,與 Claude 產生該區塊時其簽章所記錄的內容進行比對。您的上一個請求與此無關。前綴檢查只看內容,不看工作階段、ID 或使用者。新請求或分支中的相同內容都會通過前綴檢查。
- 前綴檢查比對的是您送出的內容,而不是 Claude 讀取的內容。 在 token 閾值時進行壓縮和上下文編輯只會改變 Claude 讀取的內容,因此永遠不算是變更。在閾值壓縮區塊之後,API 只會比對從該區塊起的訊息,以及
system和tools。隨選壓縮有其自身的條件:請參閱保留的思考維持有效的條件。對於以 URL 傳送的檔案,以及在 Claude API 上的 MCP 工具清單,API 會改為比對它所擷取的內容。 - 您送出的思考必須是連續不中斷的序列。 思考區塊不會作為內容進行比對。但您送出的每個思考區塊(第一個除外),其前一個思考區塊都必須與 Claude 產生它時相同。因此,您可以省略最舊的、最新的或全部的思考區塊,但不能省略中間的某一個。
變更可以小到只是工具描述中的一個字。變更、插入、移動或刪除較早的訊息都算是變更,無論其角色為何。變更思考區塊所在訊息中位於其前面的文字也算。
什麼不算是變更
| 這不算是變更 | 原因 |
|---|---|
model、effort、max_tokens、tool_choice、metadata、thinking.display 及其他參數 | 只會比對 system、tools 和訊息 |
| JSON 格式或鍵的順序 | API 比對的是解析後的 JSON,而不是其文字 |
cache_control 標記 | 它們指出要在哪裡快取,並非 Claude 讀取的內容 |
具有 defer_loading: true 且尚未被任何內容參照的工具 | 在有內容參照它之前,它不在 Claude 的上下文中 |
設定 prefix_mismatch_behavior
beta 標頭 thinking-binding-controls-2026-08-01 會新增設定 thinking.block_binding.prefix_mismatch_behavior,以及回應中的 input_transformations 陣列。
| 值 | 如果某個區塊未通過前綴檢查 |
|---|---|
"error" | API 會以 400 錯誤拒絕該請求,錯誤中會指出第一個無效的區塊 |
"drop_block" | API 會捨棄無效的區塊,請求會成功。您不需要為這些區塊付費,但捨棄它們可能會花費更多 |
未設定,或 null | 視模型而定 |
只要變更仍然存在,未通過前綴檢查的區塊在之後每個送出它們的請求中都會保持無效。此設定只作用於攜帶它的那一個請求。在思考關閉的情況下("disabled" 或 "between_tools"),送出此設定在每個模型上都會是 400 錯誤。
以下請求將 prefix_mismatch_behavior 設為 "drop_block"。在第一個輪次中沒有需要送回的思考,因此 input_transformations 會傳回空值:
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
thinking={
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "drop_block"},
},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
betas=["thinking-binding-controls-2026-08-01"],
)
for block in response.content:
if block.type == "text":
print(block.text)
print(f"Input transformations: {len(response.input_transformations or [])}")監看正式環境流量
當 prefix_mismatch_behavior 未設定時,在部分模型上,未通過前綴檢查的請求可能不會得到錯誤。未通過前綴檢查的思考區塊接著會傳到模型。若要在正式環境流量中找出這些區塊,請送出 thinking-binding-controls-2026-08-01 beta 標頭、將此設定保持未設定,並記錄每個回應的 input_transformations 陣列。此標頭會新增該陣列,並不會改變模型接收到的內容。
每個這類區塊都會在該陣列中擁有自己的 thinking_mismatch_allowed 項目。一個項目看起來像這樣:
{
"input_transformations": [
{
"type": "thinking_mismatch_allowed",
"path": "messages.1.content.0",
"reason": "prefix_binding_mismatch"
}
]
}若要找出變更,請參閱找出您的程式碼變更了什麼。
檢查您會得到哪種情況
在部分模型上,未通過前綴檢查的請求可能會得到 400 錯誤,也可能不會得到錯誤。以下測試可顯示請求會得到哪一種:
- 取一個包含來自這些模型之一的思考區塊的對話。變更或新增系統提示(
system)。該區塊接著會未通過前綴檢查,因為系統提示在 Claude 產生該區塊之後有所變更。 - 將其連同
thinking-binding-controls-2026-08-01beta 標頭送往同一個模型,並將prefix_mismatch_behavior保持未設定。
回應會是下列其中之一:
- 指出
bound to a different conversation的 400 錯誤: 該請求得到了 400 錯誤。 input_transformations陣列中含有thinking_mismatch_allowed項目的 200 回應: 該請求沒有得到錯誤。每個項目都指出一個未通過前綴檢查且傳到 Claude 的思考區塊。input_transformations陣列為空的 200 回應: 沒有區塊未通過前綴檢查,因此此測試無法顯示任何結果。請確認該對話包含來自該模型的思考區塊。
此結果只描述那一個請求,並不保證之後的請求會如何,因此請撰寫您的程式碼以處理兩種情況。
後續步驟
針對您的程式碼對對話所做的每項變更,應改為送出什麼。
復原未通過前綴檢查的對話、找出您的程式碼變更了什麼,並測試問題是否已消除。
保留思考是什麼、思考區塊與什麼綁定,以及切換模型或帳戶。
這個頁面有幫助嗎?