• Mensajes
  • Agentes gestionados
  • Administración
Search...
⌘K
Primeros pasos
Introducción a ClaudeInicio rápido
Desarrollar con Claude
Descripción general de funcionesUso de la API de MensajesMotivos de detención y respaldoRechazos y respaldoCrédito de respaldo
Capacidades del modelo
Pensamiento extendidoPensamiento adaptativoEsfuerzoPresupuestos de tareas (beta)Modo rápido (vista previa de investigación)Salidas estructuradasCitasStreaming de mensajesProcesamiento por lotesResultados de búsquedaStreaming de rechazosSoporte multilingüeEmbeddings
Herramientas
Descripción generalCómo funciona el uso de herramientasTutorial: Crear un agente que usa herramientasDefinir herramientasGestionar llamadas a herramientasUso de herramientas en paraleloTool Runner (SDK)Uso de herramientas estrictoUso de herramientas con almacenamiento en caché de promptsHerramientas de servidorSolución de problemasHerramienta de búsqueda webHerramienta de obtención webHerramienta de ejecución de códigoHerramienta de asesorHerramienta de memoriaHerramienta BashHerramienta de uso de computadoraHerramienta de editor de texto
Infraestructura de herramientas
Referencia de herramientasGestionar contexto de herramientasCombinaciones de herramientasBúsqueda de herramientasLlamadas programáticas a herramientasStreaming detallado de herramientas
Gestión de contexto
Ventanas de contextoCompactaciónEdición de contextoAlmacenamiento en caché de promptsMensajes del sistema en mitad de conversaciónCrear un modo de orquestaciónDiagnóstico de caché (beta)Conteo de tokens
Trabajar con archivos
API de archivosCompatibilidad con PDFImágenes y visión
Habilidades
Descripción generalInicio rápidoMejores prácticasHabilidades para empresasHabilidades en la API
MCP
Servidores MCP remotosConector MCP
Claude en plataformas en la nube
Amazon BedrockAmazon Bedrock (heredado)Claude Platform en AWSMicrosoft FoundryVertex AI
Log in
Motivos de detención y respaldo
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Solutions

  • AI agents
  • Code modernization
  • Coding
  • Customer support
  • Education
  • Financial services
  • Government
  • Life sciences

Partners

  • Amazon Bedrock
  • Google Cloud's Vertex AI

Learn

  • Blog
  • Courses
  • Use cases
  • Connectors
  • Customer stories
  • Engineering at Anthropic
  • Events
  • Powered by Claude
  • Service partners
  • Startups program

Company

  • Anthropic
  • Careers
  • Economic Futures
  • Research
  • News
  • Responsible Scaling Policy
  • Security and compliance
  • Transparency

Learn

  • Blog
  • Courses
  • Use cases
  • Connectors
  • Customer stories
  • Engineering at Anthropic
  • Events
  • Powered by Claude
  • Service partners
  • Startups program

Help and security

  • Availability
  • Status
  • Support
  • Discord

Terms and policies

  • Privacy policy
  • Responsible disclosure policy
  • Terms of service: Commercial
  • Terms of service: Consumer
  • Usage policy
Mensajes/Desarrollar con Claude

Razones de detención y fallback

El campo stop_reason, qué significa cada valor y dónde manejar los rechazos y el fallback.

Cuando haces una solicitud a la API de Messages, la respuesta de Claude incluye un campo stop_reason que indica por qué el modelo dejó de generar su respuesta. Comprender estos valores es crucial para construir aplicaciones robustas que manejen adecuadamente los diferentes tipos de respuesta.

Para obtener detalles sobre stop_reason en la respuesta de la API, consulta la referencia de la API de Messages.

El campo stop_reason

El campo stop_reason forma parte de cada respuesta exitosa de la API de Messages. A diferencia de los errores, que indican fallos en el procesamiento de tu solicitud, stop_reason te indica por qué Claude completó la generación de su respuesta.

Example response
{
  "id": "msg_01234",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Here's the answer to your question..."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 100,
    "output_tokens": 50
  }
}

Valores de stop reason

end_turn

La razón de detención más común. Indica que Claude finalizó su respuesta de forma natural.

