Loading...
  • Construir
  • Admin
  • Modelos e preços
  • SDKs do cliente
  • Referência da API
Search...
⌘K
Log in
Gerenciando motivos 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/Construindo com Claude

Tratando razões de parada

Entenda os valores de stop_reason da API de Mensagens do Claude e como lidar com diferentes tipos de respostas

Quando você faz uma solicitação para a API de Mensagens, a resposta do Claude inclui um campo stop_reason que indica por que o modelo parou de gerar sua resposta. Compreender esses valores é crucial para construir aplicações robustas que lidam com diferentes tipos de resposta apropriadamente.

Para detalhes sobre stop_reason na resposta da API, consulte a referência da API de Mensagens.

O campo stop_reason

O campo stop_reason faz parte de toda resposta bem-sucedida da API de Mensagens. Diferentemente de erros, que indicam falhas no processamento de sua solicitação, stop_reason informa por que Claude completou com sucesso a geração de sua resposta.

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

A razão de parada mais comum. Indica que Claude terminou sua resposta 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)

Respostas vazias com end_turn

Às vezes Claude retorna uma resposta vazia (exatamente 2-3 tokens sem conteúdo) com stop_reason: "end_turn". Isso normalmente acontece quando Claude interpreta que o turno do assistente está completo, particularmente após resultados de ferramentas.

Causas comuns:

  • Adicionar blocos de texto imediatamente após resultados de ferramentas (Claude aprende a esperar que o usuário sempre insira texto após resultados de ferramentas, então encerra seu turno para seguir o padrão)
  • Enviar a resposta completa do Claude de volta sem adicionar nada (Claude já decidiu que terminou, então permanecerá terminado)

Como prevenir respostas vazias:

# 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

Melhores práticas:

  1. Nunca adicione blocos de texto imediatamente após resultados de ferramentas - Isso ensina Claude a esperar entrada do usuário após cada uso de ferramenta
  2. Não tente novamente respostas vazias sem modificação - Simplesmente enviar a resposta vazia de volta não ajudará
  3. Use prompts de continuação como último recurso - Apenas se as correções acima não resolverem o problema

max_tokens

Claude parou porque atingiu o limite max_tokens especificado em sua solicitação.

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

Blocos de uso de ferramenta incompletos

Se a resposta do Claude for cortada devido ao limite max_tokens, e a resposta truncada contiver um bloco de uso de ferramenta incompleto, você precisará tentar novamente a solicitação com um valor max_tokens mais alto para obter o uso de ferramenta completo.

stop_sequence

Claude encontrou uma de suas sequências 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á chamando uma ferramenta e espera que você a execute.

Para a maioria das implementações de uso de ferramentas, recomendamos usar o tool runner que lida automaticamente com execução de ferramentas, formatação de resultados e gerenciamento de conversas.

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

Retornado quando o loop de amostragem do lado do servidor atinge seu limite de iteração ao executar ferramentas de servidor como busca na web ou busca na web. O limite padrão é 10 iterações por solicitação.

Quando isso acontece, a resposta pode conter um bloco server_tool_use sem um server_tool_result correspondente. Para deixar Claude terminar o processamento, continue a conversa enviando a resposta de volta 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"}],
    )

Sua aplicação deve lidar com pause_turn em qualquer loop de agente que use ferramentas de servidor. Simplesmente adicione a resposta do assistente ao seu array de mensagens e faça outra solicitação de API para deixar Claude continuar.

refusal

Claude recusou gerar uma resposta devido a preocupações de segurança.

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

Se você encontrar razões de parada refusal frequentemente ao usar Claude Sonnet 4.5 ou Opus 4.1, você pode tentar atualizar suas chamadas de API para usar Haiku 4.5 (claude-haiku-4-5-20251001), que tem restrições de uso diferentes. Saiba mais sobre entender os filtros de segurança da API do Sonnet 4.5.

Para saber mais sobre recusas acionadas pelos filtros de segurança da API para Claude Sonnet 4.5, consulte Entender os Filtros de Segurança da API do Sonnet 4.5.

model_context_window_exceeded

Claude parou porque atingiu o limite da janela de contexto do modelo. Isso permite que você solicite o máximo de tokens possível sem conhecer o tamanho exato da 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ão de parada está disponível por padrão em Sonnet 4.5 e modelos mais novos. Para modelos anteriores, use o cabeçalho beta model-context-window-exceeded-2025-08-26 para ativar esse comportamento.

Melhores práticas para lidar com razões de parada

1. Sempre verifique stop_reason

Faça um hábito verificar o stop_reason em sua lógica de tratamento de resposta:

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. Lidar com respostas truncadas graciosamente

Quando uma resposta é truncada devido a limites de token ou janela 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. Implementar lógica de retry para pause_turn

Ao usar ferramentas de servidor, a API pode retornar pause_turn se o loop de amostragem do lado do servidor atingir seu limite de iteração (padrão 10). Lidar com isso continuando a conversa:

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

Razões de parada vs. erros

É importante distinguir entre valores de stop_reason e erros reais:

Razões de parada (respostas bem-sucedidas)

  • Parte do corpo da resposta
  • Indicam por que a geração parou normalmente
  • A resposta contém conteúdo válido

Erros (solicitações falhadas)

  • Códigos de status HTTP 4xx ou 5xx
  • Indicam falhas no processamento de solicitações
  • A resposta contém detalhes do erro
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")

Considerações de streaming

Ao usar streaming, stop_reason é:

  • null no evento inicial message_start
  • Fornecido no evento message_delta
  • Não fornecido em nenhum outro 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}")

Padrões comuns

Lidar com fluxos de trabalho de uso de ferramentas

Mais simples com tool runner: O exemplo abaixo mostra tratamento manual de ferramentas. Para a maioria dos casos de uso, o tool runner lida automaticamente com execução de ferramentas com muito 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

Garantindo respostas 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

Obtendo tokens máximos sem conhecer o tamanho da entrada

Com a razão de parada model_context_window_exceeded, você pode solicitar o máximo de tokens possível sem calcular a contagem 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

Ao lidar adequadamente com valores de stop_reason, você pode construir aplicações mais robustas que lidam graciosamente com diferentes cenários de resposta e proporcionam melhores experiências ao usuário.

Was this page helpful?

  • O campo stop_reason
  • Valores de stop_reason
  • end_turn
  • max_tokens
  • stop_sequence
  • tool_use
  • pause_turn
  • refusal
  • model_context_window_exceeded
  • Melhores práticas para lidar com razões de parada
  • 1. Sempre verifique stop_reason
  • 2. Lidar com respostas truncadas graciosamente
  • 3. Implementar lógica de retry para pause_turn
  • Razões de parada vs. erros
  • Razões de parada (respostas bem-sucedidas)
  • Erros (solicitações falhadas)
  • Considerações de streaming
  • Padrões comuns
  • Lidar com fluxos de trabalho de uso de ferramentas
  • Garantindo respostas completas
  • Obtendo tokens máximos sem conhecer o tamanho da entrada
# 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,
        )