Réseaux, collègues, keynotes, Agent IA est un terme que vous devez très certainement entendre ou voir un peu partout en ce moment. Tout le monde veut son Agent IA ! Et j'ai vraiment l'impression que ce mot est mis un peu à toutes les sauces.
C'est quoi un agent IA ?
Commençons par ce qu'un LLM sait faire : générer du texte.
Un agent IA c'est :
-
Un modèle (LLM) qui raisonne et prend des décisions
-
Des outils, c'est-à-dire des fonctions, des API ou des serveurs MCP que le modèle peut appeler pour agir et obtenir des informations
-
Des instructions qui définissent l'objectif de l'agent
Avec tout ça, on retrouve le concept de boucle : le modèle va appeler un outil, observer un résultat, décider de la suite et recommencer. Les instructions fixent l'objectif à atteindre. Ce n'est pas vous qui décidez de la séquence d'actions, c'est le modèle.
Comment fonctionne un agent IA ?
À chaque itération :
-
Le modèle reçoit l'historique de la conversation et la liste des outils disponibles
-
Il répond avec du texte ou demande un outil
-
Dans le cas d'une demande d'un appel d'outil, notre code va exécuter la fonction correspondante
-
Le résultat est ajouté à l'historique et ... on recommence 👾
C'est ce qui permet au modèle de s'adapter au fur et à mesure.
Quelle différence entre un workflow et un agent ?
Un workflow est un système où le LLM et les outils sont orchestrés via un chemin prédéfini. C'est à vous d'écrire la séquence.
Un agent est un système où le LLM décide lui-même du chemin et de quand il appelle les outils mis à sa disposition.
Je sens la question venir...
Quand utiliser un workflow ou un agent ?
Je préfère poser une autre question : Êtes-vous capable d'écrire la liste des étapes à l'avance ?
Si oui, faites un workflow : Récupérer les factures du mois, extraire les montants, générer un récapitulatif, l'envoyer par e-mail. Les étapes sont connues, toujours les mêmes et dans le même ordre. Pas besoin d'un agent qui n'apporterait pas grand-chose, à part un peu de latence et éventuellement de l'imprévisibilité.
L'agent est adapté aux situations où le problème est ouvert. Imaginez une situation où le nombre d'étapes dépend de ce que l'on découvre en cours de route. J'aime bien ce que formule Anthropic sur le sujet dans cet article : on ne peut pas coder en dur un chemin fixe pour un sujet complexe, parce que le processus est dynamique par nature et dépend du chemin parcouru. Chaque résultat renvoyé va orienter la suite.
Créer un agent en Python
Nous allons faire ça sans framework, en utilisant l'API de Mistral. Si vous préférez partir directement sur un framework qui gère la boucle pour vous, j'ai un article où l'on construit un agent avec smolagents.
Préparation du projet
Initialisons le projet avec uv :
# Création du projet et de son environnement uv init --no-package agent cd agent # Ajout des deux dépendances uv add mistralai python-dotenv
À noter
L'option --no-package évite de générer une structure avec un dossier src/.
Ensuite, créez un fichier .env à la racine avec votre clé d'API disponible via la console Mistral :
MISTRAL_API_KEY=votre_cle_api
Ensuite, le script se lancera tout simplement avec la commande uv run main.py.
Le scénario
Patrick, de la comptabilité à Rouen, veut savoir si la note de frais de Sébastien dépasse le plafond autorisé. Notre agent dispose de deux outils :
-
consulter_note_de_fraisrenvoie le montant de la note de frais d'un employé -
verifier_plafondindique si un montant dépasse le plafond
L'agent doit enchaîner les outils dans le bon ordre, et ça, il devra le déduire lui-même.
Le code
Nous allons découper le code, mais vous pouvez copier-coller directement les trois parties l'une en dessous de l'autre pour avoir le script au complet.
import json import os from dotenv import load_dotenv from mistralai.client import Mistral load_dotenv() client = Mistral(api_key=os.environ["MISTRAL_API_KEY"]) MODEL = "mistral-medium-latest" # Nos outils : de simples fonctions Python def consulter_note_de_frais(employe: str) -> str: notes = {"sebastien": 230.50, "patrick": 87.20} montant = notes.get(employe.lower()) if montant is None: return json.dumps({"erreur": "employé inconnu"}) return json.dumps({"employe": employe, "montant": montant}) def verifier_plafond(montant: float) -> str: PLAFOND = 150.0 return json.dumps({"plafond": PLAFOND, "depasse": montant > PLAFOND}) # L'annuaire : associer le nom de l'outil à la fonction Python outils_disponibles = { "consulter_note_de_frais": consulter_note_de_frais, "verifier_plafond": verifier_plafond, }
Les fonctions Python sont les outils qui renvoient du JSON pour que le modèle puisse lire le résultat.
# Les schémas : décrire les outils au modèle (format JSON Schema) tools = [ { "type": "function", "function": { "name": "consulter_note_de_frais", "description": "Renvoie le montant de la note de frais d'un employé.", "parameters": { "type": "object", "properties": { "employe": {"type": "string", "description": "Prénom de l'employé"} }, "required": ["employe"], }, }, }, { "type": "function", "function": { "name": "verifier_plafond", "description": "Indique si un montant dépasse le plafond de remboursement.", "parameters": { "type": "object", "properties": { "montant": {"type": "number", "description": "Montant en euros"} }, "required": ["montant"], }, }, }, ]
La liste tools donne une description de chaque outil au modèle au format JSON Schema, ce qui permet au modèle de savoir quand il doit utiliser l'outil.
messages = [ { "role": "user", "content": "La note de frais de Sébastien dépasse-t-elle le plafond ?", } ] # LA BOUCLE AGENTIQUE while True: reponse = client.chat.complete(model=MODEL, messages=messages, tools=tools) message = reponse.choices[0].message messages.append(message) # Pas d'appel d'outil ? Le modèle a terminé, on affiche sa réponse if not message.tool_calls: print(f"Agent : {message.content}") break # Sinon, on exécute chaque outil demandé for tool_call in message.tool_calls: nom = tool_call.function.name arguments = json.loads(tool_call.function.arguments) resultat = outils_disponibles[nom](**arguments) print(f"→ Le modèle appelle {nom}({arguments}) : {resultat}") # On renvoie le résultat au modèle pour le tour suivant messages.append( { "role": "tool", "name": nom, "content": resultat, "tool_call_id": tool_call.id, } )
La boucle while est l'agent : tant que le modèle demande des outils via message.tool_calls, on les exécute et on lui renvoie les résultats. Et quand le modèle répond sans appel d'outil, c'est sa réponse finale, on sort de la boucle.
Voici le résultat que j'ai obtenu :
→ Le modèle appelle consulter_note_de_frais({'employe': 'Sébastien'}) : {"erreur": "employ\u00e9 inconnu"} → Le modèle appelle consulter_note_de_frais({'employe': 'Sebastien'}) : {"employe": "Sebastien", "montant": 230.5} → Le modèle appelle verifier_plafond({'montant': 230.5}) : {"plafond": 150.0, "depasse": true} Agent : Oui, la note de frais de **Sébastien** (230,50 €) dépasse le plafond de remboursement, qui est fixé à **150,00 €**.
Regardez ce qu'il s'est passé, et j'avoue que je ne l'avais pas forcément prévu 😂.
Le modèle appelle d'abord l'outil avec Sébastien, ce que j'ai demandé. Sauf que mon dictionnaire contient la clé sebastien, sans accent. L'outil lui a renvoyé une erreur, le modèle l'a lu, a compris le problème et a relancé l'outil sans l'accent. C'est passé, et j'ai eu droit à une conclusion.
Un workflow peut rattraper des erreurs que vous avez anticipées, c'est plus compliqué pour notre cas, car je n'y avais même pas pensé. Et l'agent s'en est sorti quand même.
Les outils pour créer un agent IA
Dans notre exemple précédent, nous avons codé notre agent sans framework. Mais vous pouvez très bien utiliser un framework :
-
LangGraph permet de modéliser un agent sous forme de graphe avec des nœuds
-
Crew AI est pensé pour le multi-agents avec une approche par rôle
-
smolagents que je trouve plus "direct" pour faire un agent fonctionnel, c'est celui que j'utilise dans ce guide
-
Pydantic AI, nous sommes plutôt dans la validation de données à la Pydantic appliquée aux agents, n'hésitez pas à aller voir notre guide
-
OpenAI Agents SDK (librairie officielle OpenAI)
-
Claude Agent SDK (librairie officielle Anthropic)
-
N'hésitez pas à aller voir du côté de chez Mistral
Au final, tout n'a pas besoin d'être un agent, pour des choses simples ou pas adaptées, c'est lourd et ça risque de vous coûter en temps et en argent.
Personnellement, sur certaines tâches, un bon prompt à mon LLM me suffit, j'ai des tâches qui sont bien définies où j'utilise plutôt un workflow via n8n, mais le plus souvent j'utilise tout de même un agent, mais dans un cadre bien défini.