Claude Platform Docs
MessaggiRagionamento

Ragionamento preservato

Il ragionamento preservato consente a un modello di usare un blocco di ragionamento di un turno precedente solo se lo ha prodotto quel modello o uno di un insieme fisso di altri modelli e se nulla prima del blocco è cambiato.

Il "preserved thinking" (ragionamento preservato) è una proprietà dei modelli Claude più recenti che protegge dalla distillazione. Determina se il modello può usare un blocco di ragionamento che rimandi da un turno precedente. A partire da Claude Fable 5.1, quando un blocco thinking o redacted_thinking torna in una richiesta, l'API controlla la signature del blocco per due aspetti:

  • Il modello può leggere il blocco. Ogni modello legge i propri blocchi di ragionamento e quelli di un insieme fisso di altri modelli. Claude Fable 5.1 legge i blocchi di Claude Opus 5 e, sulla Claude API, di Claude Opus 5.5; né Claude Opus 5 né Claude Opus 5.5 leggono i blocchi di Claude Fable 5.1. Se il modello corrente non può leggere un blocco, l'API lo scarta da quella richiesta senza errori. Consulta Cambiare modello a metà conversazione.
  • Nulla prima del blocco di ragionamento è cambiato. Il prompt system di primo livello, i tools e i messages che precedono il blocco costituiscono il suo "prefix" (prefisso). Se il prefisso differisce da quello che hai inviato quando il blocco è stato prodotto, quel blocco e ogni blocco di ragionamento successivo non sono validi, e l'API rifiuta la richiesta con un errore 400 oppure scarta i blocchi non validi, a tua scelta. Consulta Mantenere invariato il prefisso.

Anche i blocchi di ragionamento di Claude Sonnet 5.5 e Claude Haiku 5.5 sono legati all'account che li ha prodotti. Consulta I blocchi di ragionamento restano con l'account che li ha prodotti per sapere dove l'API applica questa regola.

Il controllo del modello si applica a ogni account. L'API applica il controllo del prefisso per impostazione predefinita agli account creati a partire dal 31 agosto 2026, 00:00 UTC. Sugli account più vecchi, applica il controllo del prefisso solo alle richieste che impostano thinking.block_binding.prefix_mismatch_behavior. Rendi la tua integrazione append-only indipendentemente dall'età del tuo account, così lo stesso codice funziona su ogni account, inclusi gli account più recenti soggetti al controllo per impostazione predefinita.

Chi deve modificare qualcosa

Non cambia nulla per te se le tue richieste vengono costruite da Claude Code, claude.ai, Claude Managed Agents o dal Claude Agent SDK, oppure se il tuo codice mantiene system e tools fissi per una sessione e si limita ad aggiungere elementi a messages. Claude Mythos 5.1 e i modelli precedenti a Claude Fable 5.1 non eseguono il controllo del prefisso. Se non rimandi mai i blocchi di ragionamento, il controllo del prefisso non ha nulla da rifiutare, e il modello non riceve nulla del suo ragionamento precedente.

Controlla la tua integrazione se, tra due richieste nella stessa conversazione, esegue una delle seguenti operazioni. Ogni voce rimanda a cosa fare invece:

Su un account più vecchio, nessuna di queste operazioni produce un errore a meno che la richiesta non imposti prefix_mismatch_behavior, quindi un'esecuzione senza errori con la tua chiave non dimostra se il tuo codice è interessato. Se altre persone eseguono il tuo strumento con le proprie chiavi API, quelle con account più recenti riceveranno l'errore 400 prima di te. Per vedere ciò che vedono loro senza cambiare il comportamento delle tue richieste, invia l'header beta thinking-binding-controls-2026-08-01. Su un account più vecchio, ogni risposta segnala quindi i blocchi che non superano il controllo, e il modello continua a leggerli (consulta Imposta il comportamento in caso di mancata corrispondenza e leggi input_transformations).

Controlla la tua integrazione anche se invia blocchi di ragionamento di Claude Sonnet 5.5 o Claude Haiku 5.5 provenienti da un account in una richiesta effettuata da un account diverso. Consulta I blocchi di ragionamento restano con l'account che li ha prodotti.

Cambiare modello a metà conversazione

Claude Fable 5.1 e Claude Mythos 5.1 leggono i blocchi di ragionamento prodotti l'uno dall'altro e dai modelli Claude precedenti. Nessun altro modello legge i blocchi di ragionamento di Claude Fable 5.1 o Claude Mythos 5.1.

Claude Opus 5.5 legge i blocchi di ragionamento di Claude Opus 5, dei modelli Opus, Sonnet e Haiku precedenti e, sulla Claude API e su Google Cloud, di Claude Sonnet 5.5 e Claude Haiku 5.5, ma non dei modelli Claude Fable o Claude Mythos. Sulla Claude API, Claude Fable 5.1 e Claude Mythos 5.1 leggono i blocchi di ragionamento di Claude Opus 5.5; nessun altro modello lo fa. Quindi una conversazione che passa da Claude Opus 5 a Claude Opus 5.5 mantiene il suo ragionamento, e lo stesso vale per una che passa da Claude Opus 5.5 a Claude Fable 5.1 o Claude Mythos 5.1 sulla Claude API. Una conversazione che passa da Claude Fable 5.1 o Claude Mythos 5.1 a Claude Opus 5.5, oppure da Claude Opus 5.5 a qualsiasi modello diverso da quei due, esegue i turni successivi al cambio senza il ragionamento del modello precedente. I blocchi vengono scartati, non rifiutati, come descritto più avanti in questa sezione.

Claude Sonnet 5.5 legge i blocchi di ragionamento di Claude Sonnet 5, Claude Opus 4.8, Claude Haiku 4.5 e dei modelli precedenti e, sulla Claude API e su Google Cloud, di Claude Haiku 5.5, ma non di Claude Opus 5, Claude Opus 5.5 o di qualsiasi modello Claude Fable o Claude Mythos. Sulla Claude API e su Google Cloud, Claude Opus 5.5 legge i blocchi di ragionamento di Claude Sonnet 5.5; nessun altro modello lo fa. Quindi una conversazione che passa da Claude Sonnet 5 a Claude Sonnet 5.5 mantiene il suo ragionamento, e lo stesso vale per una che passa da Claude Sonnet 5.5 a Claude Opus 5.5 sulla Claude API e su Google Cloud. Una conversazione che passa a Claude Sonnet 5.5 da Claude Opus 5, Claude Opus 5.5 o da un modello Claude Fable o Claude Mythos esegue i turni successivi al cambio senza il ragionamento del modello precedente. Lo stesso vale per qualsiasi altro passaggio da Claude Sonnet 5.5, ad esempio un fallback lato server a Claude Sonnet 5.

