Retour aux ressources
// technique · agents

D’un prompt à l’agentique

Mon premier agent LangGraph, en refondant l’IA de Klickbee — et pourquoi un bon prompt cesse de suffire dès que la tâche devient réelle.

Technique6 juil. 2026~8 min · intermédiaire
LangGraphLLMZodPostgresLangfuseGitLab API
01

Au départ : un prompt, un objet JSON

La première version de l’IA de Klickbee tenait en une idée simple : un prompt, une réponse. L’utilisateur écrit un brief, on l’injecte dans un gros prompt, et le modèle renvoie un objet structuré — une roadmap avec ses jalons et ses tâches. Techniquement : un seul appel generateObject, un schéma Zod pour garantir la forme.

Et honnêtement, ça marche. Pour transformer « refonte du site vitrine » en une roadmap plausible, un bon prompt suffit. Rapide à écrire, facile à comprendre, peu coûteux.

i

Le problème : ce modèle atteint un plafond dès que la tâche devient réelle.

02

Les limites du one-shot

En utilisant vraiment le produit, quatre défauts reviennent tout le temps. Aucun ne se règle avec « un meilleur prompt » — ils sont architecturaux.

01
Il invente au lieu de se renseigner

Reconstruire la roadmap d’un dépôt GitLab à partir d’un simple prompt donne une fiction crédible, pas ce qui s’est passé. Il n’a pas accès aux commits, aux merge requests, aux issues.

02
Il n’a aucune mémoire

Chaque échange repart de zéro. L’utilisateur explique une contrainte, et deux messages plus tard l’IA la redemande. Ça vire à l’interrogatoire.

03
Il ne se vérifie pas

Un one-shot rend sa première réponse, bonne ou mauvaise. Pas de recul, pas d’auto-critique.

04
Il échoue en silence

Un champ mal typé renvoyé par le modèle, et tout le tour plante avec un « Failed to parse » incompréhensible côté utilisateur.

03

Le passage à l’agentique

« Agent », ce n’est pas un buzzword pour « prompt un peu plus malin ». Le vrai changement, c’est de passer de générer une réponse à mener une tâche. Sur Klickbee, chaque IA importante est devenue un graphe (LangGraph) avec des étapes explicites.

// le graphe (langgraph)
gather
contexte
clarify
question ?
draft
décider
review
auto-relire
apply
appliquer
review ↺ draft — boucle si insuffisantclarify → human-in-the-loop
Postgres — état durableLangfuse — tracé
rassembler le contexte (gather) — via des outils : lire la mémoire, lire l’activité GitLab réelle, lister les projets existants ;
décider — soit poser une question, soit produire des opérations concrètes ;
s’auto-relire (review) — le modèle critique son propre plan et boucle si c’est insuffisant ;
demander à l’humain quand c’est vraiment bloquant (human-in-the-loop, avec interruption et reprise) ;
appliquer.

Le tout est durable — l’état persiste dans Postgres, un run survit à un crash ou à une reprise plus tard — et tracé : chaque étape, chaque appel LLM est visible dans Langfuse pour déboguer et scorer.

un prompt

répond.

une entrée, une sortie
aucun accès au réel
aucune mémoire entre les tours
un agent

va chercher, décide, vérifie, collabore, et reprend.

s’ancre sur des données réelles via des outils
se relit et se corrige avant de montrer
se souvient, et reprend là où il s’est arrêté
04

Quatre cas concrets

Génération de roadmap

Le brief passe désormais par gather → clarify → draft → review → validate → apply. Le nœud draft est lui-même agentique : une boucle où le modèle appelle ses outils pour s’ancrer avant d’écrire. S’il manque une info clé — échéance, périmètre — il pose une question plutôt que de deviner. Puis il se relit et se corrige avant de montrer quoi que ce soit.

Reconstruction depuis GitLab

Ici l’ancrage change tout. L’agent lit les vrais commits, merge requests et issues, en mode autonome, et reconstruit une roadmap fidèle à ce qui a été livré — au lieu d’une histoire inventée.

i

Détail révélateur : l’API GitLab ne renvoie pas de total de commits sur certains endpoints ; il a fallu paginer pour ne plus afficher « 100 commits » à l’infini. L’agentique force à regarder le réel en face.

Chat d’ajustement

