Aller au contenu
Développement medium

Comprendre les agents IA : du chatbot à l'agent autonome

14 min de lecture

logo python

« Agent » est devenu le mot le plus galvaudé de l'IA générative — collé à tout ce qui appelle un modèle de langage. Ce guide pose une définition rigoureuse : un agent, c'est un LLM, des outils, une boucle et une mémoire. Rien de plus, rien de magique. Vous verrez ce qui sépare un agent d'un chatbot ou d'un RAG, le cycle ReAct qui anime la boucle, puis vous construirez un mini-agent en Python pur — une centaine de lignes, sans aucun framework ni dépendance — pour que la mécanique soit sous vos yeux. Public visé : développeur Python qui a déjà appelé un LLM et veut comprendre ce qu'est réellement un agent avant d'ouvrir un framework.

  • Distinguer rigoureusement chatbot, RAG, workflow et agent.
  • Les quatre composants d'un agent : LLM, outils, boucle, mémoire.
  • Le cycle ReAct : Reason, Act, Observe.
  • Construire un mini-agent en Python pur, sans framework.
  • Les limites et risques des agents, et le panorama 2026 des frameworks.

Ce guide suppose acquis :

  • Les bases d'un LLM et de son API — voir Qu'est-ce qu'un LLM.
  • Python : fonctions, dictionnaires, une boucle for.
  • Pour le lab : une instance Ollama avec le modèle llama3.2. Aucune autre dépendance.

Chatbot, RAG, workflow, agent : quatre choses différentes

Section intitulée « Chatbot, RAG, workflow, agent : quatre choses différentes »

Le mot « agent » recouvre, dans le discours courant, quatre objets qu'il faut séparer. Ils diffèrent sur une seule question : qui décide de la prochaine action ?

Un chatbot ne décide de rien. Il reçoit un message, appelle le LLM, renvoie la réponse. Un tour, une réponse. C'est utile, mais le modèle ne fait que parler.

Un RAG ajoute une étape fixe : avant d'appeler le LLM, on récupère des documents pertinents et on les injecte dans le contexte. La séquence est toujours la même — chercher, puis répondre. Le modèle ne choisit pas de chercher : c'est le code qui l'impose.

Un workflow enchaîne plusieurs appels LLM selon un graphe écrit à l'avance. Étape 1 puis étape 2 puis étape 3. Le chemin est riche, mais il est figé par le développeur.

Un agent, lui, décide. À chaque tour, c'est le LLM qui choisit la prochaine action : appeler tel outil, ou bien répondre. Le chemin n'est pas écrit à l'avance — il émerge de la situation. C'est cette autonomie de décision qui définit l'agent, et c'est aussi ce qui le rend puissant et risqué.

Démystifions. Un agent se ramène à quatre éléments, et chacun est simple.

Le LLM est le cerveau : il raisonne et décide. Mais seul, il ne sait que produire du texte.

Les outils sont les mains. Un outil est une fonction — lire un fichier, appeler une API, faire un calcul. C'est ce qui permet à l'agent d'agir sur le monde, pas seulement d'en parler. Le modèle ne voit pas le code de l'outil : il en voit le nom, la description et les paramètres. Cette description est l'interface — la soigner, c'est dire au modèle quand et comment s'en servir.

La boucle est ce qui transforme un appel LLM en agent. Plutôt qu'un seul aller-retour, l'agent recommence : il appelle le modèle, exécute l'outil demandé, renvoie le résultat au modèle, et recommence — jusqu'à une réponse finale.

La mémoire est ce qui rend la boucle cohérente. À chaque tour, on conserve tout l'historique — la question, les décisions du modèle, les résultats des outils — et on le repasse au LLM. Sans mémoire, le modèle oublierait à chaque tour ce qu'il vient de faire.

La boucle d'un agent suit un schéma nommé ReAct — contraction de Reason et Act. Chaque tour enchaîne trois temps.

Reason — le LLM examine la mémoire et décide : soit il demande un outil, soit il estime avoir la réponse. Act — si un outil est demandé, le code l'exécute avec les arguments fournis par le modèle. Observe — le résultat de l'outil est réinjecté dans la mémoire, et le tour suivant commence.

Le cycle se répète jusqu'à ce que, lors d'un Reason, le modèle ne demande plus d'outil : il produit alors sa réponse finale, et la boucle s'arrête. Tout l'agent tient dans cette répétition. Le construire en Python le montre mieux qu'un long discours.

Le lab agents/mini-agent construit un agent complet sans aucun frameworkjson et urllib de la bibliothèque standard suffisent. L'agent parle à un modèle llama3.2 servi par Ollama.

D'abord, les outils : de simples fonctions Python. Une subtilité de sécurité s'y cache — un LLM renvoie parfois ses arguments numériques sous forme de chaînes, malgré le schéma. Un outil ne fait jamais confiance aveuglément à ce que le modèle lui passe : il coerce.

def addition(a: float, b: float) -> float:
"""Additionne deux nombres."""
return float(a) + float(b)
def multiplication(a: float, b: float) -> float:
"""Multiplie deux nombres."""
return float(a) * float(b)
OUTILS = {"addition": addition, "multiplication": multiplication}

Ces fonctions sont décrites au modèle par un schéma — nom, description (la docstring), paramètres attendus. C'est ainsi que le LLM sait quels outils existent.

L'appel au LLM est une simple requête HTTP. On envoie la mémoire et le schéma des outils ; on récupère le message de réponse du modèle.

def appeler_llm(messages: list[dict]) -> dict:
"""Envoie la conversation au modèle et renvoie son message de réponse."""
corps = json.dumps(
{"model": MODELE, "messages": messages, "tools": SCHEMA, "stream": False}
).encode()
requete = urllib.request.Request(
OLLAMA_URL, data=corps, headers={"Content-Type": "application/json"}
)
with urllib.request.urlopen(requete, timeout=300) as reponse:
return json.load(reponse)["message"]

