Claude Platform Docs
MessaggiGestione del contesto

Messaggi di sistema e modifiche agli strumenti a metà conversazione

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

Le istruzioni di sistema si trovano normalmente nel campo di primo livello system, prima di ogni messaggio della conversazione. Questa posizione è ottima per il "prompt caching" (cache dei prompt): il "system prompt" (prompt di sistema) fa parte del prefisso stabile, quindi i turni successivi trovano una corrispondenza nella cache. È invece poco adatta alle istruzioni di cui scopri di aver bisogno solo a metà di una sessione. Modificare il campo di primo livello system cambia infatti l'inizio stesso del prompt e invalida la cache per tutto ciò che segue.

I messaggi di sistema a metà conversazione colmano questa lacuna. Invece di modificare il campo di primo livello system, aggiungi un messaggio {"role": "system"} nel punto della conversazione in cui la nuova istruzione diventa rilevante. Il prefisso memorizzato nella cache resta invariato, quindi la richiesta successiva lo legge ancora dalla cache. La nuova istruzione viene comunque applicata come istruzione di sistema e non come normale testo dell'utente.

Modifiche agli strumenti a metà conversazione

L'array tools si trova ancora prima del campo system di primo livello nel prefisso della richiesta sottoposto a hash, quindi modificarlo invalida la cache dei prompt per l'intera conversazione. Le modifiche agli strumenti a metà conversazione sono l'equivalente, per gli strumenti, dei messaggi di sistema a metà conversazione. Invece di fissare l'elenco degli strumenti per tutta la durata della conversazione, cambi quali strumenti vengono offerti al modello tra un turno e l'altro: dichiara l'intero set di strumenti in tools fin dall'inizio, poi usa i blocchi tool_addition e tool_removal per offrire uno strumento al modello, o ritirarlo, da un punto specifico della conversazione in poi. L'array tools stesso non cambia mai, quindi il prefisso memorizzato nella cache rimane intatto. Le modifiche agli strumenti a metà conversazione sono in beta e usano l'header beta inline-tools-2026-09-15 sulla Claude API.

tool_addition e tool_removal sono blocchi di contenuto nell'array content di un messaggio role: "system" e possono essere combinati con blocchi text nello stesso messaggio. Il messaggio segue le regole di posizionamento di qualsiasi messaggio di sistema a metà conversazione, con una restrizione aggiuntiva dopo un turno in pausa (vedi Limitazioni), e la modifica si applica da quel punto della conversazione in poi. Il campo tool di ogni blocco fa riferimento a uno strumento anziché definirlo: {"type": "tool_reference", "name": "..."} nomina uno strumento dichiarato nell'array tools della richiesta, e gli strumenti del connettore MCP possono essere referenziati singolarmente con mcp_tool_reference (server_name e name) oppure come intero set di strumenti con mcp_toolset_reference (server_name). Fare riferimento a un nome non dichiarato in tools restituisce un errore 400 (sulla Claude API, con error.details.error_code impostato su tool_reference_unresolved). Un blocco tool_addition può invece contenere la definizione completa dello strumento, cosa che l'header mid-conversation-tool-changes-2026-07-01 non supporta.

Ogni strumento dichiarato in tools viene offerto al modello dall'inizio della conversazione, a meno che non sia dichiarato con defer_loading: true, che lo mantiene nascosto finché un blocco tool_addition non lo rende disponibile. tool_addition serve anche a offrire di nuovo uno strumento che un precedente tool_removal ha ritirato.

La seguente richiesta dichiara get_weather in tools, poi lo ritira dopo il primo turno dell'utente con un blocco tool_removal. La richiesta invia l'header beta inline-tools-2026-09-15.