C’est là que la leçon a été la plus nette. La première version interrogeait l’utilisateur, une question après l’autre, en oubliant les réponses précédentes. On l’a basculée en act-first : agir par défaut avec des hypothèses explicites, ne demander qu’en cas de blocage réel, et se souvenir de toute la conversation. Comme un bon collègue, pas comme un formulaire.

Génération d’équipe

Le petit dernier : on décrit « qui bosse sur quoi », l’agent étiquette les postes, compose les équipes, et — parce qu’il lit le roster existant — réutilise les membres et équipes déjà là au lieu de créer des doublons. Il pose une question quand deux personnes se marchent sur les pieds.

05

L’intérêt — et le coût

Ce que l’agentique apporte, concrètement :

Ancrage plutôt que fluff : l’IA travaille sur des données réelles, pas sur des suppositions.
Mémoire : les décisions et préférences survivent d’un échange à l’autre.
Auto-vérification : le modèle se relit ; côté dev, on ajoute même une revue adversariale des changements.
Collaboration : il demande quand il faut, agit sinon — fini l’interrogatoire et l’hallucination confiante.
Robustesse et observabilité : sorties structurées tolérantes, streaming de progression, durabilité, traçabilité complète.
!

Soyons honnêtes sur la facture : plus de complexité (un graphe, des nœuds, des outils), plus de tokens (plusieurs appels au lieu d’un), plus d’infra (une base pour l’état, du tracing). Un generateObject d’une ligne devient un sous-système.

un prompt suffit
reformuler un texte
classer, catégoriser
extraire un champ d’un document
l’agent gagne
se renseigner sur le réel
tenir dans la durée (mémoire, reprise)
se vérifier et collaborer avec un humain
06

La bascule mentale

Le vrai déclic n’est pas technique, c’est un changement de posture. On arrête de se demander « quel prompt me donnera la bonne réponse ? » et on commence à se demander « quelles étapes une personne compétente suivrait-elle pour faire ce travail ? » — puis on donne à l’IA les outils, la mémoire et les points de contrôle pour suivre ces étapes.

Sur Klickbee, c’est ce qui a fait passer l’IA de démo qui impressionne à outil sur lequel on peut vraiment travailler.

07

Ce qui rend un graphe « agentique »

Il faut lever une ambiguïté que j’ai moi-même mis du temps à clarifier : un graphe LangGraph n’est pas automatiquement un agent. Anthropic pose la distinction la plus nette que je connaisse — un workflow orchestre LLM et outils sur des chemins de code prédéfinis, un agent laisse le modèle diriger son propre processus et décider quels outils appeler. Sur Klickbee, le graphe global reste largement un workflow (gather → clarify → draft → review → apply, des arêtes fixes), mais le nœud draft, lui, est vraiment agentique : c’est une boucle où le modèle choisit d’appeler tel outil, de reboucler ou de s’arrêter.

i

Le bon réflexe : rester en workflow tant que le chemin est connu d’avance, et n’ouvrir une zone agentique que là où la décision « quoi faire ensuite » dépend vraiment de ce que le modèle vient de découvrir. Chaque tour autonome coûte de la latence, des tokens, et laisse une erreur précoce se propager.

L’état durable, concrètement

La durabilité dont je parlais n’est pas un vague « on sauvegarde en base ». LangGraph la modélise avec deux notions précises. Un checkpointer persiste l’état du graphe à chaque superstep, rattaché à un thread_id : c’est ce qui permet à un run de survivre à un crash et de reprendre exactement où il en était. Et un store, lui, sert la mémoire durable qui traverse les threads — les préférences et décisions qui doivent survivre d’une conversation à l’autre. La mémoire du chat d’ajustement, c’est le store ; la reprise après interruption, c’est le checkpointer.

checkpointerétat d’un thread, snapshot à chaque étape — reprise, time-travel, tolérance aux pannes
storemémoire longue qui traverse les threads — préférences, décisions, roster
thread_idla clé qui rattache un run à son historique de checkpoints

L’interruption n’est pas un try/catch

Le human-in-the-loop m’a réservé le piège le plus subtil. Quand un nœud appelle interrupt() avec une valeur JSON-sérialisable, le graphe fige son état et attend indéfiniment ; on reprend plus tard, potentiellement dans une autre requête HTTP, avec Command(resume=…) et le même thread_id — la réponse humaine devient la valeur de retour de l’interrupt. Le piège : à la reprise, le nœud redémarre depuis le début, il ne repart pas de la ligne de l’interrupt. Tout code exécuté avant sera rejoué. La leçon : on met les effets de bord (écritures, appels d’API non idempotents) après le point d’interruption, pas avant.