Vient enfin le cœur : la boucle. Une vingtaine de lignes, et c'est tout l'agent.

def agent(question: str, max_tours: int = 6) -> tuple[str, list[str]]:
"""Fait tourner la boucle Reason -> Act -> Observe jusqu'à la réponse."""
memoire = [
{"role": "system", "content": SYSTEME},
{"role": "user", "content": question},
]
trace: list[str] = []
for _ in range(max_tours):
message = appeler_llm(memoire) # Reason : le modèle décide
memoire.append(message) # tout reste en mémoire
appels = message.get("tool_calls")
if not appels: # aucun outil -> réponse finale
return message["content"], trace
for appel in appels: # Act : exécuter les outils
nom = appel["function"]["name"]
arguments = appel["function"]["arguments"]
resultat = OUTILS[nom](**arguments)
trace.append(f"{nom}({arguments}) = {resultat}")
memoire.append( # Observe : résultat réinjecté
{"role": "tool", "tool_name": nom, "content": str(resultat)}
)
return "Nombre maximum de tours atteint.", trace

On retrouve les quatre composants et le cycle ReAct. La memoire est la mémoire. appeler_llm est le Reason. La boucle for appel in appels est l'Act. Le memoire.append du résultat est l'Observe. Et le max_tours est un garde-fou indispensable : sans lui, un agent qui n'aboutit pas tournerait — et facturerait — sans fin.

Lancé sur une question simple, l'agent montre le cycle à l'œuvre :

Trace des outils :
- multiplication({'a': 23, 'b': 17}) = 391.0
Réponse : Le résultat de 23 fois 17 est 391.

Deux tours ont eu lieu. Au premier, le modèle a raisonné qu'il fallait multiplier et a demandé l'outil ; le code l'a exécuté et a observé 391. Au second tour, le modèle, voyant le résultat en mémoire, n'a plus demandé d'outil — il a formulé la réponse, et la boucle s'est arrêtée.

Vérifier ce comportement demande deux tests de nature différente. Un test d'intégration lance l'agent contre le vrai modèle : appelle-t-il le bon outil, obtient-il le bon résultat ? Mais la sortie d'un LLM n'est pas déterministe — on ne peut pas y bâtir un test d'enchaînement fiable. D'où un test unitaire qui simule le LLM : on remplace appeler_llm par un scénario fixe — outil 1, outil 2, réponse finale — et l'on vérifie que la boucle enchaîne bien les tours et s'arrête net. Le réel prouve que l'agent marche ; le simulé prouve que la boucle est correcte.

Construire l'agent soi-même rend ses fragilités visibles — et elles sont réelles.

La première est l'accumulation d'erreurs. Lors d'un essai d'enchaînement sur le mini-agent, le modèle llama3.2 a correctement calculé 23 × 17 = 391, puis, au tour suivant, a passé 299 au lieu de 391 à l'addition. La boucle ne corrige rien : elle propage. Chaque tour part du résultat du précédent — une erreur intermédiaire contamine toute la suite. Plus la chaîne est longue, plus le risque est grand.

Viennent ensuite les dérives. Un agent qui n'aboutit pas peut boucler, répéter le même outil, partir dans une direction absurde — d'où le garde-fou max_tours. Le coût suit la même logique : chaque tour est un appel LLM facturé ; un agent bavard coûte cher, et le coût est difficile à prévoir puisque le nombre de tours n'est pas connu d'avance. Enfin, le risque d'alignement : un agent agit. Un outil qui écrit un fichier, supprime une ressource ou appelle une API engage des effets réels. Un agent mal cadré, ou manipulé par une injection de prompt, agit de travers — c'est tout l'objet du guide Sécurité MCP.

Ces limites ne condamnent pas les agents : elles dictent les bonnes pratiques — modèles capables, validation des résultats d'outils, observabilité, périmètre d'action restreint.

Le mini-agent de ce guide est pédagogique : en production, on s'appuie sur un framework qui gère le schéma des outils, les erreurs, l'asynchrone, l'observabilité. Les principaux, début 2026 :

FrameworkPositionnement
PydanticAIAgents typés, validation stricte des entrées/sorties — l'approche Python moderne
LangGraphAgents et workflows à état, graphe explicite, reprise sur incident
smolagentsL'agent écrit du code Python plutôt que du JSON — expressif, à sandboxer
CrewAIOrienté équipes d'agents coopérants, abstractions de haut niveau
OpenAI Agents SDKLe SDK officiel d'OpenAI, simple, centré sur leur écosystème

Aucun n'est « le meilleur » — le choix dépend du besoin en typage, en multi-agents, en intégration MCP. PydanticAI et LangGraph sont approfondis dans la suite de ce parcours. Mais quel que soit le framework, il fait tourner exactement la boucle que vous venez d'écrire : le comprendre une fois, c'est les comprendre tous.

  • Ce qui définit un agent, c'est que le LLM décide de la prochaine action — pas le développeur.
  • Un agent = LLM + outils + boucle + mémoire. Quatre composants simples, aucune magie.
  • Le cycle ReAct — Reason, Act, Observe — se répète jusqu'à ce que le modèle ne demande plus d'outil.
  • Un outil est une fonction ; le modèle n'en voit que le nom, la description et les paramètres.
  • La boucle propage les erreurs : une valeur intermédiaire fausse contamine toute la suite.
  • Toute boucle d'agent doit être bornée (max_tours) — sinon, dérives et facture ouverte.
  • Un framework ne change pas la boucle : il l'outille. La comprendre une fois suffit.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn