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. Entender esses valores é crucial para construir aplicações robustas que lidem adequadamente com diferentes tipos de resposta.

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

O que é stop_reason?

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

Exemplo de resposta
{
  "id": "msg_01234",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Aqui está a resposta para sua pergunta..."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 100,
    "output_tokens": 50
  }
}

Valores de stop reason

end_turn

O motivo de parada mais comum. Indica que o Claude terminou sua resposta naturalmente.

if response.stop_reason == "end_turn":
    # Processa a resposta completa
    print(response.content[0].text)

max_tokens

O Claude parou porque atingiu o limite de max_tokens especificado na sua solicitação.

# Solicitação com tokens limitados
response = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    max_tokens=10,
    messages=[{"role": "user", "content": "Explique a física quântica"}]
)

if response.stop_reason == "max_tokens":
    # A resposta foi truncada
    print("A resposta foi cortada no limite de tokens")
    # Considere fazer outra solicitação para continuar

stop_sequence

O Claude encontrou uma das suas sequências de parada personalizadas.

response = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    max_tokens=1024,
    stop_sequences=["FIM", "PARE"],
    messages=[{"role": "user", "content": "Gere texto até você dizer FIM"}]
)

if response.stop_reason == "stop_sequence":
    print(f"Parou na sequência: {response.stop_sequence}")

tool_use

O Claude está chamando uma ferramenta e espera que você a execute.

response = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    max_tokens=1024,
    tools=[weather_tool],
    messages=[{"role": "user", "content": "Como está o clima?"}]
)

if response.stop_reason == "tool_use":
    # Extrai e executa a ferramenta
    for content in response.content:
        if content.type == "tool_use":
            result = execute_tool(content.name, content.input)
            # Retorna o resultado para o Claude para resposta final

pause_turn

Usado com ferramentas de servidor como pesquisa na web quando o Claude precisa pausar uma operação de longa duração.

response = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    max_tokens=1024,
    tools=[{"type": "web_search_20250305", "name": "web_search"}],
    messages=[{"role": "user", "content": "Pesquise as últimas notícias sobre IA"}]
)

if response.stop_reason == "pause_turn":
    # Continua a conversa
    messages = [
        {"role": "user", "content": original_query},
        {"role": "assistant", "content": response.content}
    ]
    continuation = client.messages.create(
        model="claude-3-7-sonnet-20250219",
        messages=messages,
        tools=[{"type": "web_search_20250305", "name": "web_search"}]
    )

Melhores práticas para lidar com motivos de parada

1. Sempre verifique stop_reason

Crie o hábito de verificar o stop_reason na 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 == "pause_turn":
        return handle_pause(response)
    else:
        # Trata end_turn e outros casos
        return response.content[0].text

2. Trate max_tokens com elegância

Quando uma resposta é truncada devido aos limites de token:

def handle_truncated_response(response):
    if response.stop_reason == "max_tokens":
        # Opção 1: Avisar o usuário
        return f"{response.content[0].text}\n\n[Resposta truncada devido ao comprimento]"
        
        # Opção 2: Continuar a geração
        messages = [
            {"role": "user", "content": original_prompt},
            {"role": "assistant", "content": response.content[0].text}
        ]
        continuation = client.messages.create(
            model="claude-3-7-sonnet-20250219",
            max_tokens=1024,
            messages=messages + [{"role": "user", "content": "Por favor, continue"}]
        )
        return response.content[0].text + continuation.content[0].text

3. Implemente lógica de repetição para pause_turn

Para ferramentas de servidor que podem pausar:

def handle_paused_conversation(initial_response, max_retries=3):
    response = initial_response
    messages = [{"role": "user", "content": original_query}]
    
    for attempt in range(max_retries):
        if response.stop_reason != "pause_turn":
            break
            
        messages.append({"role": "assistant", "content": response.content})
        response = client.messages.create(
            model="claude-3-7-sonnet-20250219",
            messages=messages,
            tools=original_tools
        )
    
    return response

Motivos de parada vs. erros

É importante distinguir entre valores de stop_reason e erros reais:

Motivos 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 com falha)

  • Códigos de status HTTP 4xx ou 5xx
  • Indicam falhas no processamento da solicitação
  • A resposta contém detalhes do erro
try:
    response = client.messages.create(...)
    
    # Trata resposta bem-sucedida com stop_reason
    if response.stop_reason == "max_tokens":
        print("A resposta foi truncada")
    
except anthropic.APIError as e:
    # Trata erros reais
    if e.status_code == 429:
        print("Limite de taxa excedido")
    elif e.status_code == 500:
        print("Erro do servidor")

Considerações sobre streaming

Ao usar streaming, stop_reason é:

  • null no evento inicial message_start
  • Fornecido no evento message_delta
  • Não-nulo em todos os outros eventos
with client.messages.stream(...) as stream:
    for event in stream:
        if event.type == "message_delta":
            stop_reason = event.delta.stop_reason
            if stop_reason:
                print(f"Stream terminou com: {stop_reason}")

Padrões comuns

Lidando com fluxos de trabalho de ferramentas

def complete_tool_workflow(client, user_query, tools):
    messages = [{"role": "user", "content": user_query}]
    
    while True:
        response = client.messages.create(
            model="claude-3-7-sonnet-20250219",
            messages=messages,
            tools=tools
        )
        
        if response.stop_reason == "tool_use":
            # Executa ferramentas e continua
            tool_results = execute_tools(response.content)
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": tool_results})
        else:
            # Resposta final
            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-3-7-sonnet-20250219",
            messages=messages,
            max_tokens=4096
        )
        
        full_response += response.content[0].text
        
        if response.stop_reason != "max_tokens":
            break
            
        # Continua de onde parou
        messages = [
            {"role": "user", "content": prompt},
            {"role": "assistant", "content": full_response},
            {"role": "user", "content": "Por favor, continue de onde você parou."}
        ]
    
    return full_response

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