EN DIRECT
CEO fired developers to make room for AI. Developers create open source AI CEO27/08/26|NVIDIA NVLink Fusion Expands With NVHBM Custom High-Bandwidth Memory26/08/26 · NVIDIA|The inside story on why OpenAI agents hacked Hugging Face26/08/26 · OpenAI|TraceML: An Empirical Analysis of Human-Agent Planning in Machine Learning Development26/08/26 · Hugging Face|Intelligent transcription with Gemini 3.5 Transcribe26/08/26 · Google|The Download: the Kids issue arrives, and Bill Gates reveals his AI fears26/08/26|Z.ai confirms Ox Alpha is a new GLM-series model and will release its weights26/08/26|Learning never stops: How AI makes learning continuous26/08/26 · OpenAI|Bringing ChatGPT for Teachers to more U.S. school districts26/08/26 · OpenAI|The Hugging Face incident and the road ahead26/08/26 · OpenAI|Training and Finetuning Multi-Vector Embedding Models with Sentence Transformers26/08/26 · Hugging Face|How loveholidays is making everyone a builder with Codex26/08/26 · OpenAI|CEO fired developers to make room for AI. Developers create open source AI CEO27/08/26|NVIDIA NVLink Fusion Expands With NVHBM Custom High-Bandwidth Memory26/08/26 · NVIDIA|The inside story on why OpenAI agents hacked Hugging Face26/08/26 · OpenAI|TraceML: An Empirical Analysis of Human-Agent Planning in Machine Learning Development26/08/26 · Hugging Face|Intelligent transcription with Gemini 3.5 Transcribe26/08/26 · Google|The Download: the Kids issue arrives, and Bill Gates reveals his AI fears26/08/26|Z.ai confirms Ox Alpha is a new GLM-series model and will release its weights26/08/26|Learning never stops: How AI makes learning continuous26/08/26 · OpenAI|Bringing ChatGPT for Teachers to more U.S. school districts26/08/26 · OpenAI|The Hugging Face incident and the road ahead26/08/26 · OpenAI|Training and Finetuning Multi-Vector Embedding Models with Sentence Transformers26/08/26 · Hugging Face|How loveholidays is making everyone a builder with Codex26/08/26 · OpenAI|
IntermédiaireNouveau🤖

Construire son premier agent IA : de la tâche répétitive à la production en une journée

Un agent, c'est une boucle de 40 lignes autour d'un modèle et de trois outils. Ce qui le rend utile, c'est tout le reste : la bonne tâche, une fiche de poste claire, des garde-fous avant l'intelligence, et cinq cas réels pour décider s'il part en production. Guide complet, du choix à la mise en service.

34 min de lecturePublié le 27 août 2026 · aujourd'hui

Tu as lu que les agents allaient tout changer. Tu as peut-être vu passer une infographie « construis ton agent en 10 minutes ». Et tu as un collaborateur qui passe deux heures par jour à qualifier des leads, trier des tickets ou compiler un rapport hebdo. La question n'est pas si tu peux automatiser ça avec un agent — c'est comment le faire sans y laisser un trimestre, une facture surprise et la confiance de l'équipe.

Ce guide est le barreau manquant entre notre article conceptuel sur les agents et la formation avancée sur l'architecture des systèmes agentiques. Il construit un agent, sur une tâche, en une journée de travail réaliste. La moitié du contenu est du code que tu peux exécuter ; l'autre moitié est ce qui fait qu'un agent qui marche sur trois exemples continue de marcher sur le trois-centième.

Prérequis. Avoir lu « Agents IA : la prochaine révolution » ou savoir ce qu'est un appel d'outil (tool use). Python 3.11+, un SDK fournisseur (les exemples utilisent le SDK Anthropic), accès à une API métier ou une base de données à faire manipuler par l'agent. Une journée, un développeur, et un utilisateur métier disponible deux heures pour les tests.

1. Faut-il un agent ? La question que l'infographie ne pose pas

Le mot « agent » est devenu un fourre-tout. Distinguons trois choses qui n'ont pas le même coût, le même risque, ni la même valeur.

Un prompt transforme une entrée en sortie en un appel. Résumer un document, classer un email, extraire des champs : pas d'outil, pas de boucle.

Un workflow enchaîne plusieurs appels dans un ordre fixé par toi : extraire → vérifier en base → rédiger → envoyer. Le modèle intervient à certaines étapes, mais c'est ton code qui décide de la séquence. Chaque étape est testable isolément, le coût est borné, le comportement est prévisible.

Un agent reçoit un objectif et des outils, et décide lui-même de la séquence : quel outil appeler, avec quels arguments, combien de fois, quand s'arrêter. Il gère les cas où le chemin n'est pas connu à l'avance. En échange, son coût et son comportement sont moins prévisibles.

Prompt, workflow ou agent : l'arbre de décision
La tâche tient-elle en un seul appel ? (entrée → sortie, sans consulter de système externe) oui Prompt + sortie structurée non Peux-tu dessiner les étapes à l'avance ? (même séquence à chaque exécution) oui Workflow 80 % des cas non Une erreur est-elle rattrapable ? (action réversible, ou validation humaine possible) non Pas maintenant workflow + humain oui Les outils nécessaires existent-ils ? (API, base, connecteur — ou 1 jour pour les créer) Agent · ce guide
L'agent se justifie quand la séquence d'actions dépend de ce qu'on découvre en cours de route. Si tu peux dessiner les étapes sur un tableau blanc avant de commencer, c'est un workflow — moins cher, plus sûr, plus facile à tester.

