LECTURE · EN DIRECT v3.2.1 QC · CA EN
notes-terrain/tx-017 · publié 2026·05·09 · 8m de lecture · nombre de mots 1 420
--:--:-- UTC
QUEBEC · 46.81°N -71.21°W
racine / notes-terrain / tx · 017
tx · 017 agents · planificateur 2026·05·09 8m de lecture 1 420 mots diff +642 / −94

Construire un planificateur d'agent qui sait s'arrêter.

La plupart des échecs d'agents ne sont pas de mauvaises réponses : ce sont des boucles infinies. Nous avons ajouté un budget de confiance à notre planificateur et la latence p99 a chuté de 38 %.

JP
Jean Pierre Levac
Fondateur · Acceleratech

Pendant des mois, notre rotation d'astreinte avait un récidiviste : l'agent qui ne voulait tout simplement pas s'arrêter. Il replanifiait, requêtait à nouveau, se reposait la même sous-question en la formulant légèrement différemment, accumulant de la latence jusqu'à ce qu'un timeout finisse par le tuer. La trace atterrissait dans nos tableaux de bord comme un mauvais ECG, une ligne plate de tentatives suivie d'une falaise.

Nous avons d'abord blâmé la qualité des prompts. Ensuite la fiabilité des outils. Puis le modèle lui-même. Tout cela était réel, mais rien de tout cela n'était la cause profonde. La cause profonde était architecturale : notre planificateur n'avait aucun mécanisme raisonné pour cesser d'essayer.

↳ résumé La terminaison est un primitif, pas un filet de sécurité. Encapsulez chaque étape de planification dans un budget de confiance qui se dépense sur le raisonnement et se reconstitue sur les observations nouvelles. Quand le solde atteint zéro, escaladez vers une réponse partielle et élégante. Pas une nouvelle tentative. Pas un timeout. La latence p99 a chuté de 38 %, les boucles incontrôlées de 91 %.

Le problème de boucle

Une boucle de planification survient quand les croyances d'un agent sur le monde ne convergent pas. Il émet une action, observe un résultat qu'il juge ambigu, met à jour son état interne d'une façon qui réactive la même branche de raisonnement, et recommence. Vu de l'extérieur, ça ressemble à du patinage. Vu de l'intérieur, si l'on peut dire, ça ressemble à de la diligence.

La diligence sans condition de terminaison n'est qu'une façon élégante de manquer de temps.

Les mesures correctives habituelles (nombre d'étapes maximal, timeouts, déduplication des appels d'outils) traitent le symptôme. Elles coupent la boucle après qu'elle tourne déjà. Ce que nous voulions, c'était un mécanisme qui empêche la boucle de se former en premier lieu, ou du moins qui remonte une réponse dégradée propre quand la confiance n'est véritablement pas récupérable.

Le budget de confiance

Le budget de confiance est une valeur de première classe dans le contexte d'exécution de notre planificateur. Pensez-y comme une monnaie : chaque étape de raisonnement dépense du budget, et chaque information nouvelle et non redondante en reconstitue. Quand le solde atteint zéro, le planificateur ne retente pas. Il escalade vers un repli élégant.

fig · 01 / confidence-budget · state machine ● spend / earn / depleted
PLAN STEP − SPEND OBSERVE + EARN BUDGET CHECK CONTINUE → next step FALLBACK best-effort ok depleted
fig · 01 l'étape du planificateur est une machine à états sur un scalaire unique : le solde. Chaque étape soustrait un coût fixe ; chaque observation nouvelle ajoute du budget proportionnel à sa teneur en information. L'épuisement est une sortie propre, pas une erreur.

L'asymétrie dépense/gain est le choix de conception central. Les observations redondantes, les réponses d'outils dont le contenu est sémantiquement équivalent à quelque chose déjà dans le contexte, ne rapportent aucun budget. Les observations nouvelles à forte information en rapportent proportionnellement à la réduction d'incertitude qu'elles apportent. Les étapes qui ne font que reformater ou réexaminer le contexte existant dépensent au taux normal sans rien rapporter.

Esquisse d'implémentation

Le primitif lui-même est petit. Une trentaine de lignes de Python logées dans notre package planificateur, câblées dans le contexte d'exécution qui traverse déjà chaque étape. Deux unités d'état, trois méthodes, un point de décision dans Planner.step.

planner/budget.py · 28 lines python · 3.11
from dataclasses import dataclass, field

@dataclass
class ConfidenceBudget:
    initial: float = 1.0
    balance: float = field(default_factory=lambda: 1.0)
    step_cost: float = 0.08       # flat spend per planning step
    novelty_gain: float = 0.12    # max earn per novel observation

    def spend(self) -> None:
        self.balance = max(0.0, self.balance - self.step_cost)

    def earn(self, novelty_score: float) -> None:
        # novelty_score: 0.0 = fully redundant, 1.0 = fully novel
        gain = novelty_score * self.novelty_gain
        self.balance = min(self.initial, self.balance + gain)

    def is_depleted(self) -> bool:
        return self.balance <= 0.05   # 5% threshold, graceful exit

