Lorsque vous effectuez une requête à l’API Messages, la réponse de Claude inclut un champ stop_reason qui indique pourquoi le modèle a cessé de générer sa réponse. Comprendre ces valeurs est crucial pour créer des applications robustes qui gèrent différents types de réponses de manière appropriée.

Pour plus de détails sur stop_reason dans la réponse de l’API, consultez la référence de l’API Messages.

Qu’est-ce que stop_reason ?

Le champ stop_reason fait partie de chaque réponse réussie de l’API Messages. Contrairement aux erreurs, qui indiquent des échecs dans le traitement de votre requête, stop_reason vous indique pourquoi Claude a terminé avec succès la génération de sa réponse.

Exemple de réponse
{
  "id": "msg_01234",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Voici la réponse à votre question..."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 100,
    "output_tokens": 50
  }
}

Valeurs de stop_reason

end_turn

La raison d’arrêt la plus courante. Indique que Claude a terminé sa réponse naturellement.

if response.stop_reason == "end_turn":
    # Traiter la réponse complète
    print(response.content[0].text)

max_tokens

Claude s’est arrêté car il a atteint la limite max_tokens spécifiée dans votre requête.

# Requête avec tokens limités
response = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    max_tokens=10,
    messages=[{"role": "user", "content": "Expliquez la physique quantique"}]
)

if response.stop_reason == "max_tokens":
    # La réponse a été tronquée
    print("La réponse a été coupée à la limite de tokens")
    # Envisagez de faire une autre requête pour continuer

stop_sequence

Claude a rencontré l’une de vos séquences d’arrêt personnalisées.

response = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    max_tokens=1024,
    stop_sequences=["END", "STOP"],
    messages=[{"role": "user", "content": "Générez du texte jusqu'à ce que vous disiez END"}]
)

if response.stop_reason == "stop_sequence":
    print(f"Arrêté à la séquence : {response.stop_sequence}")

tool_use

Claude appelle un outil et s’attend à ce que vous l’exécutiez.

response = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    max_tokens=1024,
    tools=[weather_tool],
    messages=[{"role": "user", "content": "Quel temps fait-il ?"}]
)

if response.stop_reason == "tool_use":
    # Extraire et exécuter l'outil
    for content in response.content:
        if content.type == "tool_use":
            result = execute_tool(content.name, content.input)
            # Renvoyer le résultat à Claude pour la réponse finale

pause_turn

Utilisé avec des outils serveur comme la recherche web lorsque Claude doit mettre en pause une opération de longue durée.

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": "Recherchez les dernières actualités sur l'IA"}]
)

if response.stop_reason == "pause_turn":
    # Continuer la conversation
    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"}]
    )

Bonnes pratiques pour gérer les raisons d’arrêt

1. Toujours vérifier stop_reason

Prenez l’habitude de vérifier le stop_reason dans votre logique de traitement des réponses :

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:
        # Gérer end_turn et autres cas
        return response.content[0].text

2. Gérer max_tokens avec élégance

Lorsqu’une réponse est tronquée en raison des limites de tokens :

def handle_truncated_response(response):
    if response.stop_reason == "max_tokens":
        # Option 1 : Avertir l'utilisateur
        return f"{response.content[0].text}\n\n[Réponse tronquée en raison de la longueur]"
        
        # Option 2 : Continuer la génération
        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": "Veuillez continuer"}]
        )
        return response.content[0].text + continuation.content[0].text

3. Implémenter une logique de nouvelle tentative pour pause_turn

Pour les outils serveur qui peuvent être mis en pause :

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

Raisons d’arrêt vs. erreurs

Il est important de distinguer entre les valeurs stop_reason et les erreurs réelles :

Raisons d’arrêt (réponses réussies)

  • Font partie du corps de la réponse
  • Indiquent pourquoi la génération s’est arrêtée normalement
  • La réponse contient un contenu valide

Erreurs (requêtes échouées)

  • Codes de statut HTTP 4xx ou 5xx
  • Indiquent des échecs de traitement de la requête
  • La réponse contient des détails d’erreur
try:
    response = client.messages.create(...)
    
    # Gérer une réponse réussie avec stop_reason
    if response.stop_reason == "max_tokens":
        print("La réponse a été tronquée")
    
except anthropic.APIError as e:
    # Gérer les erreurs réelles
    if e.status_code == 429:
        print("Limite de débit dépassée")
    elif e.status_code == 500:
        print("Erreur serveur")

Considérations pour le streaming

Lors de l’utilisation du streaming, stop_reason est :

  • null dans l’événement initial message_start
  • Fourni dans l’événement message_delta
  • Non-null dans tous les autres événements
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"Le flux s'est terminé avec : {stop_reason}")

Modèles courants

Gestion des flux de travail d’utilisation d’outils

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":
            # Exécuter les outils et continuer
            tool_results = execute_tools(response.content)
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": tool_results})
        else:
            # Réponse finale
            return response

Assurer des réponses complètes

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
            
        # Continuer à partir de l'endroit où il s'est arrêté
        messages = [
            {"role": "user", "content": prompt},
            {"role": "assistant", "content": full_response},
            {"role": "user", "content": "Veuillez continuer à partir de l'endroit où vous vous êtes arrêté."}
        ]
    
    return full_response

En gérant correctement les valeurs stop_reason, vous pouvez créer des applications plus robustes qui gèrent élégamment différents scénarios de réponse et offrent de meilleures expériences utilisateur.