Tool calling : la mecanique fondamentale
Un LLM seul ne peut que generer du texte. Le tool calling lui donne des mains — la capacite d’agir sur le monde exterieur : chercher sur le web, lire une base de donnees, envoyer un email, executer du code.
Le principe est simple : tu decris tes fonctions au modele, et il decide quand et comment les appeler.
Tool definition
Chaque outil est decrit en JSON Schema. Le modele lit les descriptions et les utilise pour decider quel outil appeler et avec quels arguments.
Trois elements cles dans une definition d’outil :
- name — identifiant unique, court et explicite
- description — phrase claire qui explique ce que l’outil fait et quand l’utiliser
- input_schema — les parametres attendus, avec types et descriptions
La qualite des descriptions est critique. Un modele choisit ses outils en fonction de ce qu’il comprend de leur utilite. Une description vague produit des appels incoherents.
Tool use loop
Le tool calling n’est pas un appel unique — c’est une boucle :
- Tu envoies la question de l’utilisateur au LLM
- Le LLM analyse la question et decide d’appeler un outil
- Tu executes l’outil cote serveur
- Tu renvoies le resultat au LLM
- Le LLM decide : appeler un autre outil, ou donner la reponse finale
- La boucle continue jusqu’a
end_turn
Parallel tool calls
Le modele peut demander plusieurs outils simultanement dans une seule reponse. Par exemple, chercher sur Google et lire une URL en meme temps. C’est une optimisation critique en production — chaque aller-retour API coute du temps et des tokens.
Stop reason
Le modele signale son intention via le stop_reason :
tool_use— le modele veut appeler un ou plusieurs outils. Tu dois les executer et renvoyer les resultats.end_turn— le modele a termine. La boucle s’arrete.
C’est le mecanisme qui rend la boucle deterministe : tu sais toujours si tu dois continuer ou non.
Full agent loop
const tools = [
{
name: 'search_web',
description: 'Chercher des informations recentes sur le web',
input_schema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Requete de recherche precise' }
},
required: ['query']
}
},
{
name: 'read_url',
description: "Lire le contenu d'une page web",
input_schema: {
type: 'object',
properties: {
url: { type: 'string', description: 'URL complete a lire' }
},
required: ['url']
}
}
]
async function runAgent(userQuery: string, maxIterations = 5) {
let messages = [{ role: 'user', content: userQuery }]
let iterations = 0
while (iterations < maxIterations) {
const response = await claude.messages.create({ tools, messages })
if (response.stop_reason === 'end_turn') {
return response.content
}
if (response.stop_reason === 'tool_use') {
const toolCalls = response.content.filter(b => b.type === 'tool_use')
const results = await Promise.all(
toolCalls.map(async (call) => ({
type: 'tool_result',
tool_use_id: call.id,
content: await executeTool(call.name, call.input)
}))
)
messages = [
...messages,
{ role: 'assistant', content: response.content },
{ role: 'user', content: results }
]
}
iterations++
}
throw new Error('Max iterations reached — agent loop detected')
}
Points cles de cette implementation :
Promise.allsur les tool calls — les outils s’executent en parallelemaxIterations— protection contre les boucles infinies- Messages accumules — le LLM voit tout l’historique a chaque iteration
- Error throw — si l’agent boucle, on coupe proprement
Le pattern ReAct
ReAct (Reasoning + Acting) est le pattern fondamental des agents IA. L’idee : forcer le modele a ecrire sa reflexion avant d’agir. Ca reduit les erreurs, ca rend le comportement debugable, et ca produit de meilleurs resultats.
Sans ReAct, un agent agit a l’aveugle. Avec ReAct, il raisonne a voix haute.
Le cycle Penser-Agir-Observer
A chaque iteration, l’agent suit trois etapes :
- Penser — “Que sais-je ? Que me manque-t-il ? Quel outil utiliser ?”
- Agir — Appeler l’outil choisi avec les bons arguments
- Observer — Analyser le resultat et decider de la suite
Ce cycle se repete jusqu’a ce que l’agent ait assez d’information pour repondre.
Scratchpad
Les pensees intermediaires de l’agent constituent son scratchpad. En production, logger systematiquement ce scratchpad est non negociable. C’est le seul moyen de comprendre pourquoi un agent a pris telle decision.
ReAct system prompt
const reactSystemPrompt = `Tu as acces a des outils pour repondre aux questions.
Pour chaque tache, tu DOIS suivre ce processus :
1. PENSER : "Que sais-je ? Que dois-je chercher ?"
2. AGIR : appeler l'outil le plus approprie
3. OBSERVER : analyser le resultat obtenu
4. REPETER si necessaire, ou donner la reponse finale
Prefixe tes reflexions par [Reflexion] et ta reponse finale par [Reponse finale].
Ne donne la reponse finale que quand tu as suffisamment d'information.`
Max iterations et early stopping
Deux garde-fous indispensables :
- Max iterations — Toujours definir une limite dure. 5 a 10 iterations suffisent pour la majorite des cas.
- Early stopping — Detecter quand l’agent tourne en rond : memes outils appeles avec les memes arguments, resultats identiques. Interrompre proprement et retourner ce qui a ete collecte.
Workflows et orchestration
Un agent unique avec beaucoup d’outils, ca marche pour des taches simples. Pour des taches complexes, il faut orchestrer plusieurs LLMs ensemble. Quatre patterns fondamentaux.
Prompt chaining
La sortie du LLM A devient l’entree du LLM B. Chaque etape a un role precis et des instructions optimisees.
Pourquoi c’est mieux qu’un mega-prompt : un prompt de 2000 mots qui essaie de tout faire produit des resultats mediocres. Decomposer en etapes courtes et precises donne des resultats bien superieurs — et c’est plus facile a debugger.
Exemple : generer un article → le relire → l’optimiser SEO → le formater. Quatre prompts simples au lieu d’un prompt monstre.
Routing
Un LLM classifie la requete entrante, puis la route vers un agent specialise. Plus efficace qu’un agent generaliste qui essaie de tout faire.
async function routeQuery(query: string) {
const category = await classifyQuery(query)
const agents = {
facturation: billingAgent,
technique: techAgent,
general: generalAgent
}
return agents[category]?.(query) ?? generalAgent(query)
}
Le LLM de classification peut etre petit et rapide (Haiku). Les agents specialises utilisent un modele plus puissant si necessaire.
Parallelisation
Lancer plusieurs appels LLM simultanement puis agreger les resultats. Gain de temps x3 a x5 sur les taches independantes.
async function analyzeDocument(text: string) {
const [summary, sentiment, keyPoints, actionItems] = await Promise.all([
summarize(text),
analyzeSentiment(text),
extractKeyPoints(text),
extractActionItems(text)
])
return { summary, sentiment, keyPoints, actionItems }
}
Quatre analyses en parallele au lieu de quatre en sequence. Meme cout en tokens, temps divise par quatre.
Orchestrator-worker
Un LLM “chef” decompose une tache complexe et pilote des LLM “workers” specialises. Le chef decide de la strategie, les workers executent.
Exemple : un orchestrateur recoit “Refactorise ce module”. Il analyse le code, identifie 4 sous-taches (renommer les variables, extraire les fonctions, ajouter les types, ecrire les tests), et les distribue a des workers specialises.
Comparaison des patterns
| Pattern | Cas d’usage | Complexite | Quand l’utiliser |
|---|---|---|---|
| Prompt chaining | Taches sequentielles decomposables | Faible | Pipeline de contenu, ETL de donnees, validation multi-etapes |
| Routing | Requetes heterogenes a diriger | Faible | Support client, assistants multi-domaines, triage automatique |
| Parallelisation | Analyses independantes simultanees | Moyenne | Analyse de documents, extraction multi-criteres, audits |
| Orchestrator-worker | Taches complexes a decomposer dynamiquement | Elevee | Refactoring, recherche approfondie, projets multi-fichiers |
La regle : commence toujours par le pattern le plus simple qui resout ton probleme. Prompt chaining couvre 70% des cas. L’orchestrator-worker est puissant mais complexe a debugger.
MCP et memoire long-terme
MCP (Model Context Protocol)
MCP est un standard open source initie par Anthropic en 2024 pour connecter des LLMs a des services externes de maniere standardisee. Au lieu de coder une integration custom pour chaque outil, tu decris tes outils une fois via le protocole MCP, et ils sont utilisables par n’importe quel client compatible.
Concretement, MCP permet a un agent de se connecter a GitHub, Slack, des bases de donnees, des APIs metier — sans ecrire de glue code pour chaque integration.
Outils a integrer dans un agent reel
Voici les categories d’outils les plus utiles en production :
- Recherche web — Tavily API, Brave Search API, Serper. Donnent au modele un acces a l’information en temps reel.
- Lecture d’URLs — fetch + html-to-text (Readability.js). Transformer une page web en texte lisible par le modele.
- Execution de code — Sandboxes E2B, Modal, Pyodide. Permettre au modele de tester et valider du code.
- Calendrier / email — APIs Google, Microsoft Graph. Automatiser les taches administratives.
- Base de donnees — Via MCP ou appels directs. Donner au modele un acces en lecture (et parfois ecriture) aux donnees metier.
Memoire : transformer un chatbot en assistant
Sans memoire, chaque conversation repart de zero. Avec memoire, l’agent s’ameliore a chaque interaction.
Trois types de memoire :
Memoire episodique — Stocker les interactions passees. L’agent “se souvient” des sessions precedentes. Utile pour la continuite conversationnelle et le suivi de projets.
Memoire semantique — Stocker des faits sur l’utilisateur dans une vector DB. “Cet utilisateur est developpeur senior”, “Il prefere les reponses concises avec du code”. Le modele adapte ses reponses en fonction du profil.
Memoire procedurale — Les instructions et preferences apprises au fil du temps, injectees dans le system prompt de maniere dynamique. L’agent apprend les conventions d’un projet, les preferences d’un utilisateur, les patterns recurrents.
Projet : Agent de recherche web
Objectif : construire un agent qui recoit une question, cherche sur le web, lit les pages pertinentes, synthetise l’information et cite ses sources. Avec streaming temps reel et affichage des etapes de raisonnement.
Etapes de construction
-
Definir 3 outils —
search(query)pour chercher sur le web,read_url(url)pour lire le contenu d’une page,final_answer(text, sources[])pour structurer la reponse finale avec ses sources. -
Boucle ReAct avec garde-fous — Max 5 iterations. Detection de boucle infinie : si l’agent appelle le meme outil avec les memes arguments deux fois de suite, on interrompt et on retourne les resultats collectes.
-
Interface transparente — Affichage live des etapes de raisonnement. L’utilisateur voit ce que l’agent pense, quels outils il appelle, et quels resultats il obtient. La transparence cree la confiance.
-
Citations structurees — Reponse finale avec citations numerotees
[1],[2]linkees vers les sources originales. Chaque affirmation factuelle doit etre tracable. -
Logging complet — Chaque appel outil est logge : nom de l’outil, arguments, resultat (tronque), duree d’execution. Indispensable pour le debug et l’optimisation.
-
Monitoring des couts — Tracker les tokens consommes par query. En production, un agent mal optimise peut couter 10x plus qu’un agent bien concu pour le meme resultat.