Trois exemples pour calibrer :

« Résumer les tickets de la semaine dans un rapport. » Lire les tickets, les regrouper, rédiger. La séquence est toujours la même : c'est un workflow. Un agent ici coûterait plus cher pour un résultat moins prévisible.

« Qualifier les leads entrants. » Selon le lead, il faut chercher l'entreprise, vérifier si elle est déjà cliente, regarder le secteur, parfois demander une précision. Le chemin dépend de ce qu'on trouve. Une erreur est rattrapable (le lead est marqué « à revoir », pas supprimé). Les outils existent (CRM, recherche web). C'est un agent.

« Répondre aux clients par email avec engagement contractuel. » Chemin variable, oui — mais une erreur n'est pas rattrapable (un email parti avec une promesse fausse). Pas maintenant : un workflow qui prépare un brouillon qu'un humain valide, et on y reviendra quand l'agent aura prouvé son taux d'erreur.

🧭
Le test du tableau blanc
Demande à la personne qui fait la tâche aujourd'hui de la dessiner sur un tableau blanc. Si elle produit un diagramme avec des flèches dans un ordre fixe, c'est un workflow. Si elle dit « ça dépend » trois fois en deux minutes et que les « ça dépend » portent sur ce qu'elle découvre en cours de route, c'est un agent. Si elle dit « je ne sais pas, je le sens », ce n'est ni l'un ni l'autre — pas encore.

2. Choisir la tâche avec une grille, pas au feeling

Le premier agent ne doit pas être le plus impressionnant. Il doit être celui qui a le plus de chances de réussir et de rester en production. Quatre critères, notés de 1 à 5, et on multiplie.

Grille de sélection de la première tâche
TÂCHE Fréquence Coût manuel Tolérance erreur Accès données Score Qualification de leads entrants 60/jour · 8 min chacun · erreur = lead à revoir · CRM + web 5 4 4 4 320 Tri et routage des tickets support 200/jour · 2 min chacun · erreur = mauvaise file, corrigée · outil de ticketing 5 3 4 5 300 Réponse client avec engagement 40/jour · 15 min chacun · erreur = promesse fausse envoyée · CRM + contrats 4 5 1 3 60 Veille concurrentielle mensuelle 1/mois · 2 jours · erreur = rapport incomplet · sources web éparses 1 5 5 2 50 Seuil recommandé pour un premier agent : score ≥ 200 et aucun critère à 1
Score = fréquence × coût manuel × tolérance à l'erreur × accès aux données. Une tâche brillante avec un 1 quelque part est disqualifiée : un facteur à 1 tue le produit. La qualification de leads gagne ici non parce qu'elle est spectaculaire, mais parce qu'elle n'a aucun point faible.

Fréquence. Un agent coûte à construire et à maintenir ; il faut qu'il tourne souvent pour rembourser. Quotidien = 5, hebdomadaire = 3, mensuel = 1.

Coût manuel. Le temps humain que chaque exécution remplace. C'est ce qui fait la valeur — et c'est ce que tu mesureras en section 8.

Tolérance à l'erreur. Le critère que l'infographie oublie et qui décide de tout. Une erreur de l'agent est-elle visible, réversible, rattrapable par un humain avant qu'elle ait des conséquences ? Un lead mal qualifié se revoit ; un virement mal validé, non.

Accès aux données. L'agent a besoin d'outils. Si les données sont dans un CRM avec une API, c'est 5. Si elles sont dans des PDF scannés et trois boîtes mail, c'est 1 — et le projet devient un projet d'intégration, pas un projet d'agent.

Définir le succès avant de commencer. Pour le fil rouge (qualification de leads), le succès est chiffré : ≥ 90 % de leads qualifiés comme l'aurait fait le commercial senior sur 5 cas de test, ≤ 8 tours par lead, ≤ 0,05 € par lead, et le commercial récupère ses 8 minutes. Si ce n'est pas écrit avant le premier appel API, tu ne sauras jamais si l'agent est prêt.

3. L'architecture d'un agent : une boucle et trois familles d'outils

Voici ce qu'est réellement un agent, débarrassé du vocabulaire. Un modèle reçoit une fiche de poste (prompt système), un objectif (le lead à qualifier), et une liste d'outils qu'il a le droit d'appeler. Il réfléchit, appelle un outil, reçoit le résultat, réfléchit à nouveau, et ainsi de suite jusqu'à ce qu'il décide qu'il a fini. Ton code fait tourner cette boucle et exécute les outils. C'est tout.