draft-node.tscopier
// Le nœud agentique : boucle outillée + auto-relecture avant de rendre
async function draftNode(state: GraphState) {
// effets de lecture seule : OK avant un éventuel interrupt
const grounding = await gatherTools.run(state);
let draft = await model.generateObject({
schema: RoadmapSchema, // Zod : la forme est garantie ou l'appel échoue
prompt: buildDraftPrompt(state, grounding),
});
// boucle évaluateur-optimiseur : le modèle critique son propre plan
for (let i = 0; i < MAX_REVIEWS; i++) {
const review = await model.generateObject({
schema: ReviewSchema, // { ok: boolean; issues: string[] }
prompt: `Critique ce plan, cite ce qui manque :\n\${JSON.stringify(draft)}`,
});
if (review.object.ok) break;
draft = await model.generateObject({
schema: RoadmapSchema,
prompt: buildRevisePrompt(draft, review.object.issues),
});
}
// blocage réel : on demande à l'humain. Les écritures viennent APRÈS.
if (needsHuman(draft)) {
const answer = interrupt({ question: whatIsMissing(draft) });
return applyHumanAnswer(draft, answer);
}
return { draft: draft.object };
}
08

La boucle d’auto-relecture, en détail

« Il se relit » mérite d’être démonté, parce que c’est un patron nommé et étudié, pas une astuce maison. Anthropic l’appelle évaluateur-optimiseur : un LLM produit, un second évalue et renvoie un feedback, on boucle. Il ne brille que sous deux conditions — des critères d’évaluation clairs, et un gain mesurable à chaque itération. Sur la génération de roadmap, les deux sont réunies : « chaque tâche a-t-elle un jalon parent ? y a-t-il des doublons ? le périmètre du brief est-il couvert ? » sont des questions vérifiables.

La version la plus ambitieuse de ce patron s’appelle Reflexion. LangChain la décrit bien : au lieu d’une auto-critique purement interne, l’acteur ancre sa critique sur des données externes — il va chercher des preuves avant de se juger. Le guide Reflexion décompose ça en trois rôles : un acteur qui produit, un évaluateur qui score la trajectoire, et une auto-réflexion qui transforme ce score en consigne verbale pour le tour suivant. C’est exactement ce que fait mon nœud draft quand il relit les vrais commits GitLab avant de valider un plan.

auto-critique interne

le modèle se juge sur ce qu’il « pense ».

cheap, un seul modèle, deux prompts
peut renforcer sa propre erreur
bon pour la forme, le style, la cohérence
réflexion ancrée (Reflexion)

le modèle va chercher des preuves avant de se juger.

plus de tokens, des appels d’outils
corrige les faits, pas juste la forme
indispensable dès qu’on touche au réel
!

Une boucle sans garde-fou tourne à l’infini ou explose la facture. Trois protections : un plafond d’itérations (MAX_REVIEWS), une condition d’arrêt claire (« review.ok === true »), et une sortie structurée validée à chaque tour. Chez moi, le schéma Zod fait double emploi : la génération échoue plutôt que de renvoyer un objet invalide, ce qui transforme un « Failed to parse » silencieux en erreur qu’on peut rattraper et rejouer.

09

Sources & ressources

01Anthropic — Building Effective AgentsLa référence sur workflow vs agent et sur le patron évaluateur-optimiseur. À lire avant d’ajouter la moindre autonomie.02LangGraph — Persistence (checkpointers & threads)Comment l’état devient durable : checkpointer par thread, store cross-thread, reprise après crash.03LangGraph — Interrupts (human-in-the-loop)interrupt() et Command(resume=…), et le piège du nœud rejoué depuis le début à la reprise.04LangChain — Reflection AgentsBoucle génération/critique et implémentation de Reflexion en tant que graphe LangGraph.05Prompt Engineering Guide — ReflexionLes trois rôles — acteur, évaluateur, auto-réflexion — expliqués simplement.06AI SDK — Generating Structured DatagenerateObject + schéma Zod : sorties validées, et l’erreur levée quand l’objet est invalide.

La vraie question n’est pas « prompt ou agent ? » mais « qu’est-ce que la tâche exige ? ». Reformuler, classer, extraire : un prompt suffit. Mener une tâche qui doit se renseigner, tenir dans la durée, se vérifier et collaborer : l’agent gagne, largement.