client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    betas=["inline-tools-2026-09-15"],
    # L'intero set di strumenti è dichiarato all'inizio e non cambia mai, quindi il
    # prefisso in cache resta intatto.
    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.",
        },
        # Ritira get_weather da questo punto in poi. Il blocco fa riferimento
        # allo strumento per nome invece di modificare `tools`, così i turni precedenti restano
        # identici byte per byte e la cache viene comunque colpita.
        {
            "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)

Definire strumenti in un messaggio (beta)

Con l'header beta inline-tools-2026-09-15, un blocco tool_addition può definire uno strumento per valore, contenendone la definizione completa, invece di indicarlo per riferimento. Questo ti consente di introdurre uno strumento sconosciuto all'inizio della conversazione, o il cui schema cambia in seguito, aggiungendo un messaggio role: "system". L'array tools e ogni messaggio precedente rimangono esattamente come inviati, quindi la cache dei prompt trova ancora corrispondenza e solo il messaggio aggiunto viene elaborato come nuovo input. L'unica eccezione, un array tools senza alcuno strumento non differito, è trattata nelle regole seguenti. L'header copre anche l'aggiunta e la rimozione di strumenti per riferimento, quindi non è necessario inviare anche mid-conversation-tool-changes-2026-07-01.

Racchiudi la definizione in un oggetto tool di tipo tool_definition. La definition è una voce di tools, come uno strumento personalizzato o uno strumento client o server definito da Anthropic, con la sua consueta configurazione, inclusi cache_control e defer_loading. Durante la beta, alcuni tipi di strumenti (tra cui lo strumento computer use) non possono ancora essere definiti in un messaggio e restituiscono un errore 400 che lo indica; dichiarali in tools e aggiungili per riferimento. Ad esempio, per definire uno strumento personalizzato a metà conversazione:

{
  "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"]
          }
        }
      }
    }
  ]
}

Da quella posizione in poi, il modello può chiamare lo strumento nello stesso modo in cui chiama uno strumento dichiarato in tools. Inviare di nuovo una definizione identica non cambia nulla, quindi un client può reinviarla in sicurezza, ad esempio in caso di nuovo tentativo.

La seguente richiesta mantiene get_weather in tools e definisce db_query dopo il primo turno dell'utente:

client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    betas=["inline-tools-2026-09-15"],
    # Mantieni almeno uno strumento non differito in `tools`, così uno strumento definito
    # in seguito non modifica l'inizio del prompt renderizzato.
    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?"},
        # Da qui in poi definisci db_query per valore. `tools` e i
        # messaggi precedenti restano identici a quelli inviati, quindi la cache viene comunque colpita.
        {
            "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)

Il content della risposta include un blocco tool_use per il nuovo strumento, ad esempio:

{
  "type": "tool_use",
  "id": "toolu_01A09q90qw90lq917835lq9",
  "name": "db_query",
  "input": {
    "sql": "SELECT COUNT(*) FROM orders WHERE shipped_at::date = CURRENT_DATE - 1"
  }
}

Per cambiare lo schema di uno strumento, o per passare a una versione più recente di uno strumento server, invia una definizione diversa con lo stesso nome. La nuova definizione sostituisce quella precedente da quella posizione in poi. Una definizione che riutilizza il nome di uno strumento di tipo diverso restituisce un errore 400 con error.details.error_code impostato su tool_name_conflict. Una versione più recente dello stesso strumento non conta come tipo diverso. tool_removal accetta comunque un riferimento, e uno strumento rimosso può essere definito od offerto di nuovo in seguito.

Alcune regole derivano dal punto in cui viene resa la definizione:

  • Dichiara in anticipo ciò che conosci. Uno strumento che conosci al momento della prima richiesta va in tools, con defer_loading: true e un successivo riferimento tool_addition se il modello non deve ancora vederlo. Definisci per valore solo ciò che è sconosciuto alla prima richiesta o che cambia in seguito.
  • Mantieni almeno uno strumento non differito in tools. Una conversazione il cui array tools non contiene alcuno strumento non differito viene accettata, ma il primo strumento che definisce per valore cambia l'inizio del prompt reso, il che comporta un "cache miss" (mancata corrispondenza nella cache) completo su quella richiesta. Uno strumento di ricerca degli strumenti conta come non differito.
  • I tipi di strumenti con data mantengono i propri header beta. Se uno strumento server che definisci per valore richiede un proprio header beta, invia quell'header in ogni richiesta successiva della conversazione.
  • cache_control va sul blocco o nella definizione, non in entrambi, e conta ai fini del limite di "breakpoint" (punti di interruzione) della richiesta. Una definizione differita non può contenere cache_control.

Una richiesta restituisce un errore 400 con error.details.error_code impostato su available_tools_limit_exceeded quando viene superato uno qualsiasi di questi limiti:

  • Più di 10.000 strumenti differiti sono disponibili dopo un qualsiasi messaggio.
  • Più di 10.000 strumenti definiti dopo il primo messaggio dell'utente sono disponibili dopo un qualsiasi messaggio.
  • Le definizioni degli strumenti inviate dopo il primo messaggio dell'utente che sono ancora disponibili dopo un qualsiasi messaggio superano in totale 4 MB (4.194.304 byte).
  • Il testo reso degli strumenti supera i 4 MB (4.194.304 byte).

Aggiungere un server MCP a metà conversazione (beta)

Per aggiungere un server del connettore MCP a metà di una conversazione, invia l'header beta mcp-client-2026-09-15 insieme a inline-tools-2026-09-15. La definition in un blocco tool_addition può quindi essere un mcp_toolset, così gli strumenti del server diventano disponibili senza modificare tools. Elenca come di consueto i dettagli di connessione del server in mcp_servers, poi aggiungi il toolset nel punto in cui il server è diventato disponibile:

{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": { "type": "mcp_toolset", "mcp_server_name": "calendar" }
      }
    }
  ]
}

L'oggetto mcp_toolset è lo stesso che inseriresti in tools, inclusi default_config e configs. Un blocco tool_addition non contiene mai un URL o un token del server. Questi rimangono in mcp_servers.

La seguente richiesta mantiene get_weather in tools, elenca il server del calendario in mcp_servers e aggiunge il toolset del server dopo il primo turno dell'utente:

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?"},
        # Rendi disponibili gli strumenti del server del calendario da questo punto in poi.
        # Il blocco indica il nome del server; non contiene mai un URL o un token.
        {
            "role": "system",
            "content": [
                {
                    "type": "tool_addition",
                    "tool": {
                        "type": "tool_definition",
                        "definition": {
                            "type": "mcp_toolset",
                            "mcp_server_name": "calendar",
                        },
                    },
                },
            ],
        },
    ],
)

# La risposta inizia con un blocco mcp_tool_listing per il server del calendario,
# quindi controlla il tipo di ogni blocco invece di leggere 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)

Con mcp-client-2026-09-15, una risposta per la quale l'API ha recuperato l'elenco degli strumenti di un server inizia con un blocco mcp_tool_listing, uno per ogni server recuperato. Se il tuo codice legge content[0], salta questi blocchi. Reinvia il messaggio dell'assistente invariato, incluso questo blocco, e continua a inviare mcp-client-2026-09-15 in ogni richiesta che lo contiene. Le richieste successive useranno quindi l'elenco registrato invece di interrogare di nuovo il server. Per fissare tu stesso un toolset, copia quell'elenco nel campo tools del mcp_toolset, come descritto in Fissare l'elenco degli strumenti di un server MCP.

mcp-client-2026-09-15 include tutto ciò che include mcp-client-2025-11-20, quindi non è necessario inviarli entrambi. Queste funzionalità sono disponibili sulla Claude API. Le richieste che usano il connettore MCP mantengono i suoi termini di conservazione dei dati.

Quando usare un messaggio di sistema a metà conversazione

La cache dei prompt calcola l'hash del prefisso della richiesta in ordine: tools, poi system, poi messages. Un riscontro nella cache richiede che il prefisso corrisponda esattamente, byte per byte, a una richiesta recente fino al breakpoint della cache.

Questo ordinamento significa che il campo system di primo livello si trova quasi all'inizio del prefisso sottoposto a hash. Qualsiasi modifica, anche l'aggiunta di una frase, produce un hash diverso, e la richiesta manca la cache per il prompt di sistema e per ogni messaggio in cache successivo.

I messaggi di sistema a metà conversazione ti permettono invece di aggiungere l'istruzione alla fine della cronologia dei messaggi. Tutto ciò che precede la nuova istruzione rimane invariato, quindi la voce di cache esistente corrisponde ancora, e solo il nuovo messaggio viene elaborato come input nuovo.

Alcune situazioni in cui questo è importante:

  • Cambi di policy o di persona a metà sessione. Una lunga sessione agentica ha bisogno di un nuovo vincolo ("da ora in poi, scrivi tutto l'SQL come query parametrizzate") dopo decine di turni in cache. Aggiungerlo al campo system di primo livello rielaborerebbe l'intera cronologia.
  • Contesto per turno che deve essere autorevole. Vuoi iniettare una nota di aggiornamento, una scadenza di sessione o un cambiamento nella disponibilità degli strumenti con peso a livello di sistema, e cambia troppo spesso per risiedere nel prefisso in cache.
  • Promemoria per turno che non devono accumularsi. Un harness sollecita il modello dopo ogni gruppo di risultati degli strumenti ("richiedi insieme le letture indipendenti", "l'utente non ha tue notizie da un po'") e vuole che il modello veda solo la copia più recente. Un messaggio di sistema limitato al turno viene reso per un turno e poi non costa nulla, senza eliminare nulla dalla cronologia.
  • Cambiamenti di stato osservati dalla tua applicazione. La tua applicazione nota qualcosa che Claude dovrebbe trattare come un fatto a livello di operatore: file modificati su disco, l'utente ha attivato o disattivato un'impostazione di approvazione automatica, gli strumenti disponibili sono cambiati, oppure il budget di token rimanente è sceso sotto una soglia.
  • Input dell'utente che non deve interrompere un ciclo agentico. Un utente digita un messaggio di follow-up mentre Claude sta ancora eseguendo strumenti per la richiesta precedente. Inoltrarlo come messaggio di sistema dopo il successivo risultato dello strumento permette a Claude di integrare il nuovo input nel lavoro che sta già svolgendo, invece di trattarlo come una nuova richiesta a cui passare. Su Claude Sonnet 5.5 e Claude Haiku 5.5, aggiungi invece le parole dell'utente come blocco text dopo l'ultimo tool_result nello stesso messaggio user. Vedi Posizionamento dopo i risultati degli strumenti.
  • Cambi di modalità che concedono permessi permanenti. Una modalità a livello di sessione può usare un messaggio di sistema a metà conversazione per concedere un consenso permanente a una capacità costosa, come l'avvio automatico di flussi di lavoro multiagente, con un breve promemoria ogni tot turni e un avviso di uscita quando la modalità viene disattivata. Per un esempio completo, vedi Costruire una modalità di orchestrazione.

In tutti questi casi potresti inserire l'istruzione in un normale messaggio user, e Claude segue effettivamente le istruzioni che arrivano nei turni utente. La differenza è la priorità: un messaggio user viene trattato come proveniente dall'utente finale, mentre un messaggio system viene trattato come proveniente da te, l'operatore dell'applicazione. Quando i due sono in conflitto, le istruzioni di sistema hanno la precedenza, quindi usa il ruolo system per fatti e vincoli a livello di operatore che devono valere anche se l'utente finale chiede qualcosa di diverso. Un messaggio di sistema a metà conversazione mantiene quella priorità a livello di operatore senza pagare il costo del mancato riscontro in cache dovuto alla modifica del campo system di primo livello.

Come funziona

Aggiungi un messaggio con "role": "system" all'array messages. Usa una semplice stringa o blocchi di contenuto per content, come per un turno user o assistant. L'istruzione si applica da quel punto della conversazione in poi. Quando le istruzioni sono in conflitto, i messaggi di sistema successivi hanno la precedenza su quelli precedenti, e i messaggi di sistema a metà conversazione hanno la precedenza sul campo system di primo livello per i turni che li seguono.