Claude Haiku 5.5 legge i blocchi di ragionamento di Claude Sonnet 5, Claude Opus 4.8, Claude Haiku 4.5 e dei modelli precedenti, ma non di Claude Opus 5, Claude Opus 5.5, Claude Sonnet 5.5 o di qualsiasi modello Claude Fable o Claude Mythos. Sulla Claude API e su Google Cloud, Claude Opus 5.5 e Claude Sonnet 5.5 leggono i blocchi di ragionamento di Claude Haiku 5.5; nessun altro modello lo fa. Quindi una conversazione che passa da Claude Haiku 4.5 a Claude Haiku 5.5 mantiene il suo ragionamento, così come una che passa da Claude Haiku 5.5 a Claude Opus 5.5 o Claude Sonnet 5.5 sulla Claude API e su Google Cloud. Una conversazione che passa a Claude Haiku 5.5 da Claude Opus 5, Claude Opus 5.5, Claude Sonnet 5.5 o da un modello Claude Fable o Claude Mythos esegue i turni successivi al cambio senza il ragionamento del modello precedente, e lo stesso vale per qualsiasi altro passaggio da Claude Haiku 5.5.

  • Una conversazione che passa a Claude Fable 5.1 da un modello precedente, o da Claude Opus 5.5 sulla Claude API, mantiene il suo ragionamento. I blocchi di ragionamento del modello precedente restano leggibili, quindi il modello ragiona normalmente fin dal primo turno dopo il cambio.
  • Una conversazione che passa da Claude Fable 5.1 a qualsiasi modello diverso da Claude Mythos 5.1 perde il ragionamento di Claude Fable 5.1 per quella richiesta. Questo accade quando un router invia un turno a un modello più economico, dopo un fallback per rifiuto del classificatore, oppure durante un fallback lato server. L'API rimuove i blocchi illeggibili prima che il prompt raggiunga il modello. Non vengono fatturati e non contano ai fini di input_tokens.

Continua a inviare la cronologia completa a ogni richiesta, blocchi di ragionamento inclusi, e lascia che l'API scarti ciò che il modello corrente non può leggere. L'API non modifica mai il tuo array messages, quindi i blocchi scartati restano nella tua cronologia. Quando la stessa cronologia torna a Claude Fable 5.1, i suoi blocchi sono di nuovo leggibili, insieme al ragionamento del modello precedente. Il ragionamento va perso definitivamente solo se è il tuo client a rimuovere i blocchi, ad esempio un harness che elimina il ragionamento a ogni cambio di modello o che ricostruisce la cronologia in base a ciò che ogni modello ha usato.

SystemToolsUserFable thinkingread againUserFable thinkingread again[change model → Opus]UserOpus thinkingdrops Fable thinking[back to Fable 5.1]UserFable thinkingall thinking readNo errors

Con l'header beta thinking-binding-controls-2026-08-01, la risposta elenca ogni blocco scartato in un array input_transformations di primo livello con reason: "model_binding_mismatch":

{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.3.content.0",
      "reason": "model_binding_mismatch"
    }
  ]
}

Senza l'header, lo scarto avviene in modo silenzioso. Questa voce non indica un bug nella tua integrazione, e prefix_mismatch_behavior non ha alcun effetto su di essa: un blocco che il modello corrente non può leggere viene sempre scartato.

I blocchi di ragionamento restano con l'account che li ha prodotti

I blocchi di ragionamento prodotti da Claude Sonnet 5.5 o Claude Haiku 5.5 funzionano solo nell'account che li ha prodotti, o in un account collegato a esso. Quando un altro account invia uno di questi blocchi, l'API scarta il blocco prima che il modello lo veda, e la richiesta va a buon fine. Il modello risponde senza il ragionamento contenuto nei blocchi scartati. I blocchi dei modelli precedenti non sono interessati.

Sulla Claude API e su Google Cloud, con l'header beta thinking-binding-controls-2026-08-01, la risposta elenca ogni blocco scartato in input_transformations come voce thinking_dropped con reason: "organization_binding_mismatch". Senza l'header, lo scarto avviene in modo silenzioso.

Mantenere invariato il prefisso

Su Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5, un blocco di ragionamento resta valido solo finché tutto ciò che hai inviato prima di esso rimane invariato nelle richieste successive. Il prefisso controllato ha tre parti:

  • Il prompt system di primo livello
  • L'insieme dei tools
  • Ogni message prima del blocco

Nota: con la compattazione lato server, il prefisso controllato inizia dal blocco di compattazione più recente.

I parametri della richiesta al di fuori di questi tre campi, come effort, max_tokens, output_config, tool_choice e metadata, non fanno parte del controllo del prefisso, e nemmeno i marcatori cache_control. Cosa conta come modifica contiene l'elenco completo.

I blocchi di ragionamento precedenti non fanno parte del prefisso, ma ogni blocco di ragionamento registra quale blocco di ragionamento lo ha preceduto, attraverso i turni. Puoi rimuovere blocchi di ragionamento dall'inizio della cronologia (dal più vecchio), dalla fine, oppure tutti. Ciò che non funziona è un buco: i blocchi di ragionamento che mantieni devono formare una sequenza ininterrotta di quella originale, quindi rimuoverne uno dal centro invalida i blocchi di ragionamento successivi. Una volta rimosso un blocco, lascialo fuori. Rimetterlo invalida i blocchi di ragionamento prodotti mentre era assente.

Mantieni system e tools fissi per la sessione e tratta messages come append-only. La stessa disciplina mantiene stabile il prefisso per il "prompt caching" (cache dei prompt): le modifiche che invalidano il ragionamento sono le stesse che fanno ripartire la cache.

Cosa fa l'API con un blocco non valido

Lo scegli con thinking.block_binding.prefix_mismatch_behavior:

  • "error" (predefinito): l'API rifiuta la richiesta con un errore 400 invalid_request_error che indica il primo blocco non valido.
  • "drop_block": l'API rimuove ogni blocco non valido e ogni blocco di ragionamento successivo, e la richiesta va a buon fine. I blocchi rimossi non vengono fatturati. Il modello risponde a quel turno senza usare il ragionamento dei blocchi rimossi, e la cache dei prompt riparte dal punto della modifica. La risposta elenca ogni blocco rimosso in input_transformations (nell'evento message_start durante lo streaming) con reason: "prefix_binding_mismatch".

Conta le risposte di ogni sessione il cui input_transformations contiene una voce prefix_binding_mismatch, imposta avvisi su di esse e sostituisci ogni modifica con lo schema corrispondente in Apportare modifiche senza modificare il prefisso. Nella Message Batches API, un elemento che lascia il campo non impostato non fallisce. Dove l'API applica il controllo per impostazione predefinita, rimuove invece i blocchi non validi. In quel caso, imposta esplicitamente "error" se vuoi che gli elementi del batch falliscano.

Sia il campo sia l'array input_transformations richiedono l'header beta thinking-binding-controls-2026-08-01. Imposta il comportamento in caso di mancata corrispondenza e leggi input_transformations mostra la richiesta in ogni "software development kit" (kit di sviluppo software), o SDK.

Il messaggio 400 inizia così:

messages.1.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block".

Se la richiesta non ha inviato l'header beta, il messaggio prosegue:

That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.

Di solito termina con una frase che indica cosa è cambiato, ad esempio che il prompt di sistema system o l'elenco tools differisce da quando il blocco è stato creato. Risoluzione dei problemi del ragionamento descrive cosa può indicare quella frase.

Una firma manomessa o non decifrabile è un errore diverso. Restituisce sempre un 400 (Invalid `signature` in `thinking` block senza alcuna frase sulla conversazione), e prefix_mismatch_behavior non si applica.

Costo in token di output di "drop_block"

Nei test di Anthropic su un benchmark di coding multi-turno, rimuovere i blocchi di ragionamento una volta per sessione ha aumentato i token di output del 2,5% con effort basso, del 3,9% con medio, del 4,5% con alto e del 20,1% con max. Rimuoverli a ogni turno dopo il primo ha aumentato i token di output del 4,6% con effort basso, del 9,7% con medio, del 10,3% con alto e del 67,1% con max. Queste cifre sono stime con ampi margini di errore, e l'impatto sul tuo carico di lavoro dipende dal tuo harness.

Quando Claude non può più leggere il ragionamento dei turni precedenti, lo ricrea, quindi le richieste che rimuovono blocchi di ragionamento generano più token di output e possono richiedere più tempo per rispondere. Una rimozione a ogni turno costa più di una rimozione occasionale, e quanto di più dipende dal tuo harness: quanto spesso modifica il prefisso e quanto ogni turno si basa sul ragionamento precedente.

Prima di affidarti a "drop_block", esegui valutazioni sul tuo carico di lavoro per misurare l'aumento. Se è piccolo, "drop_block" può far andare a buon fine le richieste mentre correggi la modifica. In ogni caso, correggere la modifica con uno degli schemi in Apportare modifiche senza modificare il prefisso è una soluzione migliore a lungo termine.

Gestisci l'errore nel codice

Si tratta dell'errore 400 invalid_request_error mostrato in precedenza in questa sezione. Non reinviare lo stesso corpo: fallisce allo stesso modo ogni volta. Riprova una volta con l'header beta e prefix_mismatch_behavior: "drop_block", come soluzione temporanea ("drop_block" può aumentare i token di output), e memorizza questa scelta con la sessione in modo che anche ogni richiesta successiva la invii, anche dopo un riavvio. Su Claude Sonnet 5.5 e Claude Haiku 5.5, block_binding funziona solo con thinking: {"type": "adaptive"}. Con between_tools su Claude Sonnet 5.5, o thinking: {"type": "disabled"} su Claude Haiku 5.5, mantieni la cronologia in sola aggiunta, oppure elimina i blocchi di ragionamento dal turno modificato in poi. Se non puoi inviare l'header beta, rimuovi una volta ogni blocco thinking e redacted_thinking dalla cronologia, lasciali fuori e continua. Poi correggi la modifica che ha causato la mancata corrispondenza.

Imposta il comportamento in caso di mancata corrispondenza e leggi input_transformations

L'header beta thinking-binding-controls-2026-08-01 aggiunge:

  • Un array input_transformations di primo livello in ogni risposta
  • Un oggetto block_binding nella configurazione thinking, il cui unico campo è prefix_mismatch_behavior

block_binding è accettato insieme a thinking.type: "adaptive" e thinking.type: "enabled". Su Claude Sonnet 5.5 e Claude Haiku 5.5, block_binding funziona solo con thinking: {"type": "adaptive"}. Inviarlo con between_tools su Claude Sonnet 5.5, o con thinking: {"type": "disabled"} su Claude Haiku 5.5, restituisce un errore 400. Inviarlo senza l'header beta restituisce un errore 400 il cui messaggio termina con block_binding: Extra inputs are not permitted. I modelli che non eseguono il controllo del prefisso accettano l'oggetto e segnalano solo gli scarti dovuti al controllo del modello, quindi un unico corpo di richiesta funziona con tutti i modelli. Il riferimento dell'API chiama il controllo del prefisso "conversation check" (controllo della conversazione).

La seguente richiesta sceglie di scartare anziché rifiutare. In un primo turno non c'è nulla da riprodurre, quindi input_transformations torna vuoto:

client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-fable-5-1",
    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 [])}")
Output
The greatest common divisor of 1071 and 462 is 21.
Input transformations: 0

Con l'header beta, ogni risposta di un modello con capacità di ragionamento contiene input_transformations. Ogni voce identifica un blocco di ragionamento tramite il suo path (ad esempio messages.1.content.0) e fornisce un reason. Esistono due tipi di voce:

  • thinking_dropped: l'API scarta il blocco prima che il modello lo legga, e il blocco non viene fatturato. Il reason è prefix_binding_mismatch o model_binding_mismatch (consulta Cambiare modello a metà conversazione). Il reason può anche essere organization_binding_mismatch, che significa che il blocco proviene da un altro account (consulta I blocchi di ragionamento restano con l'account che li ha prodotti).
  • thinking_mismatch_allowed: il blocco non supera il controllo del prefisso, ma l'API non applica quel controllo per questa richiesta, quindi il blocco raggiunge il modello invariato e viene fatturato. Il reason è sempre prefix_binding_mismatch. Questa voce compare solo nelle richieste in cui l'API non applica il controllo per impostazione predefinita, come quelle di un account più vecchio (consulta Quando l'API applica il controllo). Impostare prefix_mismatch_behavior su uno qualsiasi dei due valori attiva l'applicazione del controllo per la richiesta, quindi una richiesta che lo imposta non riceve mai questa voce.

L'array è vuoto quando nessun blocco è stato scartato e nessuno ha fallito il controllo del prefisso. Ignora le voci il cui type o reason non riconosci, perché controlli futuri aggiungeranno nuovi valori.

Durante lo streaming, l'array arriva nell'oggetto message dell'evento message_start. Dopo un fallback lato server a metà stream, l'evento message_delta finale lo riporta di nuovo con le voci del modello che ha servito la richiesta. In un batch di messaggi, un elemento il cui blocco non supera il controllo del prefisso con un "error" esplicito si risolve come errored. Un elemento che lascia il campo non impostato non fallisce. Dove l'API applica il controllo per impostazione predefinita, scarta invece i blocchi non validi. L'endpoint di conteggio dei token esegue lo stesso controllo del prefisso e restituisce lo stesso 400.

Quando l'API applica il controllo

L'API applica il controllo del prefisso su Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5 per i nuovi account.

  • Account creati a partire dal 31 agosto 2026, 00:00 UTC: l'API controlla le richieste a Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5 e applica "error" a meno che tu non imposti "drop_block". La stessa definizione di nuovo account si applica alla Claude API e alle piattaforme cloud.
  • Account più vecchi: l'API applica il controllo solo alle richieste che impostano prefix_mismatch_behavior. Impostare il campo attiva il controllo per una richiesta, così puoi vedere ciò che vede un nuovo account senza crearne uno. Nelle richieste che lo lasciano non impostato, l'API esegue comunque il controllo ma lascia passare i blocchi non validi al modello. Con l'header beta, la risposta elenca ciascuno di essi in input_transformations come thinking_mismatch_allowed, così puoi individuare le modifiche al prefisso senza cambiare ciò che il modello riceve.

Per scoprire a quale gruppo appartiene il tuo account, prendi una conversazione con Claude Fable 5.1 che contiene un blocco di ragionamento, modifica qualcosa prima di quel blocco e inviala a Claude Fable 5.1 senza l'header beta né il campo block_binding. Una risposta 400 che menziona l'header significa che il tuo account è soggetto al controllo per impostazione predefinita. Una risposta 200 significa che non lo è. Per conferma, invia di nuovo la stessa richiesta con l'header beta, sempre senza block_binding: la risposta elenca ogni blocco di ragionamento successivo alla tua modifica in input_transformations come thinking_mismatch_allowed.

Cosa conta come modifica

Ogni riga confronta due richieste consecutive:

Modifica tra le richiesteBlocchi di ragionamento successivi
Aggiungere messaggi alla fineValidi
Aggiungere uno strumento con defer_loading: true a cui nulla ha ancora fatto riferimentoValidi
Rimuovere blocchi thinking dall'inizio della cronologia, dalla fine, oppure rimuoverli tuttiValidi (il modello perde quel ragionamento)
Modificare qualsiasi parametro della richiesta al di fuori di system, tools e messages (effort, max_tokens, output_config, tool_choice, metadata, thinking.display e così via)Validi
Aggiungere, spostare o rimuovere marcatori cache_controlValidi
Un URL firmato a rotazione che restituisce gli stessi byteValidi
La compattazione lato server o la modifica del contesto rimuove o sostituisce contenutiValidi (il controllo confronta ciò che hai inviato, non la copia modificata dal server)
Un messaggio di sistema con ambito di turno già cancellato e lasciato al suo postoValidi
Modificare, riordinare o eliminare qualsiasi messaggio user, assistant o system precedenteNon validi, tranne quando il blocco firmato della compattazione on-demand sostituisce i messaggi che riassume, alle condizioni per il ragionamento mantenuto
Rigenerare con un valore modificato il contesto inserito nel primo messaggio utenteNon validi per ogni blocco di ragionamento
Cancellare o accorciare un tool_result precedente, ricodificare un'immagine precedente o modificare l'input di un tool_use precedenteNon validi per ogni blocco di ragionamento successivo
Aggiungere un blocco di testo a un turno utente precedente, o rimuoverne uno aggiunto l'ultima voltaNon validi
Modificare la stringa o i blocchi system di primo livelloNon validi
Aggiungere, rimuovere, rinominare o modificare uno strumento in toolsNon validi
Rimuovere un blocco thinking dal centro della cronologia e mantenere quelli successiviNon validi per ogni blocco di ragionamento successivo
Reinserire un blocco thinking rimosso in una richiesta precedenteNon validi per i blocchi di ragionamento prodotti mentre era assente
Un URL di immagine o documento che restituisce byte diversi alla richiesta successivaNon validi
Lo stesso messaggio con ambito di turno eliminato o riformulato in una richiesta successivaNon validi

Verifica se il tuo codice modifica il prefisso

Per prima cosa, confronta ciò che invii. Acquisisci i corpi delle richieste che la tua integrazione invia nel corso di alcuni turni normali, inclusa una compattazione o una modifica degli strumenti. Per ogni coppia di richieste consecutive, confronta system, tools e i messages che hanno in comune. Devono essere identici fino ai turni appena aggiunti.

Poi verifica con l'API. Aggiungi l'header beta thinking-binding-controls-2026-08-01, imposta prefix_mismatch_behavior su "drop_block" ed esegui una normale sessione multi-turno tramite la tua integrazione su . L'esempio seguente esegue due turni nel modo in cui dovrebbe farlo la tua integrazione: messages cresce soltanto, ogni turno dell'assistente viene rimandato esattamente come l'API lo ha restituito, blocchi thinking inclusi, e block_binding è impostato in ogni richiesta. Dopo ogni turno stampa il numero di blocchi thinking nella risposta e il numero di blocchi scartati:

client = anthropic.Anthropic()

user_turns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many of those are odd?",
]

# messages cresce a ogni turno: ogni turno dell'assistente viene rinviato esattamente come restituito
messages = []
for user_turn in user_turns:
    messages.append({"role": "user", "content": user_turn})
    response = client.beta.messages.create(
        model="claude-fable-5-1",
        max_tokens=16000,
        thinking={
            "type": "adaptive",
            "block_binding": {"prefix_mismatch_behavior": "drop_block"},
        },
        messages=messages,
        betas=["thinking-binding-controls-2026-08-01"],
    )
    messages.append({"role": "assistant", "content": response.content})
    thinking_blocks = sum(block.type == "thinking" for block in response.content)
    dropped = len(response.input_transformations or [])
    print(f"thinking blocks: {thinking_blocks}, dropped: {dropped}")
Output
thinking blocks: 1, dropped: 0
thinking blocks: 1, dropped: 0

Nessuno dei due turni scarta un blocco perché nulla di precedente è cambiato. Verifica che la prima risposta contenga un blocco thinking. Con il ragionamento adattivo, alcune risposte non ne hanno. Se nessuna risposta della sessione ne contiene uno, non c'è nulla da controllare e il conteggio degli scarti è 0 qualunque cosa tu modifichi, quindi esegui di nuovo l'esempio.

Registra input_transformations a ogni turno della tua integrazione. Quando l'API scarta un blocco, la voce ha il seguente aspetto:

{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.1.content.0",
      "reason": "prefix_binding_mismatch"
    }
  ]
}
  • Vuoto a ogni turno di una sessione che contiene blocchi thinking: la tua integrazione mantiene intatto il prefisso.
  • reason: "prefix_binding_mismatch": qualcosa prima del blocco in path è cambiato rispetto alla richiesta precedente. Confronta system, tools e messages fino a quel turno per individuarlo, oppure reinvia la richiesta con "error": il 400 di solito termina con una frase che indica cosa è cambiato. Poi trova la sostituzione corrispondente in Apportare modifiche senza modificare il prefisso.
  • reason: "model_binding_mismatch": la conversazione è passata a un modello che non può leggere i blocchi del modello precedente. Non si tratta di una modifica al prefisso. Consulta Cambiare modello a metà conversazione.
  • reason: "organization_binding_mismatch": il blocco proviene da un altro account. Consulta I blocchi di ragionamento restano con l'account che li ha prodotti.

Per provocare volutamente un errore, invia un terzo turno dall'esempio precedente e aggiungi un prompt system solo a quella richiesta, in modo che differisca dalle prime due richieste, che non ne avevano. Con "drop_block", il conteggio degli scarti non è più 0: la risposta contiene una voce per ogni blocco di ragionamento nella cronologia, ciascuna con reason: "prefix_binding_mismatch". Con "error", la richiesta restituisce il 400 descritto in Cosa fa l'API con un blocco non valido, e la sua ultima frase menziona il prompt system. Nelle schede cURL e CLI, rimuovi il filtro jq per vedere il corpo dell'errore. Se il conteggio è ancora 0, non c'era nulla da controllare: verifica che il modello sia , che la richiesta imposti block_binding, che la cronologia inviata contenga blocchi thinking e che le prime due richieste non avessero un prompt system.

