---
title: Gestire i rifiuti in streaming
url: https://platform.claude.com/docs/it/test-and-evaluate/strengthen-guardrails/handle-streaming-refusals
description: Rileva e gestisci i motivi di arresto per rifiuto nelle risposte in streaming e riprova le richieste rifiutate su un modello di fallback.
---

A partire dai modelli Claude 4, le risposte in streaming dall'API di Claude restituiscono **`stop_reason`: `"refusal"`** quando i classificatori di streaming intervengono per gestire potenziali violazioni delle policy. Questa funzionalità di sicurezza aiuta a mantenere la conformità dei contenuti durante lo streaming in tempo reale.

<Tip>
  Questa pagina descrive come i rifiuti appaiono nelle risposte in streaming. Per ogni valore di `stop_reason` e come gestirlo, consulta [Motivi di arresto e fallback](https://platform.claude.com/docs/it/build-with-claude/handling-stop-reasons). Per riprovare le richieste rifiutate su un altro modello Claude, consulta [Rifiuti e fallback](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback).
</Tip>

## Formato della risposta API

Quando i classificatori di streaming rilevano contenuti che violano le policy di Anthropic, l'API restituisce questa risposta:

```json
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Hello.."
    }
  ],
  "stop_reason": "refusal",
  "stop_details": {
    "type": "refusal",
    "category": "cyber",
    "explanation": "This request was declined because it could enable cyber harm."
  }
}
```

Nel flusso di eventi, `stop_details` arriva nell'evento `message_delta` insieme a `stop_reason`.

<Note>
  Una risposta `refusal` dai classificatori di streaming include un oggetto `stop_details` con una `category` e una `explanation` leggibile che puoi mostrare all'utente. Consulta [Rifiuti e fallback](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#refusal-response) per la struttura completa della risposta e le categorie disponibili.

  In caso di rifiuto l'oggetto `stop_details` è sempre presente, ma i suoi campi `category` ed `explanation` possono essere `null`, ad esempio quando il rifiuto non corrisponde a nessuna categoria denominata. Esegui la diramazione su `stop_reason` o `stop_details.type` anziché presumere che `category` ed `explanation` siano popolati, e fornisci i tuoi messaggi rivolti all'utente quando sono `null`.
</Note>

## Reimpostare il contesto dopo un rifiuto

Quando ricevi **`stop_reason`: `refusal`**, devi reimpostare il contesto della conversazione prima di continuare. Puoi rimuovere o riformulare il turno che ha attivato il rifiuto, oppure cancellare completamente la cronologia della conversazione. Tentare di continuare senza reimpostare comporterà ulteriori rifiuti.

<Note>
  Le metriche di utilizzo vengono comunque fornite nella risposta, anche quando la risposta viene rifiutata. Il fatto che una richiesta rifiutata venga fatturata dipende da quando arriva il rifiuto e dalla sua categoria; consulta [Come vengono fatturati i rifiuti](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#how-refusals-are-billed).
</Note>

<Tip>
  Reimpostare il contesto non è l'unico modo per recuperare. Puoi anche riprovare la richiesta rifiutata su un modello Claude diverso, e la pagina [Rifiuti e fallback](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback) mostra come configurarlo con il fallback lato server, il middleware dell'SDK o un nuovo tentativo manuale.
</Tip>

## Guida all'implementazione

Ecco come rilevare e gestire i rifiuti in streaming nella tua applicazione:

<CodeGroup>
  ```bash cURL
  response=$(curl -N https://api.anthropic.com/v1/messages \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -d '{
      "model": "claude-opus-5-5",
      "messages": [{"role": "user", "content": "Hello"}],
      "max_tokens": 1024,
      "stream": true
    }')

  if echo "$response" | jq -R -e 'select(startswith("data: "))
      | sub("^data: "; "") | fromjson
      | select(.delta.stop_reason == "refusal")' >/dev/null; then
    echo "Response refused - resetting conversation context"
    # Reimposta qui lo stato della conversazione
  fi
  ```

  ```bash CLI
  response=$(ant messages create --stream --format jsonl \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: Hello}')

  if echo "$response" | jq -e 'select(.delta.stop_reason == "refusal")' >/dev/null; then
    echo "Response refused - resetting conversation context"
    # Reimposta qui lo stato della conversazione
  fi
  ```

  ```python Python
  client = anthropic.Anthropic()
  messages = []


  def reset_conversation():
      """Reset conversation context after refusal"""
      global messages
      messages = []
      print("Conversation reset due to refusal")


  try:
      with client.messages.stream(
          max_tokens=1024,
          messages=messages + [{"role": "user", "content": "Hello"}],
          model="claude-opus-5-5",
      ) as stream:
          for event in stream:
              # Verifica la presenza di un rifiuto nel message delta
              if event.type == "message_delta":
                  if event.delta.stop_reason == "refusal":
                      reset_conversation()
                      break
  except Exception as e:
      print(f"Error: {e}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();
  let messages: Anthropic.MessageParam[] = [];

  function resetConversation() {
    // Reimposta il contesto della conversazione dopo un rifiuto
    messages = [];
    console.log("Conversation reset due to refusal");
  }

  try {
    const stream = await client.messages.stream({
      messages: [...messages, { role: "user", content: "Hello" }],
      model: "claude-opus-5-5",
      max_tokens: 1024
    });

    for await (const event of stream) {
      // Verifica la presenza di un rifiuto nel message delta
      if (event.type === "message_delta" && event.delta.stop_reason === "refusal") {
        resetConversation();
        break;
      }
    }
  } catch (error) {
    console.error("Error:", error);
  }
  ```

  ```csharp C#
  List<Message> messages = new();
  AnthropicClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "Hello" }]
  };

  try
  {
      await foreach (var streamEvent in client.Messages.CreateStreaming(parameters))
      {
          if (
              streamEvent.TryPickDelta(out var deltaEvent)
              && deltaEvent.Delta.StopReason == StopReason.Refusal
          )
          {
              ResetConversation();
              break;
          }
      }
  }
  catch (Exception e)
  {
      Console.WriteLine($"Error: {e.Message}");
  }

  void ResetConversation()
  {
      messages.Clear();
      Console.WriteLine("Conversation reset due to refusal");
  }
  ```

  ```go Go
  var messages []anthropic.MessageParam

  func resetConversation() {
  	messages = []anthropic.MessageParam{}
  	fmt.Println("Conversation reset due to refusal")
  }
  // ...
  	client := anthropic.NewClient()

  	stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 1024,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock("Hello")),
  		},
  	})

  streamLoop:
  	for stream.Next() {
  		event := stream.Current()
  		switch eventVariant := event.AsAny().(type) {
  		case anthropic.MessageDeltaEvent:
  			if eventVariant.Delta.StopReason == anthropic.StopReasonRefusal {
  				resetConversation()
  				break streamLoop
  			}
  		}
  	}

  	if err := stream.Err(); err != nil {
  		log.Fatal(err)
  	}
  ```

  ```java Java
  import com.anthropic.core.http.StreamResponse;
  import com.anthropic.models.messages.RawMessageStreamEvent;
  import com.anthropic.models.messages.StopReason;
  // ...

  List<MessageParam> messages = new ArrayList<>();

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024L)
          .addUserMessage("Hello")
          .build();

      try (StreamResponse<RawMessageStreamEvent> stream = client.messages().createStreaming(params)) {
          stream.stream().forEach(event -> {
              event.messageDelta().ifPresent(deltaEvent -> {
                  deltaEvent.delta().stopReason().ifPresent(stopReason -> {
                      if (stopReason.equals(StopReason.REFUSAL)) {
                          resetConversation();
                      }
                  });
              });
          });
      } catch (Exception e) {
          System.err.println("Error: " + e.getMessage());
      }
  }

  void resetConversation() {
      messages.clear();
      IO.println("Conversation reset due to refusal");
  }
  ```

  ```php PHP
  $client = new Client();
  $messages = [];

  function resetConversation(&$messages) {
      $messages = [];
      echo "Conversation reset due to refusal\n";
  }

  try {
      $stream = $client->messages->createStream(
          maxTokens: 1024,
          messages: [
              ['role' => 'user', 'content' => 'Hello']
          ],
          model: 'claude-opus-5-5',
      );

      foreach ($stream as $event) {
          if ($event->type === 'message_delta' && $event->delta->stopReason === 'refusal') {
              resetConversation($messages);
              break;
          }
      }
  } catch (\Exception $e) {
      echo "Error: " . $e->getMessage() . "\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new
  messages = []

  def reset_conversation(messages)
    messages.clear
    puts "Conversation reset due to refusal"
  end

  begin
    stream = client.messages.stream(
      model: :"claude-opus-5-5",
      max_tokens: 1024,
      messages: [{ role: "user", content: "Hello" }]
    )

    stream.each do |event|
      if event.type == :message_delta && event.delta.stop_reason == :refusal
        reset_conversation(messages)
        break
      end
    end
  rescue => e
    puts "Error: #{e.message}"
  end
  ```
</CodeGroup>

## Tipi di rifiuto attuali

L'API attualmente gestisce i rifiuti in tre modi diversi:

| Tipo di rifiuto                            | Formato della risposta       | Quando si verifica                                       |
| ------------------------------------------ | ---------------------------- | -------------------------------------------------------- |
| Rifiuti dei classificatori di streaming    | **`stop_reason`: `refusal`** | Durante lo streaming quando il contenuto viola le policy |
| Validazione dell'input API e del copyright | Codici di errore 400         | Quando l'input non supera i controlli di validazione     |
| Rifiuti generati dal modello               | Risposte di testo standard   | Quando il modello stesso rifiuta                         |

## Best practice

* **Monitora i rifiuti:** Includi controlli su **`stop_reason`: `refusal`** nella tua gestione degli errori
* **Reimposta automaticamente:** Implementa la reimpostazione automatica del contesto quando vengono rilevati rifiuti
* **Esegui il fallback su un altro modello:** Configura il [fallback lato server o il middleware dell'SDK](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback) in modo che le richieste rifiutate vengano riprovate su un altro modello Claude invece di mostrare un rifiuto all'utente. Claude Haiku 5.5 non dispone di fallback lato server, quindi configura il nuovo tentativo nel tuo client
* **Riscatta il credito di fallback nei tentativi manuali:** Se implementi tu stesso il nuovo tentativo, passa il token del [credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit) del rifiuto in modo che il nuovo tentativo non paghi due volte il costo della cache dei prompt. I rifiuti di Claude Haiku 5.5 non includono credito di fallback
* **Fornisci messaggi personalizzati:** Crea messaggi comprensibili per l'utente per una migliore UX quando si verificano rifiuti
* **Traccia i pattern di rifiuto:** Monitora la frequenza dei rifiuti per identificare potenziali problemi con i tuoi prompt

## Note sulla migrazione

Se hai implementato la gestione dei rifiuti quando questa funzionalità è stata rilasciata per la prima volta, o la stai aggiungendo a un'integrazione esistente, verifica quanto segue:

* **I rifiuti sono risposte, non errori.** Un rifiuto arriva come risposta HTTP 200 riuscita con `stop_reason`: `"refusal"`, quindi un monitoraggio basato solo sui tassi di errore non lo rileverà. Traccia i rifiuti come segnale a sé stante.
* **I rifiuti includono dettagli strutturati.** Su ogni modello, un rifiuto include anche un oggetto `stop_details` che identifica la categoria di policy alla base del rifiuto. Consulta [Rifiuti e fallback](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#refusal-response) per la struttura completa della risposta.
* **Riprova su un modello diverso.** Inviare di nuovo una richiesta rifiutata allo stesso modello di solito comporta un altro rifiuto. Invece di limitarti a reimpostare il contesto, riprova su un modello di fallback con il [fallback lato server, il middleware dell'SDK o un nuovo tentativo manuale](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback), e riscatta il [credito di fallback](https://platform.claude.com/docs/it/build-with-claude/fallback-credit) quando implementi tu stesso il nuovo tentativo. Claude Haiku 5.5 non dispone di fallback lato server e i suoi rifiuti non includono credito di fallback, quindi configura il nuovo tentativo nel tuo client.
* **Controlla i risultati dei batch per i rifiuti.** Una richiesta rifiutata in un [Message Batch](https://platform.claude.com/docs/it/build-with-claude/batch-processing) viene restituita come risultato riuscito con `stop_reason`: `"refusal"`, non come risultato in errore.
* **Centralizza la gestione su `stop_reason`.** L'API continua a consolidare la gestione dei rifiuti attorno a `stop_reason`: `"refusal"`, quindi esegui la diramazione sul motivo di arresto anziché su comportamenti specifici del modello.

## Prossimi passi

<CardGroup cols={2}>
  <Card title="Rifiuti e fallback" icon="arrows-clockwise" href="https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback">
    Riprova le richieste rifiutate su un altro modello Claude, lato server o nel tuo client.
  </Card>

  <Card title="Motivi di arresto e fallback" icon="code" href="https://platform.claude.com/docs/it/build-with-claude/handling-stop-reasons">
    Ogni valore di `stop_reason` e come gestirlo.
  </Card>

  <Card title="Messaggi in streaming" icon="lightning" href="https://platform.claude.com/docs/it/build-with-claude/streaming">
    Trasmetti le risposte in streaming e leggi `stop_reason` dagli eventi `message_delta` man mano che arrivano.
  </Card>

  <Card title="Supporto multilingue" icon="text-aa" href="https://platform.claude.com/docs/it/build-with-claude/multilingual-support">
    Servi utenti in più lingue con le capacità cross-linguistiche di Claude.
  </Card>
</CardGroup>
