Aller au contenu principal

Travailler avec les messages

Mis à jour le 29 juillet 2026

Objectifs

  • Comprendre le format de l’API Messages
  • Manipuler les objets de réponse
  • Construire un chatbot multi-tours

Le format des messages

Toute interaction avec Claude, du prompt isolé au chatbot complet, emprunte le même chemin : une liste de messages transmise à client.messages.create(). Chaque message est un dictionnaire à deux clés, et ce sont les deux seules requises.

  • role : "user" (vos messages) ou "assistant" (messages de Claude)
  • content : le texte du message

Un échange minimal ne contient donc qu’une entrée, celle de votre question :

messages = [
    {"role": "user", "content": "Quels sont les ingrédients du Dr. Pepper ?"}
]

Le point qui surprend le plus les débutants est que l’API ne conserve aucune mémoire d’un appel à l’autre. Pour que Claude tienne compte de ce qui a déjà été dit, vous devez lui renvoyer l’historique complet à chaque requête : c’est votre code qui porte la mémoire de la conversation, pas le serveur. Une conversation multi-tours prend donc la forme d’une liste qui s’allonge.

messages = [
    {"role": "user", "content": "Bonjour Claude !"},
    {"role": "assistant", "content": "Bonjour ! Comment puis-je vous aider ?"},
    {"role": "user", "content": "Raconte-moi un fait sur les furets."},
]

Les messages doivent toujours alterner entre user et assistant.

Inspecter la réponse

L’appel ne renvoie pas du texte brut mais un objet Message, dont le texte n’est qu’une propriété parmi d’autres. Prenons une requête simple pour l’examiner :

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1000,
    messages=[
        {"role": "user", "content": "Traduis bonjour en anglais. Réponds en un seul mot."}
    ]
)
PropriétéDescription
contentLe contenu généré (liste de blocs)
idIdentifiant unique du message
modelLe modèle utilisé
stop_reasonRaison de l’arrêt (end_turn, max_tokens, stop_sequence)
usageTokens d’entrée (input_tokens) et de sortie (output_tokens)

Deux de ces propriétés méritent votre attention en production. Le stop_reason vous dit si Claude a terminé son propos de lui-même ou s’il a été coupé par le plafond de tokens, ce qui change tout lorsque vous parsez la sortie. Et usage vous donne la consommation réelle de chaque appel, seule base fiable pour estimer un coût avant de passer à l’échelle. Le texte lui-même s’obtient en descendant dans le premier bloc de contenu :

print(response.content[0].text)

Erreurs courantes

Deux contraintes de format provoquent la quasi-totalité des erreurs de débutant, et toutes deux découlent de la même règle d’alternance. La première : la liste doit toujours commencer par un message user. Une conversation qui démarre sur une réplique de l’assistant n’a pas de sens du point de vue de l’API, puisque personne n’a rien demandé.

# ERREUR : commence par assistant
messages = [
    {"role": "assistant", "content": "Bonjour !"}
]

La seconde : deux messages consécutifs portant le même rôle provoquent une erreur. Si votre utilisateur envoie deux phrases coup sur coup, votre code doit les fusionner en un seul message plutôt que de les empiler.

# ERREUR : deux messages user consecutifs
messages = [
    {"role": "user", "content": "Salut !"},
    {"role": "user", "content": "Ça va ?"}
]

Techniques avancées avec les messages

Mettre des mots dans la bouche de Claude

Rien ne vous oblige à terminer la liste par un message user. En ajoutant un message assistant en dernière position, vous forcez Claude à poursuivre à partir de ce texte au lieu de repartir de zéro. C’est le moyen le plus direct d’imposer un format de sortie : commencez la réponse par { et vous obtiendrez du JSON, commencez par un vers et vous obtiendrez la suite du poème.

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=500,
    messages=[
        {"role": "user", "content": "Génère un beau haiku"},
        {"role": "assistant", "content": "l'air frais de montagne"}
    ]
)
# Claude completera le haiku a partir de cette premiere ligne
print("l'air frais de montagne" + response.content[0].text)

Notez la reconstitution manuelle à la dernière ligne : la réponse ne contient que la suite, pas l’amorce que vous avez fournie.

Prompting few-shot

La même mécanique permet de montrer plutôt que d’expliquer. En glissant dans l’historique quelques paires question-réponse fictives, vous démontrez le format attendu sans écrire la moindre consigne. Ici, trois exemples suffisent à obtenir une classification de sentiment en un mot majuscule, sans jamais avoir demandé « réponds en un mot majuscule ».

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=500,
    messages=[
        {"role": "user", "content": "Ce produit est nul, je deteste !"},
        {"role": "assistant", "content": "NEGATIF"},
        {"role": "user", "content": "J'adore ce produit, il est genial !"},
        {"role": "assistant", "content": "POSITIF"},
        {"role": "user", "content": "Le nouveau modèle est vraiment top !"},
    ]
)
print(response.content[0].text)  # POSITIF

Exercice : construire un chatbot

Tout ce qui précède se rassemble dans un seul exercice : un chatbot en ligne de commande qui garde le fil de la discussion. La boucle est toujours la même — vous maintenez une liste pour l’historique, vous demandez une entrée utilisateur avec input(), vous envoyez l’historique complet à Claude, vous affichez la réponse, vous ajoutez cette réponse à l’historique, et vous répétez tant que l’utilisateur ne demande pas à sortir. Sans la cinquième étape, votre chatbot oubliera chaque phrase aussitôt prononcée.

Voir la solution
from anthropic import Anthropic

client = Anthropic()
conversation_history = []

while True:
    user_input = input("Vous : ")

    if user_input.lower() == "quit":
        print("Conversation terminee.")
        break

    conversation_history.append({"role": "user", "content": user_input})

    response = client.messages.create(
        model="claude-sonnet-5",
        messages=conversation_history,
        max_tokens=500
    )

    assistant_response = response.content[0].text
    print(f"Claude : {assistant_response}")
    conversation_history.append({"role": "assistant", "content": assistant_response})