Puoi comunque impostare il campo system di primo livello per le istruzioni che devono applicarsi all'intera conversazione. Riserva i messaggi di sistema a metà conversazione alle istruzioni che diventano rilevanti solo in seguito, o che vuoi aggiungere senza invalidare il prefisso memorizzato nella cache.

Un messaggio role: "system" può anche contenere output_config.effort per modificare il livello di effort a metà di una conversazione. Questa funzionalità è in beta su Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 e Claude Haiku 5.5 sulla Claude API e su Google Cloud, e richiede l'header beta mid-conversation-output-config-2026-07-01. Su Amazon Bedrock, è in beta su Claude Fable 5.1, Claude Mythos 5.1 e Claude Opus 5.5, con lo stesso valore beta. Claude Opus 5 non la supporta su Amazon Bedrock. Vedi Effort per messaggio.

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    # "Prompt caching" (cache dei prompt) automatica: ogni richiesta mette in cache la conversazione finora,
    # e la richiesta successiva legge dalla cache il prefisso invariato.
    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().",
        },
        # A metà sessione il revisore si accorge che tutti i suggerimenti devono
        # rispettare anche la rigida policy di tipizzazione del team. Aggiungere qui
        # l'istruzione mantiene i turni precedenti identici byte per byte, quindi il
        # prefisso messo in cache dalla richiesta precedente viene ancora letto dalla cache.
        {
            "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)

Questo esempio abilita la cache automatica con il campo cache_control di primo livello. La cache dei prompt è facoltativa (opt-in): se una richiesta non ha alcun campo cache_control (automatico o un breakpoint esplicito), non viene memorizzato nulla nella cache e ogni richiesta paga il prezzo normale dei token di input per l'intera conversazione. Con la cache abilitata, l'aggiunta del messaggio di sistema lascia invariati i turni già memorizzati nella cache, quindi la richiesta che contiene la nuova istruzione li legge ancora dalla cache invece di elaborarli di nuovo. La cache richiede inoltre che la conversazione raggiunga la lunghezza minima del prompt memorizzabile nella cache; un esempio breve come questo è al di sotto di tale soglia, quindi cache_creation_input_tokens e cache_read_input_tokens restano a 0 finché la conversazione non cresce.

Un messaggio di sistema a metà conversazione che contiene contenuto (blocchi text, tool_addition o tool_removal) deve seguire immediatamente un turno user (o un turno assistant che termina con il risultato di uno strumento server) e deve essere l'ultima voce in messages oppure essere immediatamente seguito da un turno assistant. Un messaggio user che contiene blocchi tool_result conta: in un ciclo agentico puoi posizionare il messaggio di sistema subito dopo i risultati degli strumenti, prima del turno successivo di Claude. Qualsiasi altra posizione per un messaggio che contiene contenuto, inclusa quella tra un blocco tool_use di assistant e il tool_result che gli risponde, restituisce un errore 400. Un messaggio con content vuoto che imposta solo output_config.effort è accettato in qualsiasi punto di messages. I messaggi system consecutivi vengono valutati insieme, quindi un messaggio che imposta solo l'effort accanto a uno che contiene contenuto segue la regola per il contenuto.

Posizionamento dopo i risultati degli strumenti

In un ciclo agentico, il messaggio di sistema va dopo il messaggio user che fornisce i risultati degli strumenti. Sulla maggior parte dei modelli, questo è anche il punto in cui la tua applicazione può inoltrare l'input che l'utente ha digitato mentre Claude stava lavorando, così il nuovo contesto viene assorbito senza riavviare il turno (per Claude Sonnet 5.5 e Claude Haiku 5.5, vedi la fine di questa sezione):

[
  { "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."
  }
]

Formula il contenuto di sistema come contesto anziché come un comando che prevale sull'utente. Enuncia il fatto ("è arrivato nuovo input dall'utente: X", "il budget di token rimanente è ora Y") e lascia che Claude agisca di conseguenza. Claude è addestrato a resistere alle istruzioni che sembrano andare contro l'utente, e quella protezione si applica anche al ruolo di sistema, quindi un linguaggio come "ignora ciò che ha detto l'utente" è meno efficace rispetto a indicare cosa è cambiato.

Questo schema serve a inoltrare input proveniente dall'utente finale della conversazione stessa. Non usarlo per passare output di strumenti, documenti recuperati o altri contenuti di terze parti; mantieni quei contenuti nei blocchi tool_result (vedi Limitazioni).

Su Claude Sonnet 5.5 e Claude Haiku 5.5, fornisci invece le parole dell'utente nel turno dell'utente. Questi modelli sono addestrati a resistere alla prompt injection tramite i risultati degli strumenti, quindi possono trattare un messaggio di sistema posizionato subito dopo il risultato di uno strumento come testo non attendibile e ignorarlo. Aggiungi le parole dell'utente come blocco text dopo l'ultimo tool_result nello stesso messaggio user. Mantieni gli avvisi dell'harness, come i promemoria, in un messaggio di sistema a metà conversazione separato dopo quel messaggio user, e non inserire mai un avviso e le parole dell'utente nello stesso blocco:

[
  { "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." }
    ]
  }
]

