Fini les arrêts en plein milieu : Hermes max_turns est désormais illimité par défaut


Vous connaissez la sensation : vous demandez à Hermes un vrai gros chantier — refactoriser tout le dépôt, traiter des milliers de fichiers par lots, construire un pipeline de données de bout en bout — et il travaille, il travaille… puis s’arrête soudainement. Pas d’erreur. Pas de question. Juste… fini. La moitié de la tâche est terminée, le reste est resté en plan.

Ce n’était pas de la magie, c’était une limite par défaut que Hermes appliquait : au cours d’un seul tour, l’agent pouvait appeler les outils 500 fois au maximum. Cinq cents, ça paraît beaucoup, mais toute tâche réelle — chercher, lire du code, modifier des fichiers, lancer les tests, corriger les bugs, relancer les tests — épuise vite ce quota. Pire encore, l’arrêt était silencieux. On ne se rendait compte du travail inachevé qu’en remontant la conversation.

Cette limite par défaut n’existe plus : depuis la branche main (post-v0.20.4), agent.max_turns est illimité par défaut. Cet article explique ce qui a changé, pourquoi, et comment fixer un plafond quand on en veut vraiment un.

D’abord : ce qu’est réellement max_turns

max_turns (aussi appelé max iterations) limite le nombre de fois où l’agent peut appeler des outils au cours d’un même tour — pas le nombre de tours possibles. Voyez les choses ainsi : vous envoyez un message, Hermes se met au travail, et chaque fichier lu, chaque commande exécutée, chaque appel API compte pour une itération. max_turns: 500 signifiait : dans ce tour, il peut faire au plus 500 unités de travail, puis il doit s’arrêter et vous rendre la main.

Dans les anciennes versions, la valeur par défaut était 500. Amplement suffisant pour le quotidien, mais pour des tâches du type « lire le code → modifier des dizaines de fichiers → lancer les tests → corriger → relancer », 500 était un plafond invisible. La tâche atteignait la limite en plein milieu et les étapes restantes devaient attendre un « continue » manuel.

Ça pouvait même être pire : si vous écriviez max_turns: none dans votre config pour exprimer « pas de limite », l’ancien code plantait avec une TypeError (issue #82813) — ou ignorait silencieusement la valeur. Parfois, l’échec n’était pas propre : il pouvait emporter avec lui les jobs cron et le gateway.

La nouvelle valeur par défaut : illimité, sauf si vous optez pour un plafond

Ce changement (PR #90708) inverse complètement le comportement par défaut :

Réglage Avant Maintenant
Non défini (défaut) plafonné à 500 illimité
max_turns: none plantage TypeError illimité
max_turns: null / unlimited / inf / infinity / 0 / -1 plantage ou ignoré illimité
max_turns: 200 plafonné à 200 plafonné à 200 (inchangé)

Autrement dit : par défaut, une tâche va désormais jusqu’au bout — plus d’arrêt silencieux. Toutes les orthographes de « illimité » (none, null, unlimited, infinite, infinity, inf, , 0, -1, insensibles à la casse et tolérantes aux espaces) sont maintenant des citoyens de première classe, normalisées par une seule fonction resolve_turn_limit(). Écrivez celle que vous voulez — même résultat, et plus aucun plantage.

Et si vous voulez vraiment un plafond pour certaines tâches, un entier positif fonctionne toujours exactement comme avant.

Comment fixer une limite quand on en veut une

L’illimité est la valeur par défaut, mais elle ne convient pas à tous les scénarios — prenons un job cron qui tourne toutes les heures et auquel vous voulez imposer un volume de travail borné pour qu’il ne puisse pas dépenser une fortune par accident. Il y a trois façons de fixer un plafond (par ordre croissant de priorité) :

1. Le fichier de config (config.yaml)

agent:
  max_turns: 200   # au plus 200 appels d'outils par tour

2. Le CLI

hermes config set agent.max_turns 200

3. La variable d’environnement

export HERMES_MAX_ITERATIONS=200
hermes chat

Les trois passent par le même analyseur resolve_turn_limit(), le comportement est donc cohérent quel que soit l’endroit où vous définissez la valeur.

À ne pas confondre : goals.max_turns reste à 20

Une chose n’a pas changé : goals.max_turns garde sa valeur par défaut de 20.

agent.max_turns régit les tours de conversation ordinaires ; goals.max_turns régit le mode goal (vous confiez à Hermes un objectif de long terme et le laissez travailler en autonomie jusqu’à ce que ce soit fait) — plus précisément, le nombre de cycles d’auto-continuation autorisés. Le mode goal a sa propre protection budgétaire : il marque une pause après 20 continuations et vous demande de faire /goal resume ou de clarifier, pour qu’un objectif flou ne puisse pas faire fondre votre budget indéfiniment. La PR a délibérément laissé ce champ tranquille — chacun des deux réglages fait son propre travail.

En résumé : vous voulez que les longues tâches cessent d’être coupées en plein vol ? Utilisez la valeur par défaut illimitée (rien à configurer). Vous voulez un frein pour la chasse aux objectifs en autonomie ? Ajustez goals.max_turns.

Bon à savoir maintenant que c’est illimité

Avec des tours illimités, deux points méritent votre attention :

  • Soyez conscient des coûts : la tâche va jusqu’au bout, ce qui signifie que le modèle API est appelé en continu. Si le budget vous importe, ne comptez pas sur max_turns comme frein — utilisez des outils plus précis comme agent.run_budget_seconds (un budget en temps réel qui vous prévient à 80 % du temps écoulé) ou le timeout d’inactivité du gateway (qui ne se déclenche que lorsque l’agent est complètement inactif depuis un moment). Ce sont des « freins élégants » — bien plus agréables qu’un arrêt en pleine tâche.
  • cron et le gateway en profitent aussi : comme le planificateur cron et la config du gateway partagent désormais le même résolveur, l’ancien plantage quand on écrivait none dans la config cron est corrigé. Les longues tâches cron vont désormais jusqu’au bout en une seule passe.

Résumé

Le passage de agent.max_turns de « 500 par défaut » à « illimité par défaut » est un correctif pragmatique pour l’expérience des longues tâches : laissez finir ce qui doit finir ; laissez fixer des limites à qui en veut. Le changement est actuellement sur la branche main (fusionné après v0.20.4) — dès que la prochaine version officielle sortira, un simple hermes update vous y mènera.

Vous voulez approfondir la façon dont Hermes gère les tours et le contexte ? Découvrez notre plongée en profondeur sur la gestion des erreurs et la récupération, ou le guide de config pour les longues tâches avec des réglages concrets qui évitent aux tâches de rester bloquées.