Loading...
  • Construir
  • Administración
  • Modelos y precios
  • SDKs de cliente
  • Referencia de API
Search...
⌘K
Log in
Gestionar razones de parada
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
Construir/Construir con Claude

Manejo de razones de parada

Comprende los valores de stop_reason en las respuestas de la API de Messages para construir aplicaciones robustas que manejen diferentes tipos de respuestas apropiadamente.

Cuando realizas 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 diferentes tipos de respuestas apropiadamente.

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 es 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 dice por qué Claude completó exitosamente 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 parada más común. Indica que Claude terminó su respuesta naturalmente.

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":
    # Process the complete response
    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 típicamente sucede 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 resultados de herramientas (Claude aprende a esperar que el usuario siempre inserte texto después de resultados de herramientas, así que termina su turno para seguir el patrón)
  • Enviar la respuesta completada de Claude sin agregar nada (Claude ya decidió que está hecho, así que permanecerá hecho)

Cómo prevenir respuestas vacías:

# INCORRECT: Adding text immediately after 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
            },
        ],
    },
]

# CORRECT: Send tool results directly without additional text
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
]


# If you still get empty responses after fixing the above:
def handle_empty_response(client, messages):
    response = client.messages.create(
        model="claude-opus-4-7", max_tokens=1024, messages=messages
    )

    # Check if response is empty
    if response.stop_reason == "end_turn" and not response.content:
        # INCORRECT: Don't just retry with the empty response
        # This won't work because Claude already decided it's done

        # CORRECT: Add a continuation prompt in a NEW user message
        messages.append({"role": "user", "content": "Please continue"})

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

    return response

Mejores prácticas:

  1. Nunca agregues bloques de texto inmediatamente después de resultados de herramientas - Esto enseña a Claude a esperar entrada del usuario después de cada uso de herramienta
  2. No reintentar respuestas vacías sin modificación - Simplemente enviar la respuesta vacía de vuelta no ayudará
  3. Usar indicadores de continuación como último recurso - Solo si las correcciones anteriores no resuelven el problema

max_tokens

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

Python
# Request with limited tokens
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=10,
    messages=[{"role": "user", "content": "Explain quantum physics"}],
)

if response.stop_reason == "max_tokens":
    # Response was truncated
    print("Response was cut off at token limit")
    # Consider making another request to continue

Bloques de uso de herramientas incompletos

Si la respuesta de Claude se corta debido a alcanzar 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.

# Check if response was truncated during tool use
if response.stop_reason == "max_tokens":
    # Check if the last content block is an incomplete tool_use
    last_block = response.content[-1]
    if last_block.type == "tool_use":
        # Send the request with higher max_tokens
        response = client.messages.create(
            model="claude-opus-4-7",
            max_tokens=4096,  # Increased limit
            messages=messages,
            tools=tools,
        )

stop_sequence

Claude encontró una de tus secuencias de parada personalizadas.