Due semplici turni raramente mostrano il problema. Esegui una sessione per ciascuno dei seguenti casi, con "error" impostato in modo che una regressione faccia fallire la tua CI:

  • La prima compattazione o riduzione lato client
  • Uno strumento, un plugin o un server MCP che si connette dopo il primo turno
  • Un cambio di modalità o di istruzioni
  • Un lungo ciclo di strumenti, se aggiungi promemoria o accorci vecchi risultati degli strumenti
  • Un passaggio a un altro modello e ritorno
  • Un salvataggio, un riavvio e una ripresa in una data successiva

Su un account più vecchio, puoi anche monitorare il traffico di produzione senza attivare l'applicazione del controllo: invia l'header beta, ometti block_binding e registra input_transformations. Inviare solo l'header non cambia ciò che il modello riceve. Ogni blocco di ragionamento che segue il contenuto modificato non supera il controllo e riceve una propria voce thinking_mismatch_allowed, con gli stessi campi path e reason di una voce thinking_dropped. I blocchi precedenti alla modifica continuano a superarlo. Una modifica a system o tools precede ogni blocco, quindi fa fallire ogni blocco di ragionamento della richiesta. Una voce ha questo aspetto:

{
  "input_transformations": [
    {
      "type": "thinking_mismatch_allowed",
      "path": "messages.1.content.0",
      "reason": "prefix_binding_mismatch"
    }
  ]
}

Esegui l'esempio seguente da un account più vecchio, perché un account più recente rifiuta la sua terza richiesta con il 400. Invia l'header senza block_binding ed estende la sessione precedente con una terza richiesta che aggiunge un prompt di sistema, modificando volutamente il prefisso. Dopo ogni turno stampa il numero di blocchi thinking e di blocchi segnalati:

client = anthropic.Anthropic()

user_turns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many of those are odd?",
    "And how many of the odd ones are below 100?",
]

# messages cresce a ogni turno: ogni turno dell'assistente viene rinviato esattamente come restituito
messages = []
for turn, user_turn in enumerate(user_turns, start=1):
    messages.append({"role": "user", "content": user_turn})
    response = client.beta.messages.create(
        model="claude-fable-5-1",
        max_tokens=16000,
        thinking={"type": "adaptive"},
        # Solo l'ultima richiesta aggiunge un prompt di sistema, che modifica il prefisso di proposito
        system="Answer briefly." if turn == len(user_turns) else anthropic.omit,
        messages=messages,
        betas=["thinking-binding-controls-2026-08-01"],
    )
    messages.append({"role": "assistant", "content": response.content})
    thinking_blocks = sum(block.type == "thinking" for block in response.content)
    flagged = sum(
        transformation.type == "thinking_mismatch_allowed"
        for transformation in response.input_transformations or []
    )
    print(f"thinking blocks: {thinking_blocks}, flagged: {flagged}")
Output
thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 0
thinking blocks: 1, flagged: 2

La terza risposta segnala ogni blocco di ragionamento dei turni precedenti, uno per turno in questa esecuzione, perché il nuovo prompt di sistema li precede tutti. Il modello li ha comunque letti.

Gestisci queste voci come faresti con gli scarti prefix_binding_mismatch. La modifica si trova prima del primo blocco elencato: confronta system, tools e messages fino al path di quel blocco con la richiesta precedente per individuarla, poi sostituiscila con lo schema corrispondente in Apportare modifiche senza modificare il prefisso. Su un nuovo account, o in qualsiasi richiesta che imposta prefix_mismatch_behavior, l'API invece rifiuta la richiesta o scarta i blocchi non validi. Le voci rappresentano un limite inferiore di ciò che l'applicazione del controllo rimuoverebbe: con "drop_block", un blocco non valido si porta dietro anche il resto dei blocchi di ragionamento di quel turno, e rimuovere un blocco può far fallire anche il successivo. Quando l'API si limita a registrare il controllo, giudica ogni blocco singolarmente ed elenca un blocco solo se quel blocco fallisce.

Apportare modifiche senza modificare il prefisso

Ogni modifica comune al prefisso ha una sostituzione che fornisce al modello le stesse informazioni e lascia invariati i byte precedenti, così il ragionamento successivo resta valido. Trova nella prima colonna la modifica che il tuo codice esegue oggi:

Invece diUsaHeader beta
Ricostruire il prompt system di primo livelloUn messaggio di sistema a metà conversazioneNessuno
Rigenerare il contesto nel primo messaggio utente (ambiente, data, memoria, istruzioni di progetto) a ogni richiestaGeneralo una volta e reinvialo invariato. Quando qualcosa cambia, inserisci la nuova versione nel turno più recenteNessuno
Cancellare o accorciare sul posto vecchi contenuti tool_result, o ricodificare vecchie immaginiAccorcia un risultato dello strumento o riduci la risoluzione di un'immagine prima di inviarli per la prima volta, non dopo. Per cancellare vecchi risultati in seguito, riduci il contesto sul server con clear_tool_uses_20250919context-management-2025-06-27
Inserire un promemoria ed eliminarlo alla richiesta successivaUn messaggio di sistema con ambito di turno (clear_at: "next_user_message")mid-conversation-system-clear-at-2026-08-21
Aggiungere o rimuovere voci in toolsBlocchi tool_addition e tool_removalinline-tools-2026-09-15 (aggiungi mcp-client-2026-09-15 quando lo strumento proviene da un server MCP connesso tramite il connettore MCP), oppure il più vecchio mid-conversation-tool-changes-2026-07-01, che funziona sulla Claude API, su Amazon Bedrock e su Google Cloud
Modificare output_config.effort di primo livello (fa ripartire la cache, non influisce sul ragionamento)Un output_config per messaggiomid-conversation-output-config-2026-07-01
Scartare o riassumere vecchi turni sul clientLa compattazione su richiesta per mantenere i turni recenti con il loro ragionamento, altre forme di compattazione o modifica del contesto lato server, oppure una compattazione lato client che non mantiene ragionamento obsoletocompact-2026-09-04
Un URL di immagine o documento i cui byte cambiano tra le richiesteUn file_id dalla Files API, oppure base64Nessuno

Tutte queste soluzioni presuppongono che tu rimandi i turni dell'assistente esattamente come restituiti. I messaggi di sistema a metà conversazione, i messaggi di sistema con ambito di turno e le modifiche agli strumenti non sono disponibili su tutti i modelli: Messaggi di sistema e modifiche agli strumenti a metà conversazione elenca i modelli che li accettano. Se il tuo codice serve più modelli, continua a modificare il prompt system di primo livello per i modelli che non li accettano.