class Planner:
    def step(self, ctx: PlanContext) -> PlanResult:
        self.budget.spend()
        if self.budget.is_depleted():
            return self.best_effort_reply(ctx)

        observation = self.execute_action(ctx)
        novelty = self.novelty_scorer.score(observation, ctx.seen)
        self.budget.earn(novelty)
        return PlanResult(observation=observation, budget=self.budget)

Le novelty scorer mérite son propre billet. Nous utilisons une comparaison d'embeddings légère sur une fenêtre glissante d'observations récentes, avec un seuil de similarité calibré sur notre surface d'outils. Les valeurs exactes ci-dessus (0.08 de dépense, 0.12 de gain) sont empiriques et seront différentes pour votre charge de travail. Le ratio compte plus que les valeurs absolues.

Ce que « repli élégant » signifie concrètement

C'est la partie qui nous a pris le plus de temps à mettre au point. Un planificateur qui plante simplement à l'épuisement du budget ne vaut pas mieux qu'un timeout. Le repli doit être une vraie réponse, incomplète, prudente, clairement partielle, mais utile. Nous avons retenu trois modes.

Résultats

latence p99
−38%
vs. même charge, planificateur précédent
boucles incontrôlées
−91%
timeouts sur chemins de replanification infinis
csat sur partiels
+4pt
vs. repli erreur générique précédent
métriqueavantaprèssignal
latence p501,4 s1,2 s−14 %
latence p9942 s26 s−38 %
taux de timeout3,1 %0,28 %−91 %
part des réponses partielles0 %6,4 %nouveau
taux d'abandon fermes.o.1,8 %cible < 2 %

L'amélioration de la latence p99 nous a surpris. Nous pensions que la p50 en serait la principale bénéficiaire. En pratique, la p99 s'est le plus améliorée parce que les boucles incontrôlées étaient concentrées dans la queue. Une fois qu'elles se résolvaient rapidement en replis, toute la queue de la distribution de latence s'est comprimée.

Le chiffre de satisfaction sur les réponses partielles mérite d'être contextualisé : nous le comparions au comportement précédent où un planificateur épuisé retournait une erreur générique. Une réponse partielle bien formulée s'avère considérablement plus utile qu'un « quelque chose a mal tourné ». Les utilisateurs peuvent agir sur une information partielle. Ils ne peuvent pas agir sur un 500.

Ce que nous ferions différemment

Nous avons initialisé les budgets de manière uniforme. Avec le recul, la complexité de la requête devrait informer le solde de départ. Une simple recherche reçoit un budget modeste ; une tâche de recherche ouverte devrait démarrer avec plus de marge avant que la courbe dépense-nouveauté ne s'enclenche. Nous construisons cela maintenant et nous attendons à ce que ça pousse les scores de satisfaction de quelques points supplémentaires.

Nous n'avons pas non plus pris en compte les courbes de nouveauté propres à chaque outil. Certains outils sont intrinsèquement plus bruités : leurs réponses varient en surface tout en encodant la même information. Le novelty scorer pénalisait ces outils injustement jusqu'à ce que nous ajoutions une calibration par outil. Si vous implémentez ceci, prévoyez du temps pour ce réglage.

Savoir quand s'arrêter est une capacité, pas une limitation. Le planificateur qui cède avec élégance est plus utile que celui qui s'acharne indéfiniment.

La leçon plus profonde est que le comportement de terminaison est une décision produit, pas seulement une décision d'ingénierie. La façon dont votre agent échoue, ou refuse d'échouer élégamment, fait partie de l'expérience utilisateur. Construisez-le explicitement.

Si vous souhaitez que nous examinions comment votre agent se termine, le formulaire de contact est la voie la plus rapide. Nous offrons des revues gratuites de 30 minutes pour les systèmes en production.

· fin · tx 017 ·
JP
Jean Pierre Levac

Fondateur d'Acceleratech, le pôle de services en IA et automatisation des flux de travail du Groupe de Croissance Numérique JPL. Rédige et révise les notes de terrain publiées ici.

Rédigé et révisé par Jean Pierre Levac. Note de transparence →

Vous avez aimé / recevez le prochain.

Notes de terrain, postmortems et opinions tranchées sur ce qui fonctionne vraiment en production dans l'IA agentique. Aux deux semaines.

© 2026 Acceleratech · notes-terrain · v3.2.1 ← retour au fil Une Stratégie de croissance numérique par Groupe de Croissance Numérique JPL.