Tool Use : Comment Claude exécute vos fonctions Python et TypeScript
Vous utilisez peut-être Claude pour analyser du texte ou générer du code. Mais saviez-vous qu’il peut aussi appeler vos propres fonctions ? Avec Tool Use, Claude devient un orchestrateur qui décide quand et comment utiliser vos outils. Je vais vous montrer comment ça marche concrètement.
Le concept : Claude comme chef d’orchestre
Tool Use, c’est l’API qui permet à Claude de demander l’exécution de fonctions que vous définissez. Le flow est simple :
- Vous envoyez une requête avec la liste des outils disponibles
- Claude analyse et décide s’il doit utiliser un outil
- Il vous renvoie une demande d’exécution (tool_use)
- Vous exécutez la fonction côté serveur
- Vous renvoyez le résultat à Claude
- Claude intègre le résultat dans sa réponse finale
C’est différent des simple prompts où vous collez des données. Ici, Claude prend des décisions : “J’ai besoin de cette info, je vais appeler cet outil”.
Votre premier outil en Python
Commençons par un exemple simple : un outil qui récupère la météo.
import anthropic
import json
client = anthropic.Anthropic(api_key="votre_cle")
# Définition de l'outil
tools = [
{
"name": "get_weather",
"description": "Récupère la météo actuelle pour une ville donnée",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Le nom de la ville"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "L'unité de température"
}
},
"required": ["city"]
}
}
]
# Fonction réelle qui sera exécutée
def get_weather(city, unit="celsius"):
# Ici vous appelleriez une vraie API météo
return {"city": city, "temperature": 22, "unit": unit, "condition": "ensoleillé"}
# Requête initiale
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "Quel temps fait-il à Paris ?"}]
)
print(f"Stop reason: {message.stop_reason}")
Si Claude décide d’utiliser l’outil, stop_reason sera tool_use au lieu de end_turn. Le message contiendra un bloc tool_use avec les paramètres.
Gérer la boucle d’exécution
Le vrai travail commence maintenant : gérer la boucle requête/réponse.
def process_tool_calls(message):
"""Exécute les outils demandés par Claude"""
tool_results = []
for block in message.content:
if block.type == "tool_use":
tool_name = block.name
tool_input = block.input
# Exécution de la fonction
if tool_name == "get_weather":
result = get_weather(**tool_input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result)
})
return tool_results
# Boucle complète
messages = [{"role": "user", "content": "Quel temps fait-il à Paris ?"}]
while True:
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
tools=tools,
messages=messages
)
if message.stop_reason == "tool_use":
# Claude veut utiliser un outil
messages.append({"role": "assistant", "content": message.content})
tool_results = process_tool_calls(message)
messages.append({"role": "user", "content": tool_results})
else:
# Claude a fini
print(message.content[0].text)
break
Ce pattern de boucle est essentiel. Claude peut enchaîner plusieurs appels d’outils avant de répondre.
Version TypeScript avec le SDK officiel
Le SDK TypeScript offre une API similaire. Voici le même exemple :
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const tools: Anthropic.Tool[] = [
{
name: 'get_weather',
description: 'Récupère la météo actuelle pour une ville donnée',
input_schema: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'Le nom de la ville',
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: 'L\'unité de température',
},
},
required: ['city'],
},
},
];
function getWeather(city: string, unit: string = 'celsius') {
return { city, temperature: 22, unit, condition: 'ensoleillé' };
}
async function runAssistant() {
const messages: Anthropic.MessageParam[] = [
{ role: 'user', content: 'Quel temps fait-il à Paris et Londres ?' },
];
while (true) {
const message = await client.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
tools,
messages,
});
if (message.stop_reason === 'tool_use') {
messages.push({ role: 'assistant', content: message.content });
const toolResults = message.content
.filter((block): block is Anthropic.ToolUseBlock => block.type === 'tool_use')
.map((block) => {
const result = getWeather(block.input.city, block.input.unit);
return {
type: 'tool_result' as const,
tool_use_id: block.id,
content: JSON.stringify(result),
};
});
messages.push({ role: 'user', content: toolResults });
} else {
console.log(message.content[0].text);
break;
}
}
}
runAssistant();
Notez comment Claude peut demander plusieurs villes en un seul appel. Il optimise automatiquement.
Cas d’usage avancés
1. Recherche et synthèse
Combinez un outil de recherche avec l’analyse de Claude :
tools = [
{
"name": "search_documentation",
"description": "Recherche dans la documentation technique",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"source": {
"type": "string",
"enum": ["github", "stackoverflow", "docs"]
}
},
"required": ["query"]
}
}
]
Claude peut enchaîner : rechercher sur GitHub, puis StackOverflow, puis synthétiser.
2. Exécution de code sécurisée
Créez un sandbox pour exécuter du code généré par Claude :
{
"name": "execute_python",
"description": "Exécute du code Python dans un environnement sécurisé",
"input_schema": {
"type": "object",
"properties": {
"code": {"type": "string"},
"timeout": {"type": "number", "default": 5}
},
"required": ["code"]
}
}
Attention : validez et sandboxez TOUJOURS le code avant exécution.
3. Workflows multi-étapes
Claude peut orchestrer des workflows complexes :
const tools = [
{ name: 'read_file', /* ... */ },
{ name: 'analyze_code', /* ... */ },
{ name: 'run_tests', /* ... */ },
{ name: 'generate_report', /* ... */ },
];
Demandez “Analyse ce projet et génère un rapport de qualité”. Claude va :
- Lire les fichiers pertinents
- Analyser le code
- Lancer les tests
- Générer le rapport
Tout ça sans que vous ayez à coder la logique d’orchestration.
Conseils pour des outils efficaces
1. Descriptions précises Claude décide grâce aux descriptions. Soyez spécifique :
- ✅ “Recherche des utilisateurs dans la base PostgreSQL par email ou ID”
- ❌ “Cherche des trucs”
2. Input schemas stricts Utilisez les enums, required, et descriptions pour chaque paramètre. Claude respecte le schéma.
3. Gestion d’erreurs Retournez des erreurs claires dans tool_result :
try:
result = ma_fonction(**tool_input)
content = json.dumps(result)
except Exception as e:
content = json.dumps({"error": str(e)})
is_error = True
4. Performance Si un outil est lent, indiquez-le dans la description. Claude peut décider de l’utiliser en dernier recours.
5. Composition Préférez plusieurs petits outils spécialisés qu’un gros outil généraliste. Claude orchestre mieux.
Conclusion
Tool Use transforme Claude en assistant capable d’interagir avec votre système. C’est la base de l’agentic AI : un modèle qui prend des décisions et agit.
Commencez simple : un ou deux outils bien définis. Puis ajoutez progressivement. Vous verrez Claude devenir de plus en plus autonome dans la résolution de problèmes complexes.
Le code complet de ces exemples est sur mon GitHub. N’hésitez pas à expérimenter et à partager vos cas d’usage sur X en me taguant @askjeanclaude !