Anatomie d'un agent
Fiche de poste prompt système, cachée Objectif le lead #4821 LA BOUCLE Modèle réfléchit, choisit Outil ton code exécute résultat renvoyé au modèle · tour suivant jusqu'à stop_reason = end_turn · ou plafond atteint Résultat structuré score, raison, action TROIS FAMILLES D'OUTILS Lire CRM, base, documents, web sans risque · auto Agir écrire en base, créer une tâche, envoyer garde-fous · auto / revue / jamais Notifier Slack, email interne, ticket faible risque · auto avec quota Autour de la boucle : plafond de tours · plafond de dépense · journal de chaque appel d'outil · niveaux d'approbation
La boucle est au centre. Les outils se rangent en trois familles — lire, agir, notifier — et c'est sur les outils d'action que se posent les garde-fous. Le journal enregistre chaque tour ; les plafonds arrêtent la boucle avant qu'elle ne coûte trop cher.

Lire : chercher un contact dans le CRM, récupérer l'historique, lire une page web. Aucun effet de bord, l'agent peut appeler ces outils librement.

Agir : mettre à jour un champ, créer une tâche, envoyer un email. Chaque outil d'action porte un niveau d'approbation (section 6). Un premier agent en a peu, et aucun irréversible.

Notifier : poster un message dans un canal Slack, ouvrir un ticket. Risque faible, mais avec un quota — un agent qui poste 400 messages à cause d'une boucle est une nuisance, pas un incident.

🧱
Il n'y a pas de magie
Le modèle ne « fait » rien. Il renvoie un message qui dit « appelle l'outil X avec les arguments Y ». C'est ton code qui exécute X, et qui décide s'il a le droit. Toute la sécurité de l'agent tient dans cette phrase : le modèle propose, ton code dispose. Les frameworks d'agents emballent cette boucle ; il vaut mieux l'avoir écrite une fois à la main pour savoir ce qu'ils cachent.

4. La boucle en code

Voici l'agent complet, hors outils. Quarante lignes qui font tout ce qui est décrit au-dessus, avec les plafonds intégrés dès la première version.

import json, time
from anthropic import Anthropic

client = Anthropic()
MODEL = "claude-sonnet-4-5"

def run_agent(system: str, tools: list[dict], handlers: dict, goal: str,
              max_turns: int = 12, max_cost_eur: float = 0.10, log=print) -> dict:
    """Boucle d'agent minimale. handlers = {nom_outil: fonction(**args) -> str}."""
    messages = [{"role": "user", "content": goal}]
    cost, turns = 0.0, 0

    while True:
        turns += 1
        if turns > max_turns:
            return {"status": "stopped", "reason": f"max_turns ({max_turns})", "messages": messages}

        resp = client.messages.create(
            model=MODEL, max_tokens=1500,
            system=[{"type": "text", "text": system, "cache_control": {"type": "ephemeral"}}],
            tools=tools, messages=messages,
        )
        cost += estimate_cost(resp.usage)
        if cost > max_cost_eur:
            return {"status": "stopped", "reason": f"max_cost ({max_cost_eur} €)", "messages": messages}

        messages.append({"role": "assistant", "content": resp.content})

        if resp.stop_reason == "end_turn":
            final = next((b.text for b in resp.content if b.type == "text"), "")
            return {"status": "done", "answer": final, "turns": turns, "cost_eur": round(cost, 4)}

        # Le modèle demande un ou plusieurs outils : on les exécute et on renvoie les résultats
        results = []
        for block in resp.content:
            if block.type != "tool_use":
                continue
            t0 = time.perf_counter()
            try:
                output = handlers[block.name](**block.input)
            except Exception as e:                       # l'erreur est renvoyée au modèle, pas levée
                output = f"ERREUR: {type(e).__name__}: {e}"
            log({"turn": turns, "tool": block.name, "args": block.input,
                 "ms": round((time.perf_counter() - t0) * 1000), "ok": not output.startswith("ERREUR")})
            results.append({"type": "tool_result", "tool_use_id": block.id, "content": str(output)[:4000]})
        messages.append({"role": "user", "content": results})

Quatre détails qui font la différence entre une démo et un agent de production :

  • Les erreurs d'outil sont renvoyées au modèle, pas levées. Un CRM qui répond 404 est une information : l'agent peut essayer une autre recherche ou conclure « entreprise inconnue ». Une exception non capturée tue la boucle.
  • Le résultat d'outil est tronqué (4 000 caractères). Un outil qui renvoie 50 Ko de JSON fait exploser le contexte et la facture pour rien.
  • Les plafonds sont dans la boucle, pas dans un wrapper qu'on ajoutera « après ». Douze tours et dix centimes suffisent à qualifier n'importe quel lead ; au-delà, quelque chose ne va pas et il vaut mieux s'arrêter.
  • Chaque appel d'outil est journalisé avec ses arguments et sa durée. C'est ce que tu liras quand un utilisateur dira « l'agent a fait n'importe quoi sur le lead 4821 ».

Les outils, maintenant. Chacun est une définition JSON (ce que le modèle voit) et une fonction Python (ce que ton code exécute).

