# Claude Message Threads API: guida ai thread

> I thread di messaggi nell'API Claude: header beta, richieste create e continue, i campi da inviare di nuovo, la scadenza e cosa fare dopo un 404.

- Canonical HTML: https://omniakey.com/it/blog/claude-message-threads-api-guide
- Markdown: https://omniakey.com/it/blog/claude-message-threads-api-guide.md
- Published: 2026-11-04 (updated 2026-11-04)
- Author: Kiki, COO at OmniaKey
- Language: it
- Category: API setup
- Reading time: 9 min
- All posts: https://omniakey.com/blog/llms.txt

---

L'API Claude Message Threads ti permette di inviare una conversazione lunga una volta sola e, a ogni turno successivo, mandare solo i messaggi nuovi. Aggiungi `"thread": {"type": "create"}` alla prima richiesta Messages e l'header beta `message-threads-2026-08-12`: l'API tiene la conversazione in memoria e la richiesta successiva invia meno contenuto (pagina Message threads di Anthropic, 4 novembre 2026).

È beta su tutti i modelli. 17 ID di modello possono usarla, incluso [Claude Opus 5.5](https://omniakey.com/it/claude-opus-5-5), che il codice qui sotto chiama. L'header beta accompagna ogni richiesta di un thread.

## Cosa risparmia un thread

Senza thread, ogni turno porta l'intera trascrizione: il system prompt, le definizioni degli strumenti, tutti i messaggi precedenti e tutti i risultati degli strumenti. Un thread archivia quella conversazione, risposta di Claude compresa, sotto l'`id` della risposta, e una richiesta continue invia solo ciò che è successo dopo (pagina Message threads, 4 novembre 2026). Meno contenuto a ogni turno.

La cache dei prompt aiuta la stessa conversazione da un altro lato. Un cache hit rende più economico l'input ripetuto: su Opus 5.5, 0,20 USD per milione di token contro 4 USD per un input nuovo (pagina dei prezzi di Anthropic, 4 novembre 2026). La richiesta porta comunque quell'input. Il thread riduce quello che invii; la cache abbassa il prezzo di ciò che si ripete. Le sessioni lunghe vogliono entrambi, e [ridurre il consumo di token di Claude Code](https://omniakey.com/it/blog/reduce-claude-code-token-usage) copre il lato contesto.

I thread non cambiano né i prezzi né i limiti di frequenza (pagina Message threads, 4 novembre 2026). Le tariffe attuali sono nella pagina [prezzi](https://omniakey.com/it/pricing).

La cache la gestisci tu. Invia un `cache_control` di primo livello in ogni richiesta e l'API lo applica all'ultimo blocco `messages` memorizzabile di quella richiesta. Il limite di quattro breakpoint è una regola della cache dei prompt valida per tutta la piattaforma, e la cache automatica ne occupa uno (pagina della cache dei prompt di Anthropic, 4 novembre 2026). Distribuiscili così:

1. il `cache_control` di primo livello, un punto in ogni richiesta del thread;
2. uno su `system`, inviato con la richiesta create;
3. uno su `tools`, anche alla create;
4. uno sul messaggio più recente.

I breakpoint sui messaggi già archiviati restano fuori da questo budget, perché una richiesta continue invia solo i messaggi nuovi. Un breakpoint inviato resta dov'è. Quando reinvii una conversazione, togli i punti dai messaggi precedenti e lascia un punto sull'ultimo blocco (pagina Message threads, 4 novembre 2026).

## Crea il primo turno, poi continua

Tre passaggi:

1. Metti la tua chiave Anthropic in `ANTHROPIC_API_KEY`.
2. Invia la conversazione completa, con `system` e `tools` se li usi, più `"thread": {"type": "create"}`.
3. Invia solo i messaggi dall'ultima risposta, più `"thread": {"type": "continue", "previous_message_id": "<previous id>"}`, e lascia fuori `system` e `tools`.

Ogni richiesta porta l'header beta e `anthropic-version: 2026-10-21`, la versione attuale (pagina delle versioni di Anthropic, 4 novembre 2026).

```bash
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2026-10-21" \
  -H "anthropic-beta: message-threads-2026-08-12" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 1024,
    "system": "You are a careful backend reviewer.",
    "messages": [
      {"role": "user", "content": "Read this design and list the risks."}
    ],
    "thread": {"type": "create"}
  }'
```

Conserva l'`id` di quella risposta. La richiesta successiva invia solo il messaggio nuovo:

```bash
PREVIOUS_ID="<id from the previous response>"

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2026-10-21" \
  -H "anthropic-beta: message-threads-2026-08-12" \
  -H "content-type: application/json" \
  -d @- <<JSON
{
  "model": "claude-opus-5-5",
  "max_tokens": 1024,
  "messages": [
    {"role": "user", "content": "Turn those risks into a checklist."}
  ],
  "thread": {"type": "continue", "previous_message_id": "$PREVIOUS_ID"}
}
JSON
```

Tieni l'`id` più recente di ogni risposta: un thread accetta solo aggiunte, ogni `id` di risposta si continua una volta sola, e la richiesta successiva deve usare l'ultimo (pagina Message threads, 4 novembre 2026).

Se ti serve un'altra strada per una chiave API, OmniaKey vende accesso all'API Claude con gli stessi ID di modello, quindi il corpo della richiesta non cambia. I thread sono beta dalla parte di Anthropic, quindi prima di dipenderne in produzione controlla che l'intermediario che usi lasci passare il campo `thread` così com'è.

L'SDK Python segue gli id per te. Prepara un helper con `client.beta.messages.thread(...)`, che si limita a preparare la chiamata, e invia ogni turno con `thread.send()`. L'helper aggiunge l'header beta, crea al primo turno, continua con i soli messaggi nuovi e una volta reinvia tutta la conversazione in una nuova richiesta create quando una continue dà `thread_not_found`, `thread_already_continued` o `thread_continue_in_flight` (pagina Message threads, 4 novembre 2026).

```python
import anthropic

client = anthropic.Anthropic()  # legge ANTHROPIC_API_KEY

# L'helper non invia ancora nulla; conserva i campi che ogni turno riusa.
thread = client.beta.messages.thread(
    model="claude-opus-5-5",
    max_tokens=1024,
    system="You are a careful backend reviewer.",
)

first = thread.send({"role": "user", "content": "Read this design and list the risks."})
print(first.id, first.stop_reason)

second = thread.send({"role": "user", "content": "Turn those risks into a checklist."})
print(second.id)  # la prossima volta continua da questo id
```

Non abbiamo eseguito queste richieste contro l'API di Anthropic; la forma viene dalla pagina Message threads di Anthropic. Per lo streaming, `thread.stream(...)` e `stream.get_final_message()` danno lo stesso flusso, e `thread.previous_message_id` restituisce l'id se preferisci seguirlo da solo.

## Cosa reinviare e cosa mai

Invia i campi fissi con gli stessi valori in ogni richiesta, `system` e `tools` solo nella richiesta create, e lascia che i campi liberi cambino da un turno all'altro.

|Gruppo|Campi|Regola|
|-|-|-|
|Solo create|`system`, `tools`|Solo nella richiesta create; inviare uno dei due in una richiesta continue, anche come `null`, dà 400.|
|Fissi|`model`, `tool_choice`, `thinking`, `mcp_servers` tranne il token di autorizzazione di ogni server, `context_management`, `output_config`, gli `skills` di `container`, il `cache_control` di primo livello e l'insieme dei valori di `anthropic-beta`|Sempre lo stesso valore. Un valore diverso dà 400 e nomina il campo che differisce.|
|Liberi|`max_tokens`, `stop_sequences`, `stream`, `metadata`, `service_tier` e i campi senza nome|Cambiali quando vuoi.|

Il 400 di un campo fisso modificato porta `thread_fingerprint_mismatch`, e il messaggio elenca i campi che differiscono. Per cambiare uno di questi valori, apri un nuovo thread con la conversazione completa e il nuovo valore.

Se manca `previous_message_id`, la richiesta continue dà 400 con un message nel corpo ma nessun `error_code`; aggiungere `system` o `tools` fa lo stesso. Una richiesta continue deve portare esattamente i messaggi dall'ultima risposta.

`mcp_servers` è fisso, ma gli URL dei server e i token di autorizzazione vivono solo nella tua richiesta, quindi invia la lista in ogni richiesta che usa MCP; un token può cambiare tra due richieste. Anche l'`id` del container vive solo nella tua richiesta, quindi invia `container` ogni volta (pagina Message threads, 4 novembre 2026).

Il fallback lato server si decide alla create: invia `fallbacks` in ogni richiesta del thread o in nessuna. Il valore può cambiare tra i turni, ma aggiungere o togliere il campo dà `thread_fingerprint_mismatch`.

## Scadenza, reinvio e il 404

Un thread scade 5 minuti dopo l'ultima richiesta, e l'API lo elimina al più tardi 1 ora dopo l'ultimo uso. Ogni risposta archiviata riavvia i 5 minuti. I thread non rientrano nella conservazione zero dei dati: la conversazione, il system prompt e gli strumenti restano in memoria, cifrati, e non vengono mai scritti su uno storage durevole (pagina Message threads, 4 novembre 2026).

Nessun campo della risposta dice se l'API ha archiviato un turno, né alla create né alla continue. Lo scopri alla richiesta continue successiva, quindi la tua applicazione resta la fonte di verità e tiene una propria copia di ogni messaggio (pagina Message threads, 4 novembre 2026).

Quando una richiesta continue dà 404 `thread_not_found`, invia la conversazione completa in una nuova richiesta create e riparti dall'`id` di quella risposta. L'API dà lo stesso 404 in tutti questi casi:

- il thread è scaduto;
- il turno precedente è stato servito e poi scartato, per esempio una chiamata a uno strumento tagliata da `max_tokens`;
- la risposta precedente l'ha scritta un modello di fallback;
- la risposta precedente è ancora in generazione;
- la richiesta arriva da un'altra organizzazione, workspace, utente o chiave di workspace;
- i messaggi nuovi portano contenuto che la conversazione archiviata non ha, come la prima immagine di una conversazione che non ne aveva.

Reinviare la conversazione completa è sempre sicuro e sistema ognuno di questi casi.

Lo streaming aggiunge una regola: riparti dall'`id` della risposta solo dopo `message_stop`, perché una continue inviata prima può dare 404. Se lo stream di una richiesta continue si interrompe prima di `message_stop`, invia di nuovo la stessa richiesta continue, e reinvia tutto se questo dà `thread_already_continued` o `thread_continue_in_flight`. Lo stream interrotto l'helper dell'SDK lo lascia al tuo retry.

Altri tre casi hanno una strada propria:

- `pause_turn`: riparti dall'`id` di quella risposta con `"messages": []`. Se dà 404, reinvia tutto includendo la risposta in pausa.
- `stop_reason: "refusal"`: apri un nuovo thread senza il turno che l'ha provocato; l'API potrebbe già avere il turno rifiutato.
- una voce `fallback_message` in `usage.iterations`, o nell'ultimo `message_delta` di uno stream, segnala una risposta di fallback: reinvia tutto.

## Errori

I cinque errori di thread tornano prima che il modello giri: la richiesta non consuma token e il thread tiene la sua scadenza. `error.type` vale `invalid_request_error` per i 400 e `not_found_error` per il 404 (pagina Message threads, 4 novembre 2026).

- **404, `thread_not_found`**: l'API non può continuare questo thread. Invia la conversazione completa in una nuova richiesta create.
- **400, `thread_fingerprint_mismatch`**: un campo fisso è cambiato rispetto al valore salvato con il thread. Tienilo identico o apri un nuovo thread.
- **400, `thread_already_continued`**: quell'`id` di risposta è già stato usato una volta. Riparti dall'`id` più recente e reinvia tutto se non l'hai mai ricevuto.
- **400, `thread_continue_in_flight`**: un'altra continue sullo stesso `id` è ancora in corso, di solito il tuo tentativo precedente. Lasciala finire o reinvia tutto.
- **400, `thread_unsupported_request`**: la richiesta usa una funzione o un'impostazione dell'organizzazione che i thread non supportano. `error.details.unsupported` nomina uno tra `context_management`, `cache_control`, `fallbacks`, `hipaa` e `inference_hooks`; l'elenco può allungarsi, quindi se un valore ti è sconosciuto invia la conversazione completa senza `thread`.

Message Batches rifiuta il campo `thread` (un elemento di batch che lo porta fallisce con `invalid_request_error`), e il conteggio dei token e la compattazione danno 400; lo stesso vale per la modifica del contesto diversa da `clear_thinking_20251015` con `keep: "all"`. Le organizzazioni pronte per HIPAA e quelle con Inference hooks attivi sono escluse. Elencare, leggere ed eliminare un thread non esistono nell'API.

## Domande frequenti

### Che cos'è l'API Claude Message Threads?

È una funzione beta dell'API Messages che archivia una conversazione dalla parte di Anthropic, così i turni successivi inviano solo i messaggi nuovi. L'header beta è `message-threads-2026-08-12`, e ogni richiesta aggiunge un oggetto `thread` con `type` uguale a `create` o `continue`.

### I thread funzionano con la cache dei prompt?

Sì. Il thread non mette in cache il tuo prompt al posto tuo: invia un `cache_control` di primo livello in ogni richiesta e resta entro quattro breakpoint. I punti sui messaggi archiviati non contano; quello di primo livello e quelli su `system` o `tools` contano.

### Posso cambiare modello a metà thread?

Cambiare modello richiede un nuovo thread. `model` è un campo fisso, quindi un valore diverso dà 400 `thread_fingerprint_mismatch`; apri un nuovo thread con la conversazione completa e il nuovo modello.

### Perché una continue dà 400 senza error\_code?

Manca `previous_message_id`, oppure la richiesta contiene `system` o `tools`, anche come `null`. Quei 400 portano un message e omettono `error_code`, quindi leggi il testo.

### Quanto dura un thread e cosa succede alla scadenza?

Un thread scade 5 minuti dopo l'ultima richiesta e viene eliminato al più tardi 1 ora dopo l'ultimo uso. Dopo, una continue dà 404 `thread_not_found`; invia la conversazione completa in una nuova richiesta create e riparti dal suo `id`.

## Fonti verificate

- [Anthropic: message threads](https://platform.claude.com/docs/en/build-with-claude/message-threads)
- [Anthropic: cache dei prompt](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)
- [Anthropic: prezzi dell'API Claude](https://platform.claude.com/docs/en/about-claude/pricing)
- [Anthropic: versioni dell'API](https://platform.claude.com/docs/en/api/versioning)