Per usare più beta in una sola richiesta sulla Claude API, combina i loro nomi in un unico header anthropic-beta:

anthropic-beta: thinking-binding-controls-2026-08-01,mid-conversation-system-clear-at-2026-08-21,inline-tools-2026-09-15

Le altre piattaforme che offrono queste beta usano gli stessi nomi. Per inviarle lì, consulta Funzionalità beta su altre piattaforme.

Rimanda i turni dell'assistente esattamente come restituiti

Memorizza l'array content di ogni risposta e rimandalo invariato come turno dell'assistente: ogni tipo di blocco, nell'ordine ricevuto, inclusi i blocchi thinking il cui campo thinking è vuoto. Un serializzatore che scarta tipi di blocco sconosciuti, scarta campi vuoti o riordina i blocchi modifica il prefisso per ogni turno successivo.

Su Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5, il campo thinking è vuoto per impostazione predefinita e la signature contiene il ragionamento, quindi un serializzatore che salta i blocchi vuoti rimuove il ragionamento. Se li rimuove tutti, nulla fallisce e il modello perde il suo ragionamento precedente a ogni turno. Se analizzi lo stream autonomamente, mantieni il blocco anche quando non arriva alcun testo di ragionamento: si apre, riceve la sua signature in un evento signature_delta e si chiude. Un blocco rimandato con una signature vuota fallisce.

Aggiungi istruzioni con un messaggio di sistema a metà conversazione

Alcuni harness ricostruiscono il prompt di sistema system di primo livello a ogni richiesta per includere l'ora corrente, un budget di token, un flag di modalità o contesto di progetto appena scoperto. Questo invalida ogni blocco di ragionamento della conversazione. Invece, congela system all'inizio della sessione. Quando qualcosa cambia, aggiungi un messaggio role: "system" nel punto di messages in cui il cambiamento diventa vero:

{
  "role": "system",
  "content": "The user switched the workspace to read-only mode. Do not write files until told otherwise."
}

Il modello tratta questo messaggio con l'autorità di un prompt di sistema, e tutto ciò che lo precede resta invariato. In un ciclo di strumenti, posiziona il messaggio dopo il messaggio utente con il tool_result, mai tra un tool_use dell'assistente e il relativo tool_result (consulta Limitazioni). Una volta inviato, il messaggio fa parte del prefisso per il ragionamento successivo: lascialo al suo posto nelle richieste successive.

Inserisci il contesto che cambia nel turno più recente

Alcuni harness inseriscono un blocco di ambiente nel primo messaggio utente (directory di lavoro, branch, data, memoria, istruzioni di progetto) e lo rigenerano a ogni richiesta. Quando un valore cambia, messages[0] cambia, e ogni blocco di ragionamento della conversazione non è più valido. Genera quel blocco una volta e invialo di nuovo così com'era. Quando un valore cambia, segnalalo nel turno più recente: aggiungi un blocco di testo al messaggio utente che stai per inviare, oppure aggiungi un messaggio di sistema a metà conversazione se il cambiamento proviene da te in qualità di operatore.

{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "Environment update: the current branch is now release-2."
    },
    { "type": "text", "text": "Run the tests again." }
  ]
}

Una volta inviato, quel blocco di testo fa parte del prefisso per il ragionamento successivo: lascialo al suo posto nelle richieste successive.

Invia i promemoria per turno come messaggi di sistema con ambito di turno

Una modifica comune del prefisso è il promemoria per turno: una riga come "esegui insieme le letture indipendenti" o "non aggiorni l'utente da un po'" che il tuo codice aggiunge dopo ogni gruppo di risultati degli strumenti. Per evitare che i promemoria si accumulino, invia ogni promemoria come messaggio di sistema a metà conversazione con clear_at: "next_user_message", posizionato dopo il messaggio utente con il tool_result. clear_at richiede l'header beta mid-conversation-system-clear-at-2026-08-21. Il seguente array messages è la richiesta dopo due chiamate agli strumenti e i relativi risultati. messages[3] è il promemoria della richiesta precedente, lasciato al suo posto, e messages[6] è la copia di questa richiesta:

[
  { "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": "tests/test_auth.py" }
      }
    ]
  },
  {
    "role": "user",
    "content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
  },
  {
    "role": "system",
    "clear_at": "next_user_message",
    "content": "Request every independent read in one turn."
  },
  {
    "role": "assistant",
    "content": [
      { "type": "thinking", "thinking": "", "signature": "..." },
      {
        "type": "tool_use",
        "id": "toolu_02",
        "name": "read_file",
        "input": { "path": "src/auth.py" }
      }
    ]
  },
  {
    "role": "user",
    "content": [{ "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." }]
  },
  {
    "role": "system",
    "clear_at": "next_user_message",
    "content": "Request every independent read in one turn."
  }
]

Un messaggio utente che contiene solo blocchi tool_result conta come "next user message" (messaggio utente successivo), quindi messages[3] è già cancellato. Non aggiunge nulla a ciò che il modello vede e non costa token di input, ma poiché è ancora nell'array, il ragionamento in messages[4] resta valido. messages[6] è la copia che il modello vede in questo turno. Nelle richieste successive, mantieni entrambi dove sono e aggiungi una nuova copia dopo il successivo messaggio tool_result.

Aggiungi o rimuovi strumenti con tool_addition e tool_removal

Modificare l'array tools a metà sessione invalida i "thinking blocks" (blocchi di ragionamento) preservati. Lascia l'array così come lo hai inviato la prima volta e cambia gli strumenti che il modello può usare aggiungendo un messaggio role: "system" che contiene blocchi tool_addition o tool_removal. Queste sono modifiche agli strumenti a metà conversazione e richiedono l'header beta inline-tools-2026-09-15, disponibile sulla Claude API. Il vecchio header mid-conversation-tool-changes-2026-07-01 funziona ancora per le modifiche che indicano uno strumento per riferimento, sulla Claude API, su Amazon Bedrock e su Google Cloud.

Hai due modi per usare questi blocchi:

  • Dichiara ogni strumento in anticipo. Inserisci in tools alla prima richiesta ogni strumento di cui la sessione potrebbe aver bisogno, con defer_loading: true su quelli che il modello non deve ancora vedere. Poi attiva e disattiva gli strumenti con blocchi tool_addition e tool_removal che li indicano per nome.
  • Parti da un'istantanea e aggiungi strumenti strada facendo. Inserisci in tools alla prima richiesta gli strumenti che conosci. Quando arriva un nuovo strumento, definiscilo all'interno di un blocco tool_addition invece di modificare tools.

In entrambi i casi, tools non cambia mai, quindi il ragionamento precedente rimane valido e la cache dei prompt continua a trovare corrispondenze, con l'unica eccezione indicata più avanti in questa sezione.

Ad esempio, per ritirare uno strumento pericoloso dopo un cambio di modalità:

{
  "role": "system",
  "content": [
    { "type": "tool_removal", "tool": { "type": "tool_reference", "name": "delete_branch" } },
    { "type": "text", "text": "Branch deletion is disabled for the rest of this session." }
  ]
}

