La plupart des développeurs traitent les agents IA comme des chatbots avec des étapes supplémentaires. Posez une question, obtenez une réponse, passez à autre chose. Dès que vous avez besoin qu’un agent fasse réellement quelque chose — récupérer des données, mettre à jour une base de données, prendre une décision en plusieurs étapes — ce modèle échoue. C’est là que l’architecture compte, et où la plupart des implémentations échouent dans les deux premières semaines de production.
Un agent IA est une boucle, pas un modèle. Le modèle est le moteur de décision. La boucle est le système d’exploitation qui décide de la suite.
La Boucle d’Agent Fondamentale
Chaque agent fonctionnel suit ce schéma :
1. L'utilisateur fournit l'entrée/contexte
2. Le LLM décide quoi faire (y compris : ne rien faire)
3. Si le LLM a choisi une action :
- Exécuter l'outil
- Capturer le résultat
- Retourner le résultat au LLM
4. Répéter jusqu'à ce que le LLM dise "J'ai terminé"
5. Retourner la réponse finale à l'utilisateur
La boucle est le contrat. Le modèle est le décideur à l’intérieur. Confondez ces deux éléments, et vous perdrez des semaines à déboguer des prompts alors que le vrai problème est votre logique de boucle.
J’ai appris cela chez AlgoVesta à la dure. Nous avons construit un agent pour analyser les données du marché et exécuter des transactions. Le prompt était bloqué à 40% de précision — jusqu’à ce que nous réalisions que la boucle appelait le même outil deux fois, lui fournissant des résultats obsolètes du premier appel, puis nous nous demandions pourquoi l’agent prenait de mauvaises décisions. Le modèle était bien. La tuyauterie était cassée.
Appel d’Outils : Le Contrat Entre le LLM et le Code
L’appel d’outils est la manière dont le LLM indique à votre code quoi exécuter. Ce n’est pas une technique de prompt. C’est un contrat d’API.
La plupart des modèles le prennent en charge nativement maintenant — Claude (via le bloc tool_use), GPT-4o (via function_calling), Mistral (via tool_call). Les noms diffèrent. Le concept est identique : le modèle retourne des données structurées disant « exécute cet outil avec ces paramètres ».
Voici à quoi ressemble une définition d’outil basique :
{
"name": "fetch_user_data",
"description": "Récupère les informations du compte utilisateur, y compris le solde et l'historique des transactions",
"input_schema": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"description": "L'identifiant unique de l'utilisateur"
},
"include_history": {
"type": "boolean",
"description": "Inclure l'historique des transactions (par défaut : false)"
}
},
"required": ["user_id"]
}
}
La description est importante. Une description vague comme « obtenir des données » conduit le modèle à utiliser l’outil de manière incorrecte. Une description spécifique comme « Récupère les informations du compte utilisateur, y compris le solde et l’historique des transactions » donne au modèle le contexte pour décider s’il a besoin de cet outil ou non.
Voici un scénario réel : nous avions un agent censé vérifier l’éligibilité des utilisateurs avant de prendre des décisions. Il continuait d’appeler le mauvais outil car la description était générique. Changer « Valider l’éligibilité du client en fonction de l’âge du compte, du solde et des modèles de transaction » a fait chuter le taux d’erreur de 18 % à 3 %.
La définition de l’outil est à moitié de l’ingénierie de prompt. Écrivez-la clairement.
Mémoire : Conversation ou État
C’est là que la plupart des projets amateurs divergent des systèmes de production.
La mémoire conversationnelle (l’historique du chat que vous renvoyez au modèle) fonctionne jusqu’à ce qu’elle ne fonctionne plus. Les limites de tokens existent. Claude Sonnet 4 a 200 000 tokens, mais alimenter un historique de conversation de 6 mois dans chaque appel d’API gaspille des tokens et ralentit l’inférence. Après qu’AlgoVesta ait atteint environ 3 000 interactions d’agents par mois, nous avons réalisé que nous brûlions du budget sur du contexte dont le modèle n’avait pas besoin.
Les agents de production nécessitent deux couches de mémoire :
Mémoire à court terme : La conversation ou la tâche en cours. Gardez-la courte — seulement les 5 à 10 derniers messages, ou les 5 dernières minutes d’interaction, selon ce qui est le plus petit.
Mémoire à long terme : Faits dont l’agent a besoin pour se souvenir mais qu’il n’a pas besoin dans chaque prompt. Stockez-les séparément — une base de données, un magasin vectoriel, ou une base de connaissances structurée — et récupérez-les uniquement lorsque c’est pertinent.
Voici le schéma :
1. L'utilisateur envoie un message
2. Interroger la mémoire à long terme pour les faits pertinents
3. Ajouter ces faits au prompt système
4. Ajouter l'historique récent de la conversation (N derniers messages)
5. Envoyer au LLM
6. Si l'agent a appris quelque chose d'important, stockez-le
7. Procéder à l'appel d'outils
Pour un agent de trading, nous stockons les décisions antérieures et leurs résultats. Lorsque l’agent décide d’exécuter une transaction, nous récupérons les 5 dernières transactions similaires et leurs résultats — pas l’historique complet de la conversation, juste le signal.
C’est un changement de 10 lignes de « mémoire naïve » à « mémoire évolutive ». La plupart des développeurs ne le font jamais.
Gestion des Échecs et Logique de Réessai
Un appel d’outil échoue. La base de données était lente. L’API a renvoyé un timeout. Que fait l’agent ?
Si votre boucle plante simplement, vous avez construit un jouet. Les agents de production ont besoin d’une logique de repli.
Schéma minimal viable :
for attempt in range(max_retries):
try:
result = execute_tool(tool_name, params)
if result.success:
return result
except ToolExecutionError as e:
if attempt == max_retries - 1:
# Dernière tentative échouée. Informer le LLM.
agent_message = f