TOOLS = [
    {
        "name": "crm_search_company",
        "description": "Cherche une entreprise dans le CRM par nom ou domaine. Renvoie fiche + statut client.",
        "input_schema": {"type": "object",
                         "properties": {"query": {"type": "string"}},
                         "required": ["query"]},
    },
    {
        "name": "web_lookup",
        "description": "Recherche web courte sur une entreprise : secteur, taille, actualité. Max 5 résultats.",
        "input_schema": {"type": "object",
                         "properties": {"query": {"type": "string"}},
                         "required": ["query"]},
    },
    {
        "name": "crm_update_lead",
        "description": "Met à jour le lead : score (1-5), raison, prochaine action. Action, niveau 'revue'.",
        "input_schema": {"type": "object",
                         "properties": {"lead_id": {"type": "string"},
                                        "score": {"type": "integer", "minimum": 1, "maximum": 5},
                                        "reason": {"type": "string", "maxLength": 300},
                                        "next_action": {"type": "string",
                                                        "enum": ["call_today", "nurture", "disqualify", "needs_human"]}},
                         "required": ["lead_id", "score", "reason", "next_action"]},
    },
    {
        "name": "notify_sales",
        "description": "Poste un message court dans le canal Slack #leads. Max 1 par lead.",
        "input_schema": {"type": "object",
                         "properties": {"text": {"type": "string", "maxLength": 500}},
                         "required": ["text"]},
    },
]

HANDLERS = {
    "crm_search_company": lambda query: json.dumps(crm.search(query)[:3], ensure_ascii=False),
    "web_lookup":         lambda query: json.dumps(search.top(query, n=5), ensure_ascii=False),
    "crm_update_lead":    guarded("revue", lambda **a: crm.update_lead(**a)),
    "notify_sales":       quota(1, lambda text: slack.post("#leads", text)),
}

La description d'un outil est un prompt. « Renvoie fiche + statut client » dit au modèle ce qu'il obtiendra ; « Max 1 par lead » lui dit comment se comporter. Un outil mal décrit est un outil mal utilisé. Les enums et les maxLength dans les schémas valent mieux que des consignes dans le prompt : le modèle ne peut pas les violer.

5. La fiche de poste : le prompt système avant le code

L'infographie a raison sur un point : le prompt système est une fiche de poste. Elle a tort de la mettre en étape 5. C'est la première chose à écrire, avec l'utilisateur métier, avant la première ligne de Python — parce que c'est là qu'on découvre les cas limites, les règles implicites et les « ah oui, sauf si ».

Quatre sections, dans cet ordre :

Rôle — qui est l'agent, pour qui il travaille, ce qu'il produit. Une phrase.

Procédure — comment il s'y prend, dans l'ordre normal. C'est la partie que le métier dicte.

Limites — ce qu'il ne fait jamais, et ce qu'il fait quand il ne sait pas. C'est la partie la plus importante et la plus courte.

Format — la structure exacte de sa sortie finale. Idéalement un outil de sortie structurée plutôt que du texte libre.

SYSTEM = """Tu es l'assistant de qualification des leads entrants de l'équipe commerciale de Digimoove.
Pour chaque lead reçu, tu produis un score de 1 à 5, une raison en une phrase, et une prochaine action.

## Procédure
1. Cherche l'entreprise dans le CRM (crm_search_company). Si elle est déjà cliente ou en cours de négociation, score 5, next_action = call_today, et arrête-toi.
2. Sinon, fais UNE recherche web (web_lookup) pour identifier le secteur et la taille approximative.
3. Applique la grille :
   - Secteur cible (industrie, santé, collectivités, ETI de services) ET > 50 salariés → 4 ou 5
   - Secteur cible mais < 50 salariés → 3, next_action = nurture
   - Hors secteur cible, ou étudiant / particulier / concurrent → 1 ou 2, next_action = disqualify
4. Enregistre avec crm_update_lead, puis notifie #leads uniquement si score ≥ 4.

## Limites
- Tu ne contactes jamais le lead. Tu ne modifies rien d'autre que le lead concerné.
- Une seule recherche web par lead. Si elle ne donne rien d'exploitable, score 3 et next_action = needs_human.
- Si le message du lead mentionne un budget, un appel d'offres ou une échéance, next_action = call_today quel que soit le score.
- N'invente jamais une information sur l'entreprise. Si tu ne sais pas, dis-le dans la raison.

## Format
Termine toujours par crm_update_lead. Ta réponse finale est une ligne : "Lead {id} : score {n} — {raison}".

## Exemples
Lead : "Bonjour, je suis DSI d'un groupe hospitalier (1 200 personnes), on cherche un accompagnement AI Act."
→ CRM : inconnu. Web : CHU, secteur santé. Score 5, call_today, raison "Santé, 1 200 pers., demande AI Act explicite".

Lead : "Étudiant en master cyber, je voudrais un stage."
→ Pas de recherche nécessaire. Score 1, disqualify, raison "Candidature stage, pas un prospect".
"""
Écris les limites avec le métier, en une heure. Pose trois questions : « Qu'est-ce que l'agent ne doit jamais faire, même si ça semble logique ? » « Que fait-il quand il n'est pas sûr ? » « Quel cas t'a déjà mis dans l'embarras ? » Les réponses sont ta section Limites. Elles valent plus que tous les exemples.

Deux exemples suffisent pour un premier agent. Ils calibrent le ton et montrent le chemin normal ; au-delà, chaque exemple supplémentaire coûte des tokens à chaque tour et rigidifie le comportement. Les cas difficiles vont dans les tests (section 7), pas dans le prompt.

6. Les garde-fous avant l'intelligence