Python
from anthropic import Anthropic

client = Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
if response.stop_reason == "end_turn":
    # Procesa la respuesta completa
    print(response.content[0].text)

Respuestas vacías con end_turn

A veces Claude devuelve una respuesta vacía (exactamente 2-3 tokens sin contenido) con stop_reason: "end_turn". Esto suele ocurrir cuando Claude interpreta que el turno del asistente está completo, particularmente después de resultados de herramientas.

Causas comunes:

  • Agregar bloques de texto inmediatamente después de los resultados de herramientas (Claude aprende a esperar que el usuario siempre inserte texto después de los resultados de herramientas, por lo que termina su turno para seguir el patrón)
  • Enviar de vuelta la respuesta completada de Claude sin agregar nada (Claude ya decidió que terminó, por lo que seguirá considerando que terminó)

Cómo prevenir respuestas vacías:

# INCORRECTO: Agregar texto inmediatamente después de tool_result
messages = [
    {"role": "user", "content": "Calculate the sum of 1234 and 5678"},
    {
        "role": "assistant",
        "content": [
            {
                "type": "tool_use",
                "id": "toolu_123",
                "name": "calculator",
                "input": {"operation": "add", "a": 1234, "b": 5678},
            }
        ],
    },
    {
        "role": "user",
        "content": [
            {"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"},
            {
                "type": "text",
                "text": "Here's the result",  # Don't add text after tool_result
            },
        ],
    },
]

# CORRECTO: Envía los resultados de herramientas directamente sin texto adicional
messages = [
    {"role": "user", "content": "Calculate the sum of 1234 and 5678"},
    {
        "role": "assistant",
        "content": [
            {
                "type": "tool_use",
                "id": "toolu_123",
                "name": "calculator",
                "input": {"operation": "add", "a": 1234, "b": 5678},
            }
        ],
    },
    {
        "role": "user",
        "content": [
            {"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"}
        ],
    },  # Just the tool_result, no additional text
]


# Si sigues obteniendo respuestas vacías después de corregir la estructura del mensaje:
def handle_empty_response(client, messages):
    response = client.messages.create(
        model="claude-opus-4-8", max_tokens=1024, messages=messages
    )

    # Verifica si la respuesta está vacía
    if response.stop_reason == "end_turn" and not response.content:
        # INCORRECTO: No simplemente reintentes con la respuesta vacía
        # Esto no funcionará porque Claude ya decidió que terminó

        # CORRECTO: Agrega un prompt de continuación en un NUEVO mensaje de usuario
        messages.append({"role": "user", "content": "Please continue"})

        response = client.messages.create(
            model="claude-opus-4-8", max_tokens=1024, messages=messages
        )

    return response

Mejores prácticas:

  1. Nunca agregues bloques de texto inmediatamente después de los resultados de herramientas - Esto le enseña a Claude a esperar input del usuario después de cada uso de herramientas
  2. No reintentes respuestas vacías sin modificación - Simplemente enviar de vuelta la respuesta vacía no ayudará
  3. Usa prompts de continuación como último recurso - Solo si estas correcciones no resuelven el problema

max_tokens

Claude se detuvo porque alcanzó el límite de max_tokens especificado en tu solicitud.

Python
# Solicitud con tokens limitados
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=10,
    messages=[{"role": "user", "content": "Explain quantum physics"}],
)

if response.stop_reason == "max_tokens":
    # La respuesta fue truncada
    print("Response was cut off at token limit")
    # Considera hacer otra solicitud para continuar

Bloques de tool use incompletos

Si la respuesta de Claude se corta debido a que alcanzó el límite de max_tokens, y la respuesta truncada contiene un bloque de uso de herramientas incompleto, necesitarás reintentar la solicitud con un valor de max_tokens más alto para obtener el uso de herramientas completo.

# Verifica si la respuesta se truncó durante el uso de herramientas
if response.stop_reason == "max_tokens":
    # Verifica si el último bloque de contenido es un tool_use incompleto
    last_block = response.content[-1]
    if last_block.type == "tool_use":
        # Envía la solicitud con un max_tokens más alto
        response = client.messages.create(
            model="claude-opus-4-8",
            max_tokens=4096,  # Increased limit
            messages=messages,
            tools=tools,
        )

stop_sequence

Claude encontró una de tus secuencias de detención personalizadas.

Python
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    stop_sequences=["END", "STOP"],
    messages=[{"role": "user", "content": "Generate text until you say END"}],
)

if response.stop_reason == "stop_sequence":
    print(f"Stopped at sequence: {response.stop_sequence}")

tool_use

Claude está llamando a una herramienta y espera que la ejecutes.

Para la mayoría de las implementaciones de uso de herramientas, usa el tool runner, que maneja automáticamente la ejecución de herramientas, el formateo de resultados y la gestión de la conversación.

Python
from anthropic import Anthropic

client = Anthropic()
weather_tool = {
    "name": "get_weather",
    "description": "Get the current weather in a given location",
    "input_schema": {
        "type": "object",
        "properties": {
            "location": {"type": "string", "description": "City and state"},
        },
        "required": ["location"],
    },
}


def execute_tool(name, tool_input):
    """Execute a tool and return the result."""
    return f"Weather in {tool_input.get('location', 'unknown')}: 72°F"


response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    tools=[weather_tool],
    messages=[{"role": "user", "content": "What's the weather?"}],
)

if response.stop_reason == "tool_use":
    # Extrae y ejecuta la herramienta
    for content in response.content:
        if content.type == "tool_use":
            result = execute_tool(content.name, content.input)
            # Devuelve el resultado a Claude para la respuesta final

pause_turn

Se devuelve cuando el bucle de muestreo del lado del servidor alcanza su límite de iteraciones mientras ejecuta herramientas de servidor como búsqueda web o web fetch. El límite predeterminado es de 10 iteraciones por solicitud.

Cuando esto sucede, la respuesta puede contener un bloque server_tool_use sin un server_tool_result correspondiente. Para permitir que Claude termine de procesar, continúa la conversación enviando la respuesta de vuelta tal como está.

Python
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=[{"type": "web_search_20250305", "name": "web_search"}],
    messages=[{"role": "user", "content": "Search for latest AI news"}],
)

if response.stop_reason == "pause_turn":
    # Continúa la conversación enviando la respuesta de vuelta
    messages = [
        {"role": "user", "content": original_query},
        {"role": "assistant", "content": response.content},
    ]
    continuation = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        messages=messages,
        tools=[{"type": "web_search_20250305", "name": "web_search"}],
    )

Tu aplicación debe manejar pause_turn en cualquier bucle de agente que use herramientas de servidor. Simplemente agrega la respuesta del asistente a tu array de mensajes y haz otra solicitud a la API para permitir que Claude continúe.

refusal

Claude se negó a generar una respuesta. En Claude Fable 5, los clasificadores de seguridad devuelven esta razón de detención como una respuesta HTTP 200 normal, no como un error.

Python
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "[Unsafe request]"}],
)

if response.stop_reason == "refusal":
    # Claude se negó a responder
    print("Claude was unable to process this request")
    # Considera reformular o modificar la solicitud

Si encuentras razones de detención refusal con frecuencia mientras usas Claude Sonnet 4.5 u Opus 4.1 (obsoleto), puedes intentar actualizar tus llamadas a la API para usar Haiku 4.5 (claude-haiku-4-5-20251001), que tiene diferentes restricciones de uso. Obtén más información sobre cómo entender los filtros de seguridad de la API de Sonnet 4.5.

En un rechazo, el objeto stop_details identifica la categoría de política que lo activó. Las categorías y la estructura completa de la respuesta de rechazo se cubren en Rechazos y fallback. stop_details es null para todas las razones de detención distintas de refusal.

Una solicitud rechazada en Claude Fable 5 generalmente puede atenderse reintentando en otro modelo de Claude, y Rechazos y fallback muestra cómo configurar ese reintento, del lado del servidor o en tu cliente. Crédito de fallback cubre cómo evitar pagar dos veces el costo del caché de prompts cuando construyes el reintento tú mismo.

model_context_window_exceeded

Claude se detuvo porque alcanzó el límite de la "context window" (ventana de contexto) del modelo. Esto te permite solicitar el máximo de tokens posible sin conocer el tamaño exacto del input.

Python
# Solicitud con el máximo de tokens para obtener tanto como sea posible
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=20000,  # Python SDK requires streaming for max_tokens above ~21k (Opus 4.8 supports 128k with streaming)
    messages=[
        {"role": "user", "content": "Large input that uses most of context window..."}
    ],
)

if response.stop_reason == "model_context_window_exceeded":
    # La respuesta alcanzó el límite de la ventana de contexto antes de max_tokens
    print("Response reached model's context window limit")
    # La respuesta sigue siendo válida pero fue limitada por la ventana de contexto

Esta razón de detención está disponible de forma predeterminada en Sonnet 4.5 y modelos más recientes. Para modelos anteriores, usa el encabezado beta model-context-window-exceeded-2025-08-26 para habilitar este comportamiento.

Mejores prácticas para manejar razones de detención

1. Siempre verifica stop_reason

Acostúmbrate a verificar el stop_reason en tu lógica de manejo de respuestas:

def handle_response(response):
    if response.stop_reason == "tool_use":
        return handle_tool_use(response)
    elif response.stop_reason == "max_tokens":
        return handle_truncation(response)
    elif response.stop_reason == "model_context_window_exceeded":
        return handle_context_limit(response)
    elif response.stop_reason == "pause_turn":
        return handle_pause(response)
    elif response.stop_reason == "refusal":
        return handle_refusal(response)
    else:
        # Maneja end_turn y otros casos
        return response.content[0].text

2. Maneja las respuestas truncadas con elegancia

Cuando una respuesta se trunca debido a límites de tokens o de la ventana de contexto:

def handle_truncated_response(response):
    if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
        # Opción 1: Advertir al usuario sobre el límite específico
        if response.stop_reason == "max_tokens":
            message = "[Response truncated due to max_tokens limit]"
        else:
            message = "[Response truncated due to context window limit]"
        return f"{response.content[0].text}\n\n{message}"

        # Opción 2: Continuar la generación
        messages = [
            {"role": "user", "content": original_prompt},
            {"role": "assistant", "content": response.content[0].text},
        ]
        continuation = client.messages.create(
            model="claude-opus-4-8",
            max_tokens=1024,
            messages=messages + [{"role": "user", "content": "Please continue"}],
        )
        return response.content[0].text + continuation.content[0].text

3. Implementa lógica de reintento para pause_turn

Al usar herramientas de servidor, la API puede devolver pause_turn si el bucle de muestreo del lado del servidor alcanza su límite de iteraciones (predeterminado 10). Maneja esto continuando la conversación:

def handle_server_tool_conversation(client, user_query, tools, max_continuations=5):
    """
    Handle server tool conversations that may require multiple continuations.

    The server runs a sampling loop when executing server tools. If the loop
    reaches its iteration limit, the API returns pause_turn. Continue the
    conversation by sending the response back to let Claude finish.
    """
    messages = [{"role": "user", "content": user_query}]

    for _ in range(max_continuations):
        response = client.messages.create(
            model="claude-opus-4-8", max_tokens=1024, messages=messages, tools=tools
        )

        if response.stop_reason != "pause_turn":
            # Claude terminó de procesar: devuelve la respuesta final
            return response

        # pause_turn: reemplaza la lista completa de mensajes para mantener roles alternados
        messages = [
            {"role": "user", "content": user_query},
            {"role": "assistant", "content": response.content},
        ]

    # Se alcanzó el máximo de continuaciones: devuelve la última respuesta
    return response

Razones de detención vs. errores

Es importante distinguir entre los valores de stop_reason y los errores reales:

Razones de detención (respuestas exitosas)

  • Forman parte del cuerpo de la respuesta
  • Indican por qué la generación se detuvo normalmente
  • La respuesta contiene contenido válido

Errores (solicitudes fallidas)

  • Códigos de estado HTTP 4xx o 5xx
  • Indican fallos en el procesamiento de la solicitud
  • La respuesta contiene detalles del error
Python
import anthropic
from anthropic import Anthropic

client = Anthropic()

