Aller au contenu principal

Le workflow complet du Tool Use

Objectifs

  • Implementer le workflow complet en 4 etapes
  • Ecrire des messages tool_result correctement structures
  • Construire un chatbot qui utilise des outils
Boucle d'exécution du Tool Use avec Claude

Rappel des 4 etapes

Jusqu’ici, nous avons vu Claude demander l’utilisation d’un outil, mais nous n’avons pas renvoye le resultat a Claude pour qu’il formule sa reponse finale. Voici le workflow complet :

  1. Fournir les outils et le prompt (requete API)
  2. Claude demande un outil (reponse API)
  3. Executer l’outil et renvoyer le resultat (requete API)
  4. Claude formule sa reponse finale (reponse API)

Exemple : recherche Wikipedia

Construisons un assistant qui repond a des questions en consultant Wikipedia.

1. La fonction de recherche

import wikipedia

def get_article(search_term):
    """Recherche un article Wikipedia et retourne son contenu."""
    results = wikipedia.search(search_term)
    if not results:
        return "Aucun article trouve."
    page = wikipedia.page(results[0])
    return page.content[:5000]  # Limiter la taille

2. La definition de l’outil

tools = [{
    "name": "get_article",
    "description": "Recherche et retourne le contenu d'un article Wikipedia.",
    "input_schema": {
        "type": "object",
        "properties": {
            "search_term": {
                "type": "string",
                "description": "Le terme de recherche pour trouver l'article Wikipedia"
            }
        },
        "required": ["search_term"]
    }
}]

3. Envoyer le prompt avec l’outil

messages = [
    {"role": "user", "content": "Qui a gagne le tournoi des Masters 2024 ?"}
]

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1000,
    tools=tools,
    messages=messages
)

4. Gerer la demande d’outil de Claude

Claude repond avec un ToolUseBlock. On doit :

  1. Extraire les parametres
  2. Executer la fonction
  3. Renvoyer le resultat dans un format specifique
# Extraire la demande d'outil
tool_block = next(b for b in response.content if b.type == "tool_use")
tool_name = tool_block.name
tool_input = tool_block.input

# Executer la fonction
article_content = get_article(tool_input["search_term"])

# Construire le message tool_result
messages = [
    {"role": "user", "content": "Qui a gagne le tournoi des Masters 2024 ?"},
    {"role": "assistant", "content": response.content},
    {
        "role": "user",
        "content": [
            {
                "type": "tool_result",
                "tool_use_id": tool_block.id,
                "content": article_content
            }
        ]
    }
]

5. Obtenir la reponse finale de Claude

final_response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1000,
    tools=tools,
    messages=messages
)

print(final_response.content[0].text)

Structure du message tool_result

Le message tool_result est un message user qui contient un bloc special :

{
    "role": "user",
    "content": [
        {
            "type": "tool_result",
            "tool_use_id": "toolu_xxx",  # L'ID du ToolUseBlock
            "content": "Le contenu retourne par l'outil"
        }
    ]
}

Points importants :

  • Le tool_use_id doit correspondre exactement a l’id du ToolUseBlock de Claude
  • Le content peut etre une chaine ou une liste de blocs de contenu
  • Chaque tool_use dans la reponse de Claude necessite un tool_result correspondant

Implementation complete automatisee

Voici une fonction qui gere automatiquement le workflow complet :

def ask_with_tools(question, tools, tool_functions):
    """
    Pose une question a Claude avec des outils disponibles.
    tool_functions : dict mappant nom_outil -> fonction
    """
    messages = [{"role": "user", "content": question}]

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        tools=tools,
        messages=messages
    )

    # Boucle tant que Claude veut utiliser des outils
    while response.stop_reason == "tool_use":
        # Ajouter la reponse de Claude a l'historique
        messages.append({"role": "assistant", "content": response.content})

        # Traiter chaque demande d'outil
        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                # Executer l'outil
                func = tool_functions[block.name]
                result = func(**block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": str(result)
                })

        # Renvoyer les resultats
        messages.append({"role": "user", "content": tool_results})

        # Nouvelle requete
        response = client.messages.create(
            model="claude-sonnet-4-20250514",
            max_tokens=4096,
            tools=tools,
            messages=messages
        )

    # Retourner la reponse textuelle finale
    return response.content[0].text

Utilisation :

answer = ask_with_tools(
    "Qui a gagne le tournoi des Masters 2024 ?",
    tools=tools,
    tool_functions={"get_article": get_article}
)
print(answer)

Exercice

En utilisant le pattern ci-dessus, construisez un assistant de recherche qui :

  1. Accepte un sujet de recherche
  2. Demande a Claude de generer des titres d’articles Wikipedia pertinents
  3. Utilise un outil pour rechercher les vrais articles sur Wikipedia
  4. Sauvegarde les liens dans un fichier markdown
Voir un indice

Definissez un outil generate_wikipedia_reading_list qui accepte un topic (string) et une liste de article_titles (array de strings). Claude generera les titres, l’outil verifiera leur existence sur Wikipedia.