---
title: Manejar rechazos en streaming
url: https://platform.claude.com/docs/es/test-and-evaluate/strengthen-guardrails/handle-streaming-refusals
description: Detecta y maneja los motivos de detención por rechazo en respuestas de streaming, y reintenta las solicitudes rechazadas en un modelo de respaldo.
featureMetadata:
  supportedModels:
    - claude-fable-5-2
    - claude-mythos-5-2
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-mythos-preview
    - claude-opus-5-5
    - claude-opus-5
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-haiku-5-5
    - claude-haiku-4-5-20251001
    - claude-opus-4-8
    - claude-opus-4-7
    - claude-opus-4-6
    - claude-sonnet-4-6
    - claude-opus-4-5-20251101
    - claude-sonnet-4-5-20250929
  supportedPlatforms:
    Claude API: stable
    Amazon Bedrock: stable
    Amazon Bedrock (bedrock-runtime): stable
    Claude Platform on AWS: stable
    Claude Models on Google Cloud (Google managed): stable
    Microsoft Foundry: stable
---

**Compatibilidad con la API**: El uso varía según el producto.

* **Messages API**: El stream termina con `stop_reason` `"refusal"`, y `stop_details` (`category` y `explanation`) llega en el evento `message_delta`.
* **Managed Agents**: Un turno rechazado termina y la sesión pasa a estar inactiva. Considera rechazado un turno si `stop_details.type` o `stop_reason.type` es `"refusal"`.

A partir de los modelos Claude 4, las respuestas de streaming de la API de Claude devuelven **`stop_reason`: `"refusal"`** cuando los clasificadores de streaming intervienen para manejar posibles violaciones de políticas. Esta función de seguridad ayuda a mantener el cumplimiento del contenido durante el streaming en tiempo real.

<Tip>
  Esta página cubre cómo aparecen los rechazos en las respuestas de streaming. Para conocer cada valor de `stop_reason` y cómo manejarlo, consulta [Motivos de detención y respaldo](https://platform.claude.com/docs/es/build-with-claude/handling-stop-reasons). Para reintentar solicitudes rechazadas en otro modelo de Claude, consulta [Rechazos y respaldo](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback).
</Tip>

## Formato de respuesta de la API

Cuando los clasificadores de streaming detectan contenido que viola las políticas de Anthropic, la API devuelve esta respuesta:

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

En el flujo de eventos, `stop_details` llega en el evento `message_delta` junto con `stop_reason`.

<Note>
  Una respuesta `refusal` de los clasificadores de streaming incluye un objeto `stop_details` con una `category` y una `explanation` legible por humanos que puedes mostrar al usuario. Consulta [Cómo se ve un rechazo](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback#refusal-response) para ver la estructura completa de la respuesta y las categorías disponibles.

  En un rechazo, el objeto `stop_details` siempre está presente, pero sus campos `category` y `explanation` pueden ser `null`, por ejemplo cuando el rechazo no corresponde a ninguna categoría con nombre. Ramifica según `stop_reason` o `stop_details.type` en lugar de asumir que `category` y `explanation` están completos, y proporciona tus propios mensajes orientados al usuario cuando sean `null`.
</Note>

## Restablecer el contexto después de un rechazo

Cuando recibes **`stop_reason`: `refusal`**, debes restablecer el contexto de la conversación antes de continuar. Puedes eliminar o reformular el turno que provocó el rechazo, o borrar por completo el historial de la conversación. Intentar continuar sin restablecer dará como resultado rechazos continuos.

<Note>
  Las métricas de uso se siguen proporcionando en la respuesta, incluso cuando la respuesta es rechazada. Que una solicitud rechazada se facture o no depende de cuándo llega el rechazo y de su categoría; consulta [Cómo se facturan los rechazos](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback#how-refusals-are-billed).
</Note>

<Tip>
  Restablecer el contexto no es la única forma de recuperarse. También puedes reintentar la solicitud rechazada en un modelo de Claude diferente, y la página [Rechazos y respaldo](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback) muestra cómo configurarlo con respaldo del lado del servidor, el middleware del SDK o un reintento manual.
</Tip>

## Guía de implementación

Así es como puedes detectar y manejar rechazos en streaming en tu aplicación:

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Detectar un rechazo en el flujo y restablecer la conversación necesita más lógica que un solo comando de shell. Usa el [Anthropic SDK](https://platform.claude.com/docs/es/cli-sdks-libraries/overview) para ejecutarlo.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Detectar un rechazo en el flujo y restablecer la conversación necesita más lógica que un solo comando de shell. Usa el [Anthropic SDK](https://platform.claude.com/docs/es/cli-sdks-libraries/overview) para ejecutarlo.
  </CodeGroupItem>

  ```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:
              # Comprueba si hay un rechazo en el delta del mensaje
              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() {
    // Restablece el contexto de la conversación tras un rechazo
    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) {
      // Comprueba si hay un rechazo en el delta del mensaje
      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 UserMessageParam { 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>

## Tipos de rechazo actuales

La API actualmente maneja los rechazos de tres formas diferentes:

| Tipo de rechazo                                     | Formato de respuesta         | Cuándo ocurre                                                |
| --------------------------------------------------- | ---------------------------- | ------------------------------------------------------------ |
| Rechazos del clasificador de streaming              | **`stop_reason`: `refusal`** | Durante el streaming cuando el contenido viola las políticas |
| Validación de entrada y derechos de autor de la API | Códigos de error 400         | Cuando la entrada no pasa las verificaciones de validación   |
| Rechazos generados por el modelo                    | Respuestas de texto estándar | Cuando el propio modelo rechaza                              |

## Mejores prácticas

* **Supervisa los rechazos:** Incluye comprobaciones de **`stop_reason`: `refusal`** en tu manejo de errores.
* **Restablece automáticamente:** Implementa el restablecimiento automático del contexto cuando se detecten rechazos.
* **Recurre a otro modelo:** Configura el [respaldo del lado del servidor o el middleware del SDK](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback) para que las solicitudes rechazadas se reintenten en otro modelo de Claude en lugar de mostrar un rechazo al usuario. Claude Haiku 5.5 no tiene respaldo del lado del servidor, así que configura su reintento en tu cliente.
* **Canjea el crédito de respaldo en reintentos manuales:** Si creas el reintento tú mismo, pasa el token de [crédito de respaldo](https://platform.claude.com/docs/es/build-with-claude/fallback-credit) del rechazo para que el reintento no pague dos veces el costo de la caché de prompts. Los rechazos de Claude Haiku 5.5 no incluyen crédito de respaldo.
* **Proporciona mensajes personalizados:** Crea mensajes fáciles de entender para ofrecer una mejor experiencia de usuario cuando ocurran rechazos.
* **Haz seguimiento de los patrones de rechazo:** Supervisa la frecuencia de los rechazos para identificar posibles problemas con tus prompts.

## Notas de migración

Si construiste el manejo de rechazos cuando esta función se lanzó por primera vez, o lo estás agregando a una integración existente, verifica lo siguiente:

* **Los rechazos son respuestas, no errores.** Un rechazo llega como una respuesta HTTP 200 exitosa con `stop_reason`: `"refusal"`, por lo que un monitoreo basado únicamente en tasas de error no lo detectará. Rastrea los rechazos como su propia señal.
* **Los rechazos incluyen detalles estructurados.** En todos los modelos, un rechazo también incluye un objeto `stop_details` que identifica la categoría de política detrás de la negativa. Consulta [Cómo se ve un rechazo](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback#refusal-response) para ver la estructura completa de la respuesta.
* **Reintenta en un modelo diferente.** Volver a enviar una solicitud rechazada al mismo modelo suele provocar otro rechazo. En lugar de solo restablecer el contexto, reintenta en un modelo de respaldo con [el respaldo del lado del servidor, el middleware del SDK o un reintento manual](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback), y canjea el [crédito de respaldo](https://platform.claude.com/docs/es/build-with-claude/fallback-credit) cuando construyas el reintento tú mismo. Claude Haiku 5.5 no tiene respaldo del lado del servidor y sus rechazos no incluyen crédito de respaldo, así que configura su reintento en tu cliente.
* **Revisa los resultados de lotes en busca de rechazos.** Una solicitud rechazada en un [lote de mensajes](https://platform.claude.com/docs/es/build-with-claude/batch-processing) se devuelve como un resultado exitoso con `stop_reason`: `"refusal"`, no como un resultado con error.
* **Centraliza el manejo en `stop_reason`.** La API continúa consolidando el manejo de rechazos en torno a `stop_reason`: `"refusal"`, así que ramifica según el motivo de detención en lugar de según el comportamiento específico del modelo.

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Rechazos y respaldo" icon="arrows-clockwise" href="https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback">
    Reintenta solicitudes rechazadas en otro modelo de Claude, del lado del servidor o en tu cliente.
  </Card>

  <Card title="Motivos de detención y respaldo" icon="code" href="https://platform.claude.com/docs/es/build-with-claude/handling-stop-reasons">
    Cada valor de `stop_reason` y cómo manejarlo.
  </Card>

  <Card title="Mensajes en streaming" icon="lightning" href="https://platform.claude.com/docs/es/build-with-claude/streaming">
    Transmite respuestas en streaming y lee `stop_reason` de los eventos `message_delta` a medida que llegan.
  </Card>

  <Card title="Soporte multilingüe" icon="text-aa" href="https://platform.claude.com/docs/es/build-with-claude/multilingual-support">
    Atiende a usuarios en distintos idiomas con las capacidades multilingües de Claude.
  </Card>
</CardGroup>

## Disponibilidad

Estado de Rechazos en streaming: disponible o en beta, según la API.

### Compatibilidad con la API

#### [Messages API](https://platform.claude.com/docs/es/build-with-claude/working-with-messages)

* Disponibilidad: Siempre activo
* Uso: El stream termina con `stop_reason` `"refusal"`, y `stop_details` (`category` y `explanation`) llega en el evento `message_delta`.

| Estado     | Plataformas en la nube                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Disponible | Claude API, [Amazon Bedrock](https://platform.claude.com/docs/es/build-with-claude/claude-in-amazon-bedrock), [Amazon Bedrock (bedrock-runtime)](https://platform.claude.com/docs/es/build-with-claude/claude-on-amazon-bedrock-legacy), [Claude Platform on AWS](https://platform.claude.com/docs/es/build-with-claude/claude-platform-on-aws), [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/es/build-with-claude/claude-models-on-google-cloud/google-managed), [Microsoft Foundry](https://platform.claude.com/docs/es/build-with-claude/claude-in-microsoft-foundry) |

#### [Managed Agents](https://platform.claude.com/docs/es/managed-agents/overview)

* Disponibilidad: Siempre activo
* Uso: Un turno rechazado termina y la sesión pasa a estar inactiva. Considera rechazado un turno si `stop_details.type` o `stop_reason.type` en el evento `session.status_idle` es `"refusal"`. En un turno rechazado, `stop_reason.type` puede ser `"end_turn"`. `stop_details` es `null` en cualquier otro turno, y también puede ser `null` en un turno rechazado.

| Estado | Plataformas en la nube                                                                                             |
| ------ | ------------------------------------------------------------------------------------------------------------------ |
| Beta   | Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/es/build-with-claude/claude-platform-on-aws) |