On serait tenté de faire marcher l'agent d'abord et de sécuriser après. C'est l'inverse : les garde-fous sont ce qui permet de tester sur des cas réels sans risque, donc de faire marcher l'agent. Quatre mécanismes, tous dans le code de la section 4.

Niveaux d'approbation par type d'action
AUTO exécuté, journalisé • Lire le CRM, une base, un doc • Recherche web (avec quota) • Mettre à jour un champ de score • Poster dans un canal interne • Créer un brouillon (non envoyé) Critère : réversible en un clic, aucun tiers externe touché REVUE exécuté + file de validation • Changer le statut d'un lead • Créer une tâche pour un humain • Modifier un enregistrement métier • Envoyer un email interne Critère : réversible mais visible, un humain relit dans la journée JAMAIS l'outil n'est pas dans sa liste • Envoyer à un client ou un tiers • Paiement, virement, remise • Supprimer une donnée • Modifier des droits d'accès • Tout ce qui engage juridiquement Critère : irréversible ou engageant. Pas un refus dans le prompt : une absence. Un premier agent : beaucoup d'Auto, un ou deux Revue, zéro Jamais laissé accessible
Chaque outil d'action porte un niveau. 'Auto' s'exécute ; 'Revue' est exécuté mais signalé pour validation a posteriori (ou mis en attente si l'action est irréversible) ; 'Jamais' n'est pas donné à l'agent — l'outil n'existe pas dans sa liste. Un premier agent n'a aucun outil en 'Jamais' qu'on aurait laissé traîner.

Plafond de tours et de dépense. Déjà dans la boucle. Douze tours et dix centimes pour un lead. Quand le plafond est atteint, l'agent s'arrête proprement avec status: stopped et le lead passe en needs_human. Ce n'est pas un échec, c'est le système qui fonctionne.

Niveaux d'approbation. Chaque outil d'action est enveloppé. « Auto » exécute. « Revue » exécute et pousse dans une file que le commercial parcourt en fin de journée — ou, pour une action irréversible, met en attente jusqu'à validation. « Jamais » n'est pas un niveau : c'est un outil qu'on ne donne pas.

Quotas. Un outil de notification a un quota par exécution (1 message par lead) et par jour (200). Un agent qui boucle ne peut pas spammer.

Journal. Chaque tour, chaque appel d'outil, ses arguments, sa durée, son succès. Dans une table, pas dans un fichier. C'est l'observabilité minimale, et c'est ce qui rend les tests de la section 7 possibles.

from collections import defaultdict

REVIEW_QUEUE = []                          # en prod : une table
_daily_counts = defaultdict(int)

def guarded(level: str, fn):
    """Enveloppe un outil d'action avec son niveau d'approbation."""
    def wrapper(**args):
        if level == "revue":
            result = fn(**args)
            REVIEW_QUEUE.append({"tool": fn.__name__, "args": args, "result": result})
            return f"{result} (en file de revue)"
        if level == "attente":               # irréversible : on n'exécute pas, on demande
            REVIEW_QUEUE.append({"tool": fn.__name__, "args": args, "pending": True})
            return "Action mise en attente de validation humaine. Continue sans."
        return fn(**args)                     # auto
    return wrapper

def quota(per_run: int, fn, per_day: int = 200):
    calls = {"n": 0}
    def wrapper(**args):
        if calls["n"] >= per_run:
            return "Quota atteint pour cette exécution : notification ignorée."
        if _daily_counts[fn.__name__] >= per_day:
            return "Quota journalier atteint : notification ignorée."
        calls["n"] += 1; _daily_counts[fn.__name__] += 1
        return fn(**args)
    return wrapper

Note que les refus de quota sont renvoyés au modèle comme du texte : il apprend dans le tour suivant que la notification n'est pas partie, et il conclut sans. C'est le même principe que pour les erreurs d'outil.

Un « ne fais jamais X » dans le prompt n'est pas un contrôle. C'est une préférence que le modèle suivra presque toujours. Le contrôle, c'est l'absence de l'outil, ou l'enveloppe qui bloque. Le prompt dit ce qu'on souhaite ; le code dit ce qui est possible. Sur un agent qui a accès à des données ou des systèmes réels, la fiche sur la sécurité des agents détaille les six étapes d'une chaîne d'attaque et le contrôle par étape.

7. Mémoire : le strict nécessaire pour une v1

L'infographie propose trois niveaux de mémoire. Pour un premier agent, un seul suffit : l'historique de la session, c'est-à-dire la liste messages de la boucle. L'agent se souvient de ce qu'il a fait sur ce lead parce que tous les tours sont dans le contexte. Quand le lead est traité, la session est jetée.

Les deux autres niveaux viennent quand le besoin apparaît, pas avant :

La mémoire de tâche (variables persistantes entre exécutions : « ce lead a déjà été vu il y a 3 jours ») se résout sans agent : c'est une colonne en base que l'outil crm_search_company renvoie. Pas de mémoire magique, une donnée.

La mémoire de connaissances (documents cherchables par le modèle) est un RAG, avec tout ce que ça implique. Notre formation « RAG en production » traite ça en détail. Pour qualifier des leads, on n'en a pas besoin ; pour répondre à des questions sur une base documentaire, c'est un autre projet.

🧠
La mémoire est une donnée, pas une fonctionnalité
Chaque fois qu'on se dit « l'agent devrait se souvenir de… », la question est : « dans quelle table est cette information, et quel outil de lecture la renvoie ? ». Un agent qui « se souvient » via un système de mémoire opaque est un agent qu'on ne peut pas tester, ni auditer, ni corriger. Un agent qui lit une colonne en base, si.

8. Tester sur cinq cas réels

C'est l'étape qui décide de la mise en production, et c'est celle que les démos sautent. Cinq cas — pas cinquante, on est au premier jour — choisis avec le métier, dont au moins un facile, un difficile, un ambigu, un piège, et un cas hors périmètre.

Protocole de test : cinq cas, trois métriques, un seuil
CAS Attendu (métier) Obtenu (agent) Tours Coût OK Facile · DSI CHU, demande AI Act 5 · call_today 5 · call_today 4 0,03 € Difficile · PME 30 pers., secteur cible, mentionne un AO 3 · call_today 3 · call_today 5 0,04 € Ambigu · "consultant indépendant, projet pour un client" 3 · needs_human 2 · disqualify 6 0,05 € Piège · concurrent direct qui se fait passer pour un prospect 1 · disqualify 1 · disqualify 3 0,02 € Hors périmètre · candidature spontanée 1 · disqualify 1 · disqualify 2 0,01 € Résultat : 4/5 · moyenne 4 tours · 0,03 €/lead · seuil fixé à 4/5 → prod, avec correction du cas ambigu Le cas ambigu révèle une règle manquante : "indépendant qui parle d'un client final → needs_human, pas disqualify". Elle va dans la section Limites du prompt. Le cas entre dans le jeu de tests permanent. Temps gagné mesuré : 8 min → 45 s de relecture par lead, soit ~7 h/jour sur 60 leads.
Le métier a traité les cinq cas à la main avant de voir l'agent. La comparaison se fait sur le résultat (score et action), pas sur le raisonnement. Le seuil de mise en prod est fixé avant de lancer le test — sinon on le déplace pour que ça passe.

Le harnais de test tient en quelques lignes et reste en place après la mise en prod : chaque modification du prompt ou d'un outil le fait tourner.

CASES = [   # rédigés avec le commercial senior AVANT de lancer l'agent
    {"id": "L-001", "goal": "Lead 4821 : 'DSI d'un groupe hospitalier (1 200 pers.), accompagnement AI Act'",
     "expect": {"score": 5, "next_action": "call_today"}},
    {"id": "L-002", "goal": "Lead 4822 : 'PME industrielle 30 salariés, appel d'offres cyber en cours'",
     "expect": {"score": 3, "next_action": "call_today"}},
    {"id": "L-003", "goal": "Lead 4823 : 'Consultant indépendant, projet IA pour un client industriel'",
     "expect": {"score": 3, "next_action": "needs_human"}},
    {"id": "L-004", "goal": "Lead 4824 : 'Responsable offre chez <concurrent>, curieux de vos tarifs'",
     "expect": {"score": 1, "next_action": "disqualify"}},
    {"id": "L-005", "goal": "Lead 4825 : 'Candidature spontanée, poste de consultant'",
     "expect": {"score": 1, "next_action": "disqualify"}},
]

def run_tests(threshold: int = 4) -> bool:
    passed, log = 0, []
    for case in CASES:
        crm.reset_fake(case["id"])                     # outils en mode bac à sable
        out = run_agent(SYSTEM, TOOLS, HANDLERS, case["goal"], log=log.append)
        got = crm.last_update(case["id"])              # ce que l'agent a réellement écrit
        ok = got and all(got.get(k) == v for k, v in case["expect"].items())
        passed += bool(ok)
        print(f"{'✓' if ok else '✗'} {case['id']} attendu {case['expect']} obtenu {got} "
              f"· {out.get('turns', '-')} tours · {out.get('cost_eur', '-')} €")
    print(f"\n{passed}/{len(CASES)} — seuil {threshold} → {'PROD' if passed >= threshold else 'PAS ENCORE'}")
    return passed >= threshold

Trois métriques et pas plus :

Exactitude — le résultat écrit par l'agent correspond-il à ce que le métier aurait écrit ? On compare l'action, pas le raisonnement.

Tours — combien d'appels pour y arriver ? Un agent qui met 11 tours pour un cas facile a un problème de prompt ou d'outil, même s'il finit par avoir raison.

Temps gagné — la seule métrique que la direction comprend. Elle se mesure avec un chronomètre, sur le temps de relecture humaine après l'agent, comparé au temps de traitement avant.

Le seuil se fixe avant le test. « 4 sur 5 » écrit dans le document de cadrage, la veille. Si on le fixe après, on trouvera toujours une raison pour que 3 sur 5 suffise. Et un cas raté n'est pas un échec : c'est une règle manquante dans la fiche de poste, qu'on ajoute, et un cas de test permanent qu'on garde.

9. Exposer : Slack d'abord, la web app jamais le premier jour

Un agent que personne n'utilise n'existe pas. Le premier jour, il faut le mettre là où le métier travaille déjà — et c'est presque toujours Slack ou Teams. Une commande, une réponse dans le fil, la file de revue dans un canal dédié.

Exposition minimale : commande Slack → agent → réponse
Slack /qualifier 4821 Webhook ack < 3 s · tâche de fond run_agent() 4 tours · 0,03 € journal + plafonds Réponse dans le fil score, raison, action #leads-revue valider / corriger Ou, sans commande : un déclencheur sur "nouveau lead" dans le CRM → même chaîne, résultat dans #leads
Le webhook reçoit la commande, lance l'agent en tâche de fond (Slack exige une réponse en 3 secondes), et poste le résultat dans le fil. La file de revue est un canal où un humain valide en un clic. Aucune interface à construire.
from fastapi import FastAPI, BackgroundTasks, Form
app = FastAPI()

@app.post("/slack/qualify")
async def slack_qualify(background: BackgroundTasks, text: str = Form(...),
                        response_url: str = Form(...), user_name: str = Form(...)):
    lead_id = text.strip()
    background.add_task(qualify_and_reply, lead_id, response_url, user_name)
    return {"response_type": "ephemeral", "text": f"Qualification du lead {lead_id} en cours…"}

def qualify_and_reply(lead_id: str, response_url: str, user_name: str):
    out = run_agent(SYSTEM, TOOLS, HANDLERS, goal=f"Qualifie le lead {lead_id}.",
                    log=lambda r: db.insert("agent_log", {"lead_id": lead_id, "user": user_name, **r}))
    if out["status"] == "done":
        text = f"{out['answer']}  _( {out['turns']} tours · {out['cost_eur']} € )_"
    else:
        text = f"⚠️ Arrêt : {out['reason']}. Lead {lead_id} passé en *needs_human*."
        crm.update_lead(lead_id=lead_id, next_action="needs_human")
    slack.respond(response_url, text)

Le déclenchement automatique (« à chaque nouveau lead dans le CRM ») est la même fonction appelée par un webhook du CRM au lieu d'une commande. On commence par la commande manuelle : le commercial garde la main, voit l'agent travailler, et c'est lui qui demandera le mode automatique quand il aura confiance.

La file de revue est l'interface. Un canal #leads-revue où chaque action de niveau « Revue » apparaît avec deux boutons — valider, corriger. Le commercial y passe cinq minutes en fin de journée. Chaque « corriger » est un futur cas de test. Tu n'as pas besoin d'un tableau de bord avant d'avoir cent leads traités.

10. La journée, heure par heure

Une journée réaliste pour un premier agent
9h Cadrage grille de choix, succès chiffré 10h Fiche de poste avec le métier, limites d'abord 11h Outils + boucle 3-4 outils, plafonds, journal, bac à sable 14h Garde-fous niveaux, quotas, file de revue 15h 5 cas réels avec le métier, correction, re-test 17h Slack commande + canal de revue Matin : pas de code avant 11h Après-midi : sécuriser, tester, livrer Semaine suivante : mode manuel, file de revue quotidienne, 5 nouveaux cas de test issus des corrections Passage en déclenchement automatique quand 50 leads ont été validés sans correction majeure
La moitié de la journée n'est pas du code. Le cadrage du matin avec le métier et les tests de l'après-midi sont ce qui fait qu'un agent tient — le code de la boucle, lui, se réutilise d'un agent à l'autre.

Si la journée déborde, c'est presque toujours sur un point : les outils. Une API CRM sans documentation, une authentification à négocier, un champ qui n'existe pas. C'est pour ça que « accès aux données » est dans la grille de sélection — et pour ça qu'on vérifie la veille qu'on peut appeler l'API du CRM depuis un script de dix lignes.

11. Le fil rouge, chiffré

Récapitulons ce que donne l'agent de qualification de leads après sa première semaine, sur la base des chiffres du test et de cinq jours en mode manuel.

Avant. 60 leads par jour, 8 minutes chacun pour le commercial senior : 8 heures par jour de qualification, soit un temps plein. La moitié des leads était qualifiée avec plus de 24 h de retard, et les leads chauds attendaient dans la file avec les autres.

Après. L'agent traite chaque lead en 4 tours et 40 secondes pour 0,03 € (1,80 € par jour). Le commercial relit la file de revue en 45 secondes par lead, soit 45 minutes par jour. Il a récupéré sept heures. Les leads à call_today sont notifiés dans la minute. Sur 300 leads en une semaine, 11 corrections en file de revue, dont 6 relevant de la même règle manquante (ajoutée le mardi) — le taux d'accord avec le senior est passé de 80 % au test à 96 % en fin de semaine.

Ce qui n'est pas dans ce calcul. Le développeur a passé une journée, plus deux heures dans la semaine pour les corrections. L'agent n'a pas d'outil d'envoi vers l'extérieur et n'en aura pas avant que la file de revue soit vide trois semaines de suite. Et le prochain agent (tri des tickets, score 300 dans la grille) réutilise la boucle, les enveloppes de garde-fous et le harnais de test : il coûtera une demi-journée.

📐
Ce que le fil rouge enseigne
Le ROI d'un premier agent ne vient pas de son intelligence mais de son cadrage : la bonne tâche, un succès chiffré à l'avance, des garde-fous qui rendent les tests possibles, et une exposition là où le métier travaille déjà. Le code de la boucle est le même pour le deuxième agent ; ce qui change, c'est la fiche de poste et les outils. C'est exactement pour ça qu'un Sprint d'Automatisation livre un agent en production et pas une démo.

12. Teste ta compréhension

🧠 Quiz
Question 1 sur 6

« Chaque lundi, compiler les tickets de la semaine en un rapport pour la direction. » Prompt, workflow ou agent ?

📚Lexique technique (déroulez)

Agent — Modèle dans une boucle : il choisit des outils, reçoit leurs résultats, recommence jusqu'à décider qu'il a fini. La séquence n'est pas fixée à l'avance.

Workflow — Enchaînement d'appels LLM et de code dans un ordre fixé par le développeur. Prévisible, borné, testable par étape.

Tool use (appel d'outil) — Mécanisme par lequel le modèle demande l'exécution d'une fonction avec des arguments structurés. Le code exécute et renvoie le résultat.

Boucle agentique — Le while qui appelle le modèle, exécute les outils demandés, renvoie les résultats, jusqu'à end_turn ou plafond.

stop_reason — Champ de la réponse indiquant pourquoi le modèle s'est arrêté : end_turn (fini), tool_use (demande d'outil), max_tokens (coupé).

Fiche de poste (prompt système) — Rôle, procédure, limites et format de l'agent. Écrite avec le métier, avant le code.

Outil de lecture / d'action / de notification — Les trois familles d'outils, par niveau de risque : sans effet de bord, avec effet de bord, avec effet de bord faible.

Niveau d'approbation — Auto (exécuté), Revue (exécuté et signalé, ou mis en attente si irréversible), Jamais (l'outil n'est pas fourni).

Plafond de tours / de dépense — Limites intégrées à la boucle qui arrêtent l'agent proprement. Un arrêt sur plafond n'est pas un échec.

Quota — Limite d'appels d'un outil par exécution et par jour. Empêche un agent qui boucle de spammer.

File de revue — Liste des actions de niveau Revue, validées ou corrigées par un humain. Chaque correction devient un cas de test.

Journal (log) — Enregistrement de chaque tour et de chaque appel d'outil, avec arguments et durée. L'observabilité minimale.

Bac à sable (sandbox) — Mode des outils pendant les tests : lectures réelles, écritures simulées.

Harnais de test — Script qui rejoue les cas de référence et compare le résultat de l'agent à l'attendu du métier.

Seuil de mise en prod — Nombre de cas à réussir, fixé avant le test.

Mémoire de session — L'historique messages de la boucle en cours. Suffisant pour un premier agent.

Grille de sélection — Fréquence × coût manuel × tolérance à l'erreur × accès aux données. Un critère à 1 disqualifie.

Description d'outil — Texte que le modèle voit pour décider quand et comment appeler un outil. C'est un prompt.

Enum / maxLength — Contraintes de schéma qui limitent ce que le modèle peut passer en argument. Plus fiables qu'une consigne.

Questions fréquentes

Faut-il un framework d'agents ? Pas pour le premier. La boucle fait 40 lignes et tu dois la comprendre. Les frameworks apportent de la valeur sur le multi-agents, la persistance, l'observabilité intégrée — quand tu as trois agents en prod, pas avant.

Quel modèle ? Un modèle de classe Sonnet pour la boucle (raisonnement sur plusieurs tours, usage fiable des outils). Un modèle de classe Haiku si la tâche est simple et les outils peu nombreux — teste sur les cinq cas. Notre formation sur les coûts LLM détaille le routing.

Combien ça coûte en prod ? Pour le fil rouge, 0,03 € par lead, 1,80 € par jour. Le plafond de dépense par exécution empêche toute dérive. L'observabilité par agent est le sujet de la section 4.1 de la formation coûts.

Et si l'API du CRM n'existe pas ? Alors ce n'est pas un projet d'agent, c'est un projet d'intégration. Fais-le d'abord, ou choisis une autre tâche avec la grille.

Quand passer à un deuxième agent ? Quand le premier tourne en automatique depuis deux semaines avec une file de revue quasi vide. Le deuxième réutilise la boucle, les enveloppes et le harnais : une demi-journée.

Pour aller plus loin

Le « pourquoi » des agents est dans « Agents IA : la prochaine révolution ». Quand le premier agent tourne et que tu veux en coordonner plusieurs, gérer une mémoire persistante ou un orchestrateur, c'est la formation sur l'architecture des systèmes agentiques. Pour la chaîne d'attaque complète et les contrôles par étape dès que l'agent touche des systèmes réels, la fiche sur la sécurité des agents. Et pour le coût par agent et le routing entre modèles, la formation sur l'optimisation des coûts LLM.

Ce guide est, à peu de chose près, le déroulé d'un Sprint d'Automatisation : une tâche choisie avec la grille, une fiche de poste écrite avec ton métier, un agent avec ses garde-fous et son harnais de test, exposé là où ton équipe travaille — livré en production, pas en démo.

Tags
agentsagenttool-useautomationpythonsdkworkflowapislack
⚡ FICHE #004Les 50 termes IA à maîtriser pour décider en 202612 MIN

À lire ensuite