Per maggiori informazioni su questo comportamento, vedi Scrivere prompt per Claude Sonnet 5.5 e Prompting per Claude Haiku 5.5.

Messaggi di sistema limitati al turno

Per limitare un messaggio role: "system" al turno corrente, imposta il suo campo clear_at. Accetta uno di due valori:

  • "never" (il valore predefinito): il messaggio viene reso nella sua posizione in ogni richiesta che lo include. Omettere il campo è equivalente.
  • "next_user_message": il messaggio è limitato al turno. Il suo testo viene reso solo finché nessun messaggio role: "user" lo segue in messages. Un messaggio dell'utente che contiene solo blocchi tool_result conta qui come messaggio dell'utente. Una volta che esiste un messaggio dell'utente successivo, il messaggio viene cancellato: rimane nell'array ma non rende nulla e non costa token di input, in quella richiesta e in ogni richiesta successiva.

I messaggi di sistema limitati al turno sono in beta. Includi l'header beta mid-conversation-system-clear-at-2026-08-21. Senza di esso, clear_at viene rifiutato come campo sconosciuto.

{
  "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."
}

L'uso principale è un promemoria per turno in un ciclo di strumenti. Aggiungi il promemoria dopo il messaggio tool_result ogni volta che vuoi che il modello lo veda, e lascia ogni copia precedente dove si trova. Il modello vede solo le copie che seguono l'ultimo messaggio dell'utente, quindi il promemoria non si accumula mai. Nulla di precedente in messages cambia, quindi la cache dei prompt continua a trovare corrispondenza. Su Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5 questo mantiene anche validi i blocchi di ragionamento successivi: eliminare un promemoria precedente cambierebbe la conversazione prima di quei blocchi e farebbe fallire il controllo della conversazione, mentre un messaggio cancellato rimane nell'array e lascia invariata quella conversazione.

La seguente richiesta è un passaggio successivo di un ciclo agentico. messages[3] è stato reso nella richiesta precedente, quando era l'ultimo messaggio dell'array. Una volta che esiste messages[5] (un messaggio dell'utente successivo), messages[3] viene cancellato: il messaggio cancellato rimane nell'array, quindi la conversazione prima del blocco di ragionamento in messages[4] è invariata, ma il modello non ne vede più il testo. messages[6] e messages[7] vengono entrambi resi, in ordine.

{
  "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."
    }
  ]
}

Regole per i messaggi limitati al turno:

  • Reinvia i messaggi cancellati alla lettera. Un messaggio cancellato fa ancora parte della cronologia della conversazione. Ricostruirlo dallo stato corrente (un nuovo conteggio di token, un timestamp), eliminarlo perché ridondante o cambiarne il valore clear_at costituisce una modifica a un messaggio precedente. La cache dei prompt non trova corrispondenza da quel punto in poi, e su Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5 ogni blocco di ragionamento prodotto dopo di esso non supera il controllo della conversazione.
  • Solo testo. content è costituito da uno o più blocchi text (o da una stringa). I blocchi tool_addition e tool_removal restituiscono un errore 400 su un messaggio con ambito di turno, e lo stesso vale per output_config. Per questi usa un messaggio role: "system" separato senza clear_at.
  • Nessun cache_control sui suoi blocchi. Un messaggio cancellato non fa mai parte di una chiave di cache, quindi un breakpoint su di esso non potrebbe mai trovare corrispondenza. Posiziona invece il breakpoint sull'ultimo blocco del turno dell'utente precedente, come fa l'esempio. Il campo di cache automatica di primo livello ignora i messaggi con ambito di turno quando sceglie un breakpoint. Nella richiesta che cancella un messaggio, il prefisso riutilizzabile memorizzato nella cache termina al turno dell'utente che lo precede, quindi viene rielaborato solo l'unico turno dell'assistente tra quel messaggio e il nuovo messaggio dell'utente.
  • Le regole di posizionamento si applicano comunque, che il messaggio sia cancellato o meno. Un messaggio con ambito di turno deve seguire un turno user (o un turno assistant che termina con il risultato di uno strumento server) e precedere un turno assistant o chiudere l'array, come qualsiasi messaggio di sistema a metà conversazione. Uno che chiude l'array viene sempre reso. Uno seguito direttamente da un altro messaggio user è un errore 400, non un messaggio cancellato: inserisci tutti i risultati di un ciclo di strumenti in un unico messaggio dell'utente e i promemoria dopo di esso.
  • I turni dell'assistente non lo cancellano. Un turno dell'assistente precompilato o in pausa dopo il messaggio, o un ciclo di strumenti lato server, non aggiunge alcun messaggio dell'utente, quindi il messaggio viene ancora reso in quella continuazione. Per mantenere visibile un promemoria durante un ciclo di strumenti lato client, aggiungilo di nuovo dopo ogni messaggio tool_result.
  • Il conteggio dei token segue ciò che viene reso. Un messaggio cancellato non aggiunge nulla a usage.input_tokens né a un conteggio dei token.
  • Cronologia importata. In una trascrizione che costruisci in un unico passaggio (esempi few-shot, una conversazione migrata), un messaggio con ambito di turno che ha già un turno dell'assistente e un messaggio dell'utente dopo di sé viene cancellato fin dalla prima richiesta e non viene mai reso. Questo è lo stato corretto per un promemoria per turno che stai trasferendo. Lascia clear_at non impostato solo su un messaggio che il modello deve vedere in ogni richiesta.

Gli errori di convalida sono:

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')

Il primo è l'errore restituito senza l'header beta. Su Google Cloud e su Claude in Amazon Bedrock, invia il valore beta nell'header anthropic-beta, come sulla Claude API (vedi Header beta). Con l'API InvokeModel di Amazon Bedrock, inseriscilo invece nell'array anthropic_beta del corpo della richiesta.

