Tutorial For Power Users

Laisser Hermes tourner jusqu'au bout : `/goal` et `/subgoal` en pratique

Hermes Agent

Hermes Agent

@hermesagents

May 17, 2026

8 min de lecture

La plupart des agents IA tournent un tour à la fois. Tu tapes, ils répondent, ils attendent. La boucle, c'est toi qui la fais. L'agent n'est qu'un appel de fonction.

Hermes Agent a ce mode-là aussi — c'est même le défaut. Mais il embarque un autre mode, appelé /goal, où c'est l'agent qui fait tourner la boucle. Tu poses un objectif plus des critères de succès, l'agent propose, exécute, évalue, recommence, et continue jusqu'à ce qu'un judge LLM à part accepte que les critères sont remplis. v0.14.0 (16 mai 2026) a ajouté /subgoal pour que tu puisses superposer des critères supplémentaires sur une boucle déjà en route, sans la redémarrer (#25449).

Cet article démonte ce qui se passe vraiment, quand c'est le bon outil, et les modes d'échec qui en font le mauvais.

Le mode par défaut (pour le contraste)

Chaque session de chat dans Hermes, c'est un tour par message utilisateur. L'agent lit ton message, appelle éventuellement des outils, puis renvoie une réponse. Si la tâche n'est pas finie, c'est toi qui le pousses : « continue », « réessaie », « et X ? ». La boucle externe, c'est toi.

C'est très bien pour du travail exploratoire — « explique-moi ce code », « rédige une note », « trouve-moi un bug ». Tu veux que l'agent fasse une pause après chaque étape pour pouvoir réorienter.

C'est moins bien pour des tâches dont la condition de succès est concrète et dont le chemin pour y arriver est itératif. « Refais ce module jusqu'à ce que pytest passe » est une tâche de trente tours si tu pilotes chaque tour. Avec /goal, c'est une seule commande.

Ce que /goal fait vraiment

/goal Make all tests in tests/api/ pass. Don't change the test assertions. Done when pytest exits 0.

Quand tu envoies ça, trois choses se produisent :

  1. 1.Le texte de l'objectif devient le prompt cible du worker. À chaque tour suivant, le modèle worker reçoit un system message qui contient l'objectif et la meilleure tentative actuelle.
  2. 2.Un appel LLM « judge » séparé tourne après chaque tour du worker. Le judge voit l'objectif, l'état courant et la complétion proposée. Il renvoie soit « done » (la boucle sort), soit « continue, voilà ce qu'il manque encore ».
  3. 3.La boucle continue jusqu'à ce que le judge dise done — ou jusqu'à ce que tu l'arrêtes avec /stop, ou jusqu'à ce qu'elle tape la limite d'itérations configurée.

Le judge, c'est la pièce clé. Ce n'est pas le même appel LLM que le worker, et il ne voit pas la chaîne de pensée — uniquement l'objectif et l'état courant. C'est cette séparation qui fait marcher /goal : un modèle worker déjà convaincu que sa réponse est juste est un mauvais juge. Un appel LLM frais sans contexte est un bien meilleur juge.

Ce pattern, en interne dans la codebase de Hermes, s'appelle la « boucle de Ralph », d'après le pseudo-code canonique while not done: do(work); ralph = judge(work). L'extension /subgoal de v0.14.0 permet à l'utilisateur d'injecter de nouveaux critères de judge dans une boucle en cours.

/subgoal — ajouter des critères en plein vol

Tu as démarré un /goal pour refactoriser un module. Trois boucles plus tard, tu réalises que tu veux aussi que la refacto garde la complexité cyclomatique en dessous de 10 par fonction. Tu n'as pas envie d'arrêter la boucle et de tout recommencer.

/subgoal Each function must have cyclomatic complexity <= 10.

La prochaine fois que le judge tourne, il intègre cette nouvelle contrainte. Si la meilleure tentative actuelle échoue dessus, la boucle continue. Si elle passe, la boucle sort.

C'est le genre de fonctionnalité qui paraît minuscule dans une ligne de release notes — « des critères ajoutés par l'utilisateur sont superposés sur un /goal actif » — et qui devient un pilier porteur pour quiconque utilise vraiment la boucle. Les vrais objectifs s'affinent pendant que tu regardes l'agent bosser. Sans /subgoal, le seul moyen d'affiner était /stop + redéfinir + /goal à nouveau, en perdant l'état en cours.

Exemples concrets

Refacto jusqu'à ce que les tests passent

/goal Refactor src/api/users.py so the User class follows the new naming convention in src/conventions.md. Don't break any existing tests. Done when:
1. pytest exits 0
2. The User class matches the convention rules in conventions.md

Le worker tente des refactos, le judge vérifie les deux conditions. Quand les deux sont au vert, la boucle sort.

Itérer sur une UI

/goal Make the button on /pricing more prominent. Done when:
1. The button is the largest interactive element above the fold on desktop
2. It uses the primary brand color (#FF5A50)
3. Existing Lighthouse accessibility score doesn't drop

Le worker édite le CSS, le judge prend une capture via l'outil browser et vérifie. Beaucoup d'itérations possibles sans que tu aies à surveiller.

Trouver un bug

/goal Find the cause of the intermittent test failure in tests/auth/test_session.py::test_logout_clears_cookie. Done when you produce a minimal failing repro and a one-paragraph explanation.

Le judge ici vérifie que les deux parties du livrable sont là — repro et explication — pas juste l'une ou l'autre. /subgoal te laisse ajouter une contrainte du style « l'explication doit référencer le cycle request/response concerné » si le premier jet est trop flou.

Quand ne pas s'en servir

/goal est le mauvais outil pour les tâches où :

  • La condition de succès est floue. « Rends ça plus élégant » — le judge ne peut pas noter ça de façon stable, donc la boucle oscille ou tamponne au hasard. Là, repasse en tour-par-tour.
  • Tu veux voir le travail au fur et à mesure. Chaque itération tourne jusqu'à complétion avant que le judge se déclenche, donc tu n'as pas la même visibilité par tour. Si la revue à mi-flux compte, utilise tour-par-tour ou /handoff.
  • Le coût compte plus que la vitesse. Chaque itération de boucle, c'est un appel worker plus un appel judge. Pour un objectif à 10 itérations, tu paies 20 appels LLM. Ça vaut le coup pour de la refacto ; c'est du gâchis pour « comment je nomme cette variable ».
  • Tu n'as pas réfléchi aux critères de succès. Critères poubelle → boucle poubelle. /goal récompense la précision, et l'agent va exploiter toute ambiguïté.

Comment /goal se combine avec /handoff

v0.14.0 a aussi sorti /handoff, qui transfère une session vivante entre modèles sans perdre le contexte (#23395). Les deux se composent : tu peux passer un goal en cours d'un modèle rapide à un modèle de raisonnement profond quand le goal touche quelque chose que le modèle rapide ne sait pas résoudre. Le judge continue de noter les mêmes critères ; c'est juste le worker qui s'est amélioré.

Pareil avec /sessions (#20805) — tu peux interrompre un goal, aller voir une autre session, et reprendre le goal plus tard. L'état de la boucle est checkpointé.

Où ça se place dans la stack d'agent

Trois formes différentes de travail autonome, par ordre croissant de combien tu pilotes l'agent :

  1. 1.Tour-par-tour — tu pilotes, l'agent répond. Conversationnel.
  2. 2./goal — tu poses des critères, l'agent boucle jusqu'à ce qu'ils soient remplis. Autonomie bornée.
  3. 3.Programmation cron — l'agent tourne sans surveillance sur un horaire, avec livraison vers les plateformes de messagerie. Autonomie sans borne dans le temps.

/goal est celui du milieu. C'est l'extension juste pour une catégorie de tâches qui demandaient avant soit de la surveillance lourde, soit un script sur mesure. Le /subgoal de v0.14.0 rend la boucle pilotable en plein vol, et c'est ce qui la fait passer de curiosité à outil quotidien.

Pour aller plus loin

Abonne-toi aux mises à jour

Actualités communautaires sur les releases, les nouveaux skills et les intégrations de Hermes Agent. Pas de spam, désinscription à tout moment.