try:
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Hello!"}],
    )

    # Maneja la respuesta exitosa con stop_reason
    if response.stop_reason == "max_tokens":
        print("Response was truncated")

except anthropic.APIStatusError as e:
    # Maneja los errores reales
    if e.status_code == 429:
        print("Rate limit exceeded")
    elif e.status_code == 500:
        print("Server error")

Consideraciones de streaming

Al usar streaming, stop_reason es:

  • null en el evento inicial message_start
  • Proporcionado en el evento message_delta
  • No proporcionado en ningún otro evento
Python
from anthropic import Anthropic

client = Anthropic()

with client.messages.stream(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
) as stream:
    for event in stream:
        if event.type == "message_delta":
            stop_reason = event.delta.stop_reason
            if stop_reason:
                print(f"Stream ended with: {stop_reason}")

Patrones comunes

Manejo de flujos de trabajo de uso de herramientas

Más simple con tool runner: El siguiente ejemplo muestra el manejo manual de herramientas. Para la mayoría de los casos de uso, el tool runner maneja automáticamente la ejecución de herramientas con mucho menos código.

def complete_tool_workflow(client, user_query, tools):
    messages = [{"role": "user", "content": user_query}]

    while True:
        response = client.messages.create(
            model="claude-opus-4-8", max_tokens=1024, messages=messages, tools=tools
        )

        if response.stop_reason == "tool_use":
            # Ejecuta las herramientas y continúa
            tool_results = execute_tools(response.content)
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": tool_results})
        else:
            # Respuesta final
            return response

Asegurar respuestas completas

def get_complete_response(client, prompt, max_attempts=3):
    messages = [{"role": "user", "content": prompt}]
    full_response = ""

    for _ in range(max_attempts):
        response = client.messages.create(
            model="claude-opus-4-8", messages=messages, max_tokens=4096
        )

        full_response += response.content[0].text

        if response.stop_reason != "max_tokens":
            break

        # Continuar desde donde se quedó
        messages = [
            {"role": "user", "content": prompt},
            {"role": "assistant", "content": full_response},
            {"role": "user", "content": "Please continue from where you left off."},
        ]

    return full_response

Obtener el máximo de tokens sin conocer el tamaño del input

Con la razón de detención model_context_window_exceeded, puedes solicitar el máximo de tokens posible sin calcular el tamaño del input:

def get_max_possible_tokens(client, prompt):
    """
    Get as many tokens as possible within the model's context window
    without needing to calculate input token count
    """
    response = client.messages.create(
        model="claude-opus-4-8",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=20000,  # Python SDK requires streaming for max_tokens above ~21k
    )

    if response.stop_reason == "model_context_window_exceeded":
        # Se obtuvo el máximo de tokens posible dado el tamaño de entrada
        print(
            f"Generated {response.usage.output_tokens} tokens (context limit reached)"
        )
    elif response.stop_reason == "max_tokens":
        # Se obtuvieron exactamente los tokens solicitados
        print(f"Generated {response.usage.output_tokens} tokens (max_tokens reached)")
    else:
        # Finalización natural
        print(f"Generated {response.usage.output_tokens} tokens (natural completion)")

    return response.content[0].text

Al manejar adecuadamente los valores de stop_reason, puedes construir aplicaciones más robustas que manejen con elegancia diferentes escenarios de respuesta y proporcionen mejores experiencias de usuario.

Was this page helpful?

  • El campo stop_reason
  • Valores de stop reason
  • end_turn
  • max_tokens
  • stop_sequence
  • tool_use
  • pause_turn
  • refusal
  • model_context_window_exceeded
  • Mejores prácticas para manejar razones de detención
  • 1. Siempre verifica stop_reason
  • 2. Maneja las respuestas truncadas con elegancia
  • 3. Implementa lógica de reintento para pause_turn
  • Razones de detención vs. errores
  • Razones de detención (respuestas exitosas)
  • Errores (solicitudes fallidas)
  • Consideraciones de streaming
  • Patrones comunes
  • Manejo de flujos de trabajo de uso de herramientas
  • Asegurar respuestas completas
  • Obtener el máximo de tokens sin conocer el tamaño del input