Tramite l'SDK, imposta clear_at sulla voce role: "system" in messages e invia l'header beta. L'esempio seguente aggiunge un promemoria limitato al turno dopo il turno dell'utente; nella richiesta successiva, una volta che esiste un messaggio dell'utente successivo, il promemoria rimane nell'array ma non viene più reso:

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.",
        },
        # Promemoria limitato al turno: viene mostrato per questo turno, poi rimosso quando esiste un messaggio utente successivo.
        {
            "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)

Combinazione con la cache dei prompt

I messaggi di sistema a metà conversazione e il "prompt caching" (cache dei prompt) sono progettati per essere usati insieme:

  • Abilita la cache esplicitamente. La memorizzazione nella cache avviene solo quando la richiesta include cache_control, tramite il campo di primo livello per la cache automatica oppure tramite un "breakpoint" (punto di interruzione) esplicito su un blocco di contenuto. Un messaggio di sistema a metà conversazione non crea da solo una voce nella cache. Senza la cache abilitata, non ci sono risparmi da preservare.
  • Memorizza nella cache il prefisso stabile come di consueto. Posiziona cache_control sull'ultimo blocco che rimane invariato tra le richieste. Può trattarsi della fine del campo system di primo livello, della fine delle definizioni degli strumenti o di un punto stabile nella cronologia dei messaggi.
  • Aggiungi il messaggio di sistema dopo il breakpoint. Poiché si trova dopo il prefisso memorizzato nella cache, non modifica l'hash del prefisso e si ottiene comunque un "cache hit" (riscontro nella cache).
  • Anche un messaggio di sistema a metà conversazione può essere memorizzato nella cache. Una volta inserito nella conversazione, diventa parte della cronologia stabile. Al turno successivo puoi spostare il breakpoint della cache oltre di esso (o affidarti alla cache automatica per farlo). Il messaggio di sistema viene quindi letto dalla cache come qualsiasi altro turno.

Evita di modificare o rimuovere un messaggio di sistema a metà conversazione già inviato. Come qualsiasi altra modifica ai messaggi precedenti, ciò invalida la cache da quel punto in poi. Su Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5 e Claude Haiku 5.5 invalida anche i blocchi di ragionamento in ogni turno successivo dell'assistente. Per indicazioni che devono applicarsi a un solo turno, usa un messaggio di sistema limitato al turno e lascialo al suo posto. Se l'istruzione deve evolvere, aggiungi un nuovo messaggio di sistema anziché riscrivere quello vecchio. I messaggi di sistema consecutivi sono accettati e trattati come un'unica sezione di sistema, che segue nel suo insieme la stessa regola di posizionamento.

Limitazioni

  • Non per il primo messaggio. Un messaggio system che contiene contenuto non può essere la prima voce in messages. Usa il campo system di primo livello per le istruzioni che si applicano fin dall'inizio.
  • Il posizionamento è vincolato. Un messaggio system che contiene contenuto (blocchi text, tool_addition o tool_removal) deve seguire immediatamente un turno user (incluso un turno user che contiene blocchi tool_result) o un turno assistant che termina con il risultato di uno strumento server, e deve precedere un turno assistant o chiudere l'array. Non può trovarsi tra un blocco tool_use e il relativo tool_result. Posizionarlo altrove restituisce un errore 400. Un'eccezione: i blocchi tool_addition e tool_removal non sono accettati immediatamente dopo un turno assistant in pausa (uno che termina con il risultato di uno strumento server), mentre i blocchi text lo sono; riprendi prima il turno in pausa, poi invia la modifica agli strumenti nel messaggio system successivo. Un messaggio con content vuoto che imposta solo output_config.effort non renderizza nulla nella sua posizione ed è accettato ovunque in messages, anche come primo messaggio o tra un turno assistant e un turno user. I messaggi system consecutivi vengono valutati insieme, quindi aggiungere un messaggio con testo accanto a uno che imposta solo l'effort fa sì che l'intero gruppo segua la regola per i messaggi con contenuto.
  • I messaggi limitati al turno contengono solo testo e vanno reinviati alla lettera. Un messaggio clear_at: "next_user_message" non contiene tool_addition, tool_removal, output_config né cache_control, e una volta cancellato deve rimanere in messages byte per byte nelle richieste successive. Vedi Messaggi di sistema limitati al turno.
  • Non è il posto per contenuti non attendibili. Claude tratta il contenuto di sistema come istruzioni dell'operatore e le segue. Non inserire direttamente in un messaggio di sistema testo proveniente dall'esterno della conversazione, come output grezzo degli strumenti, documenti recuperati o contenuti web; così facendo conferiresti a quel testo un'autorità a livello di operatore. Mantieni tali dati nei blocchi tool_result e continua a seguire Mitigare jailbreak e prompt injection.

Come funziona la cache, dove posizionare i breakpoint e come leggere i campi di utilizzo della cache.

Scopri esattamente dove due richieste hanno divergito quando un riscontro in cache che ti aspettavi non si verifica.

Struttura dei messaggi, conversazioni multi-turno e il campo system.

Scrivere prompt e istruzioni di sistema efficaci.

Come sono strutturati i blocchi tool_use e tool_result nell'array messages.

Was this page helpful?