Python
response = client.messages.create(
    model="claude-opus-4-7",
    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 implementaciones de uso de herramientas, recomendamos usar el ejecutor de herramientas que maneja automáticamente la ejecución de herramientas, el formato de resultados y la gestión de conversaciones.

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":
    # Extract and execute the tool
    for content in response.content:
        if content.type == "tool_use":
            result = execute_tool(content.name, content.input)
            # Return result to Claude for final response

pause_turn

Se devuelve cuando el bucle de muestreo del lado del servidor alcanza su límite de iteraciones mientras ejecuta herramientas del servidor como búsqueda web o búsqueda web. El límite predeterminado es 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 el procesamiento, continúa la conversación enviando la respuesta tal como está.

Python
response = client.messages.create(
    model="claude-opus-4-7",
    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":
    # Continue the conversation by sending the response back
    messages = [
        {"role": "user", "content": original_query},
        {"role": "assistant", "content": response.content},
    ]
    continuation = client.messages.create(
        model="claude-opus-4-7",
        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 del servidor. Simplemente agrega la respuesta del asistente a tu matriz de mensajes y realiza otra solicitud de API para permitir que Claude continúe.

refusal

Claude se negó a generar una respuesta debido a preocupaciones de seguridad.

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

if response.stop_reason == "refusal":
    # Claude declined to respond
    print("Claude was unable to process this request")
    # Consider rephrasing or modifying the request

Si encuentras razones de parada refusal frecuentemente mientras usas Claude Sonnet 4.5 u Opus 4.1, puedes intentar actualizar tus llamadas de API para usar Haiku 4.5 (claude-haiku-4-5-20251001), que tiene restricciones de uso diferentes. Aprende más sobre entender los filtros de seguridad de API de Sonnet 4.5.

Para obtener más información sobre rechazos desencadenados por filtros de seguridad de API para Claude Sonnet 4.5, consulta Entender los filtros de seguridad de API de Sonnet 4.5.

model_context_window_exceeded

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

Python
# Request with maximum tokens to get as much as possible
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=64000,  # Practical non-streaming ceiling (Opus 4.7 supports 128K with streaming)
    messages=[
        {"role": "user", "content": "Large input that uses most of context window..."}
    ],
)

if response.stop_reason == "model_context_window_exceeded":
    # Response hit context window limit before max_tokens
    print("Response reached model's context window limit")
    # The response is still valid but was limited by context window

Esta razón de parada está disponible por defecto en Sonnet 4.5 y modelos más nuevos. 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 parada

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:
        # Handle end_turn and other cases
        return response.content[0].text

2. Maneja respuestas truncadas elegantemente

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

def handle_truncated_response(response):
    if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
        # Option 1: Warn the user about the specific limit
        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}"

        # Option 2: Continue generation
        messages = [
            {"role": "user", "content": original_prompt},
            {"role": "assistant", "content": response.content[0].text},
        ]
        continuation = client.messages.create(
            model="claude-opus-4-7",
            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

Cuando uses herramientas del 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-7", messages=messages, tools=tools
        )

        if response.stop_reason != "pause_turn":
            # Claude finished processing - return the final response
            return response

        # pause_turn: replace the full message list to maintain alternating roles
        messages = [
            {"role": "user", "content": user_query},
            {"role": "assistant", "content": response.content},
        ]

    # Reached max continuations - return the last response
    return response

Razones de parada vs. errores

Es importante distinguir entre valores de stop_reason y errores reales:

Razones de parada (respuestas exitosas)

  • 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 solicitudes
  • 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!"}],
    )

    # Handle successful response with stop_reason
    if response.stop_reason == "max_tokens":
        print("Response was truncated")

except anthropic.APIError as e:
    # Handle actual errors
    if e.status_code == 429:
        print("Rate limit exceeded")
    elif e.status_code == 500:
        print("Server error")

Consideraciones de streaming

Cuando usas 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 ejecutor de herramientas: El ejemplo a continuación muestra manejo manual de herramientas. Para la mayoría de casos de uso, el ejecutor de herramientas 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-7", messages=messages, tools=tools
        )

        if response.stop_reason == "tool_use":
            # Execute tools and continue
            tool_results = execute_tools(response.content)
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": tool_results})
        else:
            # Final response
            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-7", messages=messages, max_tokens=4096
        )

        full_response += response.content[0].text

        if response.stop_reason != "max_tokens":
            break

        # Continue from where it left off
        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 de entrada

Con la razón de parada model_context_window_exceeded, puedes solicitar el máximo de tokens posible sin calcular el recuento de tokens de entrada:

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-7",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=64000,  # Practical non-streaming ceiling (Opus 4.7 supports 128K with streaming)
    )

    if response.stop_reason == "model_context_window_exceeded":
        # Got the maximum possible tokens given input size
        print(
            f"Generated {response.usage.output_tokens} tokens (context limit reached)"
        )
    elif response.stop_reason == "max_tokens":
        # Got exactly the requested tokens
        print(f"Generated {response.usage.output_tokens} tokens (max_tokens reached)")
    else:
        # Natural completion
        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 elegantemente 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 parada
  • 1. Siempre verifica stop_reason
  • 2. Maneja respuestas truncadas elegantemente
  • 3. Implementa lógica de reintento para pause_turn
  • Razones de parada vs. errores
  • Razones de parada (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 de entrada