Per attivare uno strumento dichiarato con defer_loading: true, aggiungi un blocco tool_addition che lo indica per nome:

{
  "role": "system",
  "content": [
    { "type": "tool_addition", "tool": { "type": "tool_reference", "name": "deploy" } },
    { "type": "text", "text": "Authentication succeeded. Deployment is now available." }
  ]
}

A volte non puoi dichiarare uno strumento in anticipo perché non ne conosci ancora lo schema: uno strumento che la tua applicazione scopre in fase di esecuzione, o un server MCP che si connette dopo il primo turno. Definiscilo all'interno del blocco tool_addition invece di toccare tools. Con inline-tools-2026-09-15, il tool del blocco può essere {"type": "tool_definition", "definition": {...}}, contenente la stessa voce che avresti inserito in 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"]
          }
        }
      }
    }
  ]
}

Il nuovo strumento arriva in messages, tools non cambia mai e il ragionamento precedente resta valido. Mantieni in tools almeno uno strumento senza defer_loading: true: se tutti gli strumenti lì sono differiti, il primo strumento che definisci in questo modo costa un "cache miss" (mancato riscontro nella cache) completo della cache dei prompt.

Se l'API si connette al server MCP per tuo conto tramite il connettore MCP, invia anche mcp-client-2026-09-15. Copre tutto ciò che fa mcp-client-2025-11-20, quindi invialo al posto di quello. Il definition del blocco può quindi essere un mcp_toolset per un server elencato in mcp_servers. Quando l'API deve recuperare l'elenco degli strumenti di un server, la risposta inizia con un blocco mcp_tool_listing per quel server. Rimandalo invariato insieme al resto del turno dell'assistente, e continua a inviare mcp-client-2026-09-15 in ogni richiesta successiva che lo contiene. Il blocco vincola il toolset a quell'elenco, quindi l'API non contatta di nuovo il server per ottenerlo. Queste funzionalità del connettore MCP sono disponibili sulla Claude API.

Con il solo header precedente, puoi comunque aggiungere a tools uno strumento scoperto a metà sessione con defer_loading: true, e poi offrirlo con un blocco tool_addition. È sicuro perché il controllo del prefisso ignora uno strumento differito finché un blocco tool_addition non vi fa riferimento. Aggiungere uno strumento senza defer_loading: true modifica il prefisso e invalida il ragionamento precedente.

I messaggi role: "system" che contengono questi blocchi entrano a far parte del prefisso per il ragionamento successivo. Lasciali al loro posto nelle richieste successive.

Cambia l'effort con un output_config per messaggio

Cambiare output_config.effort di primo livello tra una richiesta e l'altra non invalida il ragionamento, perché l'effort non fa parte del prefisso. Cambiare l'effort di primo livello fa però ripartire la cache dei prompt. Dove il modello e la piattaforma supportano l'effort per messaggio, usalo al suo posto: accoda un messaggio role: "system" con content vuoto e il nuovo livello. Richiede l'header beta mid-conversation-output-config-2026-07-01. Su Claude Haiku 5.5, l'effort per messaggio è disponibile sulla Claude API e su Google Cloud e richiede il ragionamento adattivo.

{ "role": "system", "content": [], "output_config": { "effort": "low" } }

Il momento in cui il nuovo livello entra in vigore dipende da dove inserisci il messaggio. Subito dopo un messaggio user con un nuovo input, si applica a partire dalla risposta di Claude a quel messaggio. In qualsiasi altra posizione, ad esempio dopo un messaggio assistant o dopo un messaggio user che contiene solo blocchi tool_result, si applica a partire dal successivo messaggio user con un nuovo input, quindi un ciclo di strumenti già in corso mantiene il livello attuale fino ad allora. Una volta inviato, il messaggio fa parte di messages e quindi del prefisso per il ragionamento successivo: lascialo al suo posto nelle richieste successive e accodane un altro per cambiare di nuovo l'effort.

Riduci il contesto sul server

Un'altra modifica comune del prefisso è il "trimming" (riduzione) lato client: eliminare o riassumere i turni più vecchi mantenendo alla lettera quelli recenti. I blocchi di ragionamento dei turni mantenuti sono stati prodotti quando la cronologia rimossa era ancora presente, quindi non superano il controllo. Gli equivalenti lato server non contano come modifiche, perché il controllo confronta la conversazione così come l'hai inviata:

  • La compattazione su richiesta (beta) restituisce il riepilogo da una richiesta separata, che può essere eseguita in background, e tu invii il blocco restituito al posto dei messaggi che riassume. Il controllo accetta questa sostituzione, quindi i turni che mantieni possono restare validi con il loro ragionamento, alle condizioni per il ragionamento mantenuto. Richiedi un riepilogo mostra la richiesta e indica l'header beta necessario.
  • La compattazione a una soglia di token riassume i turni più vecchi in un blocco di compattazione quando il contesto si avvicina a una soglia da te impostata, e il prefisso controllato riparte da quel blocco. Il suo parametro instructions accetta un tuo prompt di riepilogo, ad esempio "preserva ogni ticker, dimensione di posizione e ipotesi dichiarata".
  • La modifica del contesto cancella i vecchi risultati degli strumenti o i vecchi blocchi di ragionamento in base a regole, a partire dai più vecchi. Le strategie sono clear_tool_uses_20250919 e clear_thinking_20251015.

Compattare sul client

Puoi comunque compattare sul client. Se scrivi tu il riepilogo, non rimandare un blocco di ragionamento prodotto prima della riscrittura. Se lo scrive l'API con la compattazione su richiesta, Condizioni affinché il ragionamento mantenuto resti valido elenca quando il ragionamento mantenuto resta valido.

Quando la conversazione diventa troppo lunga, riassumi l'intera sessione in un unico messaggio utente e invia solo quel messaggio più l'istruzione successiva. Nulla di precedente viene riprodotto, quindi non rimane alcun ragionamento che possa non superare il controllo, e il modello ragiona da capo a partire dal riepilogo.

Request 4full historyuser 1asst 1thinkinguser 2asst 2thinkinguser 3asst 3thinkinguser 4compact on the clientRequest 5after compactionuser: summary of turns 1–4 + next instructionno earlier turns replayed, so no thinking to check
[
  {
    "role": "user",
    "content": "<summary of the session so far>\n\n<the next instruction>"
  }
]

I modelli Claude sono addestrati su attività a lungo orizzonte con questo schema, che offre buone prestazioni per la maggior parte dei carichi di lavoro.

Compattazione keep-tail

La "keep-tail compaction" (compattazione con mantenimento della coda) riassume i turni più vecchi e mantiene alla lettera i turni più recenti, così il modello vede ancora parola per parola gli ultimi scambi. Se scrivi tu il riepilogo, viola la regola: i turni dell'assistente mantenuti contengono ancora blocchi di ragionamento prodotti quando erano preceduti dai turni originali, non dal riepilogo. Quei blocchi non superano il controllo.

