Boucles d’agent bornées
Une boucle d’outils permet à un modèle d’observer un résultat, de choisir une autre action et de poursuivre. C’est utile pour le débogage et les travaux en plusieurs étapes, mais une mauvaise hypothèse peut alors entraîner une suite d’écritures, de tentatives répétées et un contexte qui grossit.
La séparation importante est simple : le modèle propose ; le harnais d’exécution décide de ce qui peut être lancé et de ce qui compte comme une réussite.
Formes courantes de boucles
Le modèle importe moins que les conditions d’arrêt qui l’entourent.
Ce que le harnais doit prendre en charge
Budget et arrêt
Fixez les limites avant l’exécution : étapes, temps écoulé, usage du modèle, usage des outils, ainsi que les fichiers ou services autorisés. Arrêtez-vous lorsqu’une limite est atteinte, lorsque l’utilisateur annule, lorsque les éléments de preuve requis ne sont pas disponibles ou lorsque les échecs répétés montrent que la stratégie actuelle ne progresse pas.
Un coupe-circuit pour les appels répétés peut aider, mais son seuil doit correspondre à l’opération. Réessayer une lecture n’est pas la même chose que réessayer un paiement ou un déploiement.
Validation des outils
Validez hors du modèle les noms d’outils, les schémas d’arguments, les chemins, les autorisations et les effets de bord. Préférez des tableaux d’arguments directs à l’interpolation dans un shell, tout en vérifiant les options dangereuses et la sémantique des chemins. Considérez la sortie des outils comme une entrée non fiable, et non comme de nouvelles instructions.
Vérification
La phrase finale d’un modèle n’est pas un signal d’achèvement. Le vérificateur peut être une suite de tests, une vérification de schéma, une comparaison exacte d’artefact, une assertion dans un navigateur ou une revue humaine. Il doit tester le comportement visé et être assez indépendant pour que l’agent ne puisse pas le faire passer au vert en supprimant ou en affaiblissant le contrôle.
État durable
Conservez la transcription complète et la sortie brute des outils hors du prompt actif. Pour un travail long, enregistrez un bref état de tâche contenant :
- l’objectif et le périmètre autorisé ;
- les fichiers ou artefacts modifiés ;
- les contrôles déjà exécutés et leurs résultats ;
- les approches échouées à éviter ;
- la question ouverte et l’action suivante.
Cet état aide un contexte neuf à reprendre le travail, mais il doit être mis à jour à partir des résultats observés, et non de la confiance du modèle.
Annulation et nettoyage
Les outils de longue durée ont besoin de délais d’expiration, d’un suivi des processus et de nettoyage. Annuler dans l’interface doit aussi annuler le sous-processus ou la tâche en arrière-plan. Sinon, un agent apparemment arrêté peut continuer à écrire sur le disque.
Une boucle de contrôle minimale
Le code suivant est du pseudocode ; les interfaces d’outils et de modèles varient selon le harnais.
for step in range(max_steps):
if cancelled() or budget.exhausted():
return STOPPED
context = select_working_context(state)
proposal = model.propose(context)
if proposal.is_final:
return verify_final(proposal, state)
checked = policy.validate(proposal.tool_call)
if not checked.allowed:
state.record_denial(checked.reason)
continue
result = tools.execute(checked.call, timeout=checked.timeout)
state.record(result)
if repeated_failure(result, state):
return NEEDS_REVIEW
Les implémentations réelles nécessitent aussi la gestion des exceptions, des règles d’idempotence, le contrôle de concurrence et des journaux expurgés. Ce pseudocode est utile parce qu’il montre où placer ces préoccupations : autour de l’appel au modèle, et non dans un prompt qui demande au modèle d’être prudent.
Indices de progrès réel
Un ensemble d’échecs qui diminue, un nouveau test discriminant, un diff plus petit et justifié ou une ambiguïté levée constituent des progrès. Reformuler le même diagnostic, ajouter des abstractions sans éléments de preuve ou prolonger l’exécution n’en sont pas.
La meilleure boucle est généralement la moins autonome qui puisse terminer la tâche de façon fiable. N’ajoutez des exécutants parallèles, des couches de planification et de l’autocritique que lorsqu’un échec mesuré le justifie.
Le contrôle général présenté ci-dessus peut être comparé à l’implémentation versionnée de Pi ci-dessous. La configuration et les extensions figurent dans le cas Pi ; la reprise entre processus, dans les agents de longue durée.
Comment une boucle d’agent Pi s’exécute réellement
La vidéo sur l’architecture de Pi représente la boucle comme un modèle qui appelle un outil puis reçoit son résultat. L’idée est juste, mais les versions actuelles de agent-loop.ts et d’AgentSession montrent trois couches : la session prépare la requête, la boucle de bas niveau coordonne modèle et outils, puis la session gère persistance, compaction et reprises.
Beaucoup de choses précèdent l’appel au modèle
L’entrée utilisateur ne va pas directement au modèle. AgentSession.prompt() laisse d’abord les Extensions la traiter ou la transformer, puis développe un Skill ou un Prompt Template appelé explicitement. Si l’Agent travaille déjà, le nouveau message doit entrer dans la file Steering ou Follow-up au lieu de s’insérer au milieu d’un appel d’outil.
La session vérifie ensuite le modèle et l’authentification, puis décide si l’ancien contexte doit être compacté. Un événement before_agent_start peut aussi ajouter des messages personnalisés ou modifier le system prompt de cette exécution. Ce n’est qu’après ces étapes que le message utilisateur rejoint la boucle de bas niveau.
L’implémentation de bas niveau contient deux boucles
La boucle interne enchaîne les appels au modèle. Avant l’appel suivant, Pi peut actualiser le system prompt, les outils, le modèle et le niveau de raisonnement, puis injecter les messages Steering à une frontière de tour sûre. Le contexte est ensuite converti au format attendu par le fournisseur actif, avant la génération en streaming d’un Assistant Message.
Si cette réponse contient des appels d’outils, Pi les exécute, transforme chaque résultat en message toolResult, puis rappelle le modèle. La boucle interne ne s’arrête que lorsqu’il ne reste ni appel d’outil ni message Steering.
La boucle externe traite les messages Follow-up. Elle ne les récupère qu’une fois la chaîne d’outils et la file Steering épuisées, puis relance la boucle interne. Steering corrige donc la direction avant le prochain appel au modèle ; Follow-up poursuit le travail au moment où la tâche courante allait se terminer.
Dans Pi 0.84.3, la référence des raccourcis associe Entrée à Steering et Alt+Entrée à Follow-up ; Windows et WSL utilisent Ctrl+Q par défaut pour Follow-up. Alt+Haut remet les messages en attente dans l’éditeur (Alt+Q par défaut sous Windows et WSL), tandis que Échap interrompt l’exécution et restaure les messages non traités.
Un outil demandé ne s’exécute pas immédiatement
Pi vérifie d’abord que l’outil existe, prépare ses arguments et les valide. beforeToolCall peut bloquer l’exécution. Après le retour de l’outil, afterToolCall peut réécrire le résultat ou transformer un succès en erreur. Les appels peuvent être parallèles ; un outil marqué Sequential, ou un réglage global séquentiel, impose l’ordre.
Une autre protection mérite d’être notée. Si la réponse du modèle est tronquée par sa limite de sortie, Pi n’exécute pas les appels dont les arguments semblent malgré tout valides. Tous les appels de cette réponse deviennent des échecs et le modèle doit les soumettre à nouveau. Sans cela, un JSON incomplet pourrait passer la validation par hasard et déclencher une mauvaise action.
L’arrêt de la boucle ne signifie pas que la tâche a réussi
La boucle de bas niveau s’arrête lorsqu’il ne reste ni outil, ni Steering, ni Follow-up, ou lorsqu’une erreur, une annulation ou une condition d’arrêt externe y met fin. Pi émet alors agent_end.
Cela signifie seulement que l’Agent ne lancera pas un nouvel appel au modèle. Cela ne prouve pas que le code est correct, que les fichiers correspondent à la demande ou que l’objectif est atteint. Tests, contrôles de schéma, assertions navigateur et validation humaine restent hors de la boucle. Un modèle qui écrit « terminé » et une tâche réellement terminée sont deux événements différents.
La compaction et les reprises appartiennent à la session
Le mécanisme de compaction de Pi ne se contente pas de vérifier un compteur de Tokens une fois par tour. Il intervient avant un nouveau Prompt, avant l’appel suivant après des résultats d’outils et après une exécution de bas niveau. Lorsque le seuil est franchi, les anciens messages deviennent un résumé tandis que les plus récents restent disponibles. Un dépassement récupérable peut déclencher une compaction suivie d’une seule reprise.
Les messages sont aussi écrits dans une Session JSONL arborescente. Cet arbre conserve la conversation et les résultats d’outils, pas des snapshots du système de fichiers. Changer de branche de session n’annule pas les fichiers déjà écrits sur le disque.
La boucle à retenir
Une boucle d’agent ne consiste pas à « laisser le modèle réfléchir jusqu’à ce qu’il termine ». C’est une suite de relais explicites : la session prépare le contexte, le modèle propose une action, le harnais valide et exécute un outil, puis le résultat revient dans le contexte. La session conserve, compacte, reprend et met en file. Enfin, une validation externe décide si l’exécution a réellement accompli la tâche.