Per mantenere quel ragionamento, fai scrivere il riepilogo all'API con la compattazione su richiesta. Compattazione che mantiene i turni recenti mostra come fare, e Condizioni affinché il ragionamento mantenuto rimanga valido elenca quando il ragionamento mantenuto rimane valido.

Il resto di questa sezione riguarda un riepilogo scritto da te.

Beforefull historyuser 1asst 1thinkinguser 2asst 2thinkinguser 3asst 3thinkinguser 4asst 4thinkinguser 5Keep-tail, as writtensummary + recent turns verbatimsummary of 1–2user 3asst 3thinking ✗user 4asst 4thinking ✗user 5asst 3 and asst 4 thinking was produced after user 1 … asst 2, not after the summary, so it failsKeep-tail with drop_blockAPI drops the blockssummary of 1–2user 3asst 3droppeduser 4asst 4droppeduser 5The request succeeds. The model reads asst 3 and 4 without their thinking. input_transformations lists both blocks.

Soluzione: mantieni i turni esattamente come sono e invia prefix_mismatch_behavior: "drop_block". L'API elimina i blocchi di ragionamento obsoleti, il modello legge i blocchi text e tool_use dei turni mantenuti e la richiesta ha esito positivo.

Passa la cronologia compattata come messages e imposta block_binding nella configurazione thinking. Nell'esempio seguente, compacted_messages è l'array prodotto dal tuo passaggio di compattazione: il messaggio di riepilogo seguito dai turni mantenuti esattamente come li ha restituiti l'API, blocchi thinking inclusi:

client = anthropic.Anthropic()

# compacted_messages: il messaggio di riepilogo, seguito dai turni mantenuti così come restituiti
response = client.beta.messages.create(
    model="claude-fable-5-1",
    max_tokens=16000,
    thinking={
        "type": "adaptive",
        "block_binding": {"prefix_mismatch_behavior": "drop_block"},
    },
    messages=compacted_messages,
    betas=["thinking-binding-controls-2026-08-01"],
)

print(response.input_transformations)

La risposta contiene come di consueto il nuovo turno dell'assistente, più una voce input_transformations per ogni blocco eliminato. Per la cronologia nel diagramma, si tratta del ragionamento sui turni 3 e 4 dell'assistente:

{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.2.content.0",
      "reason": "prefix_binding_mismatch"
    },
    {
      "type": "thinking_dropped",
      "path": "messages.4.content.0",
      "reason": "prefix_binding_mismatch"
    }
  ]
}

Continua a inviare "drop_block" nelle richieste successive finché quei due turni rimangono nella cronologia. Il ragionamento che il modello produce da questa richiesta in poi segue il riepilogo e rimane valido. Se preferisci non dipendere dall'header beta, l'alternativa è rimuovere tu stesso i blocchi thinking e redacted_thinking dai turni dell'assistente mantenuti quando costruisci la cronologia compattata.

Compattazione in background (asincrona)

La compattazione in background costruisce il riepilogo al di fuori del percorso critico mentre la conversazione prosegue, poi lo sostituisce qualche richiesta dopo. Per mantenere il ragionamento prodotto nel frattempo, fai scrivere il riepilogo all'API con la compattazione su richiesta: Compattazione in background descrive i passaggi, e quel ragionamento resta valido alle stesse condizioni per il ragionamento mantenuto dei turni recenti mantenuti.

Un riepilogo che costruisci tu stesso viola la regola allo stesso modo della compattazione keep-tail, ma con un ritardo: ogni turno dell'assistente prodotto mentre il riepilogo veniva costruito contiene thinking antecedente alla sostituzione, e tutto questo thinking non supera il controllo nel momento in cui il riepilogo viene inserito. Se ne usi uno, tratta la sostituzione come nella compattazione keep-tail e invia "drop_block" dalla sostituzione in poi, oppure compatta in modo sincrono.

Schemi che non funzionano con il ragionamento preservato

  • Tagliare turni dal mezzo. La rimozione di singoli turni invalida ogni blocco di thinking successivo, e nessuno schema di compattazione lo evita. Se stavi tagliando un turno per modificare un'istruzione, aggiungi invece un messaggio di sistema a metà conversazione. Per rimuovere selettivamente vecchi risultati degli strumenti o vecchio thinking, usa il "context editing" (modifica del contesto) lato server: consulta modifica del contesto.
  • Compattare nel mezzo di un round di strumenti. Non compattare tra il tool_use di un turno dell'assistente e il tool_result che gli risponde. Rinvia quel turno dell'assistente con il suo thinking intatto, così il modello completa il round con il suo ragionamento. Consulta Preservare i blocchi di ragionamento.

Fai riferimento ai file tramite ID, non tramite un URL il cui contenuto cambia

Per un blocco image o document con una sorgente url, il controllo riguarda i byte recuperati, non la stringa dell'URL. Un URL il cui contenuto cambia invalida il thinking successivo: ad esempio un endpoint "ultimo screenshot", o un documento che qualcuno modifica tra un turno e l'altro. Un URL firmato a rotazione per lo stesso file non lo invalida. Per i contenuti a cui fai riferimento in più turni, caricali una volta con la Files API e usa il file_id, oppure inviali in base64.

Librerie, proxy e gateway

Una libreria, un proxy o un gateway si trova tra la cronologia di qualcun altro e l'API, quindi le sue riscritture contano come modifiche, e i suoi utenti non possono vederle né correggerle.

  • Inoltra ciò che non riconosci. Inoltra invariati i valori anthropic-beta e thinking.block_binding del chiamante, e restituiscigli input_transformations. Uno schema di opzioni che rifiuta le chiavi sconosciute impedisce ai tuoi utenti di scegliere "drop_block".
  • Lascia un messaggio role: "system" dove il chiamante lo ha messo. Spostarlo nel campo system di primo livello modifica system in quella richiesta e invalida ogni blocco di thinking nella conversazione.
  • Per disattivare l'uso degli strumenti per una richiesta, invia tool_choice: {"type": "none"}. Non rimuovere tools.
  • Non nascondere il 400. Se il tuo codice lo intercetta, rimuove il thinking e riprova per conto del chiamante, registra che lo ha fatto: la cronologia del chiamante risulta comunque modificata, e il modello perde il suo ragionamento precedente in ogni richiesta successiva.

Domande frequenti

Passaggi successivi

Diagnostica e correggi i fallimenti più comuni del ragionamento: errori 400 di configurazione, blocchi di ragionamento vuoti o mancanti, arresti per max_tokens e cache miss.

Modifica le istruzioni di sistema o la disponibilità degli strumenti a metà di una conversazione senza invalidare il prefisso in cache che le precede.

Compattazione del contesto lato server per gestire conversazioni lunghe che si avvicinano ai limiti della finestra di contesto.

Metti in cache i prefissi dei prompt con cache_control per ridurre costi e latenza, usando la cache automatica o breakpoint espliciti con TTL di 5 minuti o 1 ora.

Was this page helpful?