v0.21.1

Hermes Agent v0.21.1


Aperçu

v0.21.1 — The Consolidation Release. Publiée le 7 septembre 2026. ~5 139 commits · ~4 364 fichiers modifiés (+601 014 / −768 419) · ~632 PR fusionnées depuis v0.21.0.

Cette fenêtre n’a pas de fonctionnalité phare unique — c’est une passe de consolidation, et la plus grande histoire est invisible : le codebase a été décomposé et allégé d’environ 34 % de ses lignes de code source, sans aucun changement de comportement (#102117). Autour de ce grand ménage, le travail visible se concentre là où les utilisateurs avancés le ressentent vraiment : la délégation est devenue plus rapide et plus sûre (chaque résultat arrive dès qu’un subagent se termine, et les enfants peuvent vous rendre les processus d’arrière-plan en cours d’exécution), les serveurs MCP peuvent désormais s’autoriser par device codes sur des machines qui n’ont aucun navigateur à ouvrir, l’épinglage des providers OpenRouter se fait désormais par modèle et les sélecteurs de modèles se rafraîchissent toutes les 20 minutes, le search_files local exécute du ripgrep natif jusqu’à 6× plus vite, la compaction conserve son cache de préfixe à travers les reconstructions des sessions de codage, et cron cesse de laisser les ticks silencieux effacer la continuité tout en vous montrant enfin quand un job a été déclenché en retard.

Il s’agit d’une release corrective : les notes officielles sont brèves, et la documentation complète et organisée arrivera avec v0.22.0. Cette page couvre les parties les plus précieuses de la fenêtre.


Points forts

1. Le grand ménage : −34 % de LOC source, zéro changement de comportement

La plus grande histoire interne de la fenêtre est une simplification de tout le codebase (#102117, fusionnée le 4 septembre) : 1 063 826 → 698 363 lignes de code source (−34,4 %). Chaque god file a été décomposé — 37 fichiers de plus de 5 000 lignes sont devenus 6 ; gateway/run.py est passé de 34 847 à 5 512 lignes, cli.py de 22 426 à 4 656 ; les fonctions de plus de 300 lignes sont passées de 192 à 2 et la pire complexité cyclomatique de 1 075 à 84. Les anciens fichiers subsistent comme de minces points d’entrée publics, et le comportement est inchangé : schémas JSON d’outils, texte des system prompts, défauts de config et formats filaires sont identiques octet pour octet, vérifiés par des passes de parité sur toute la suite. Ce que vous y gagnez en tant qu’utilisateur, c’est un codebase moins coûteux à naviguer pour un agent, plus rapide à charger et plus facile à maintenir — sans aucun changement de config ni de commande de votre côté.

2. delegate_task : les résultats arrivent dès que chaque enfant se termine

Les fan-outs en arrière-plan n’attendent plus le subagent le plus lent. delegate_task retourne désormais le résultat de chaque tâche dès que cette tâche se termine, et les tâches qui partagent une chaîne group optionnelle par tâche sont retournées ensemble, en un seul message (#104299) :

{
  "tasks": [
    { "goal": "check api latency", "group": "bench" },
    { "goal": "check db latency",  "group": "bench" },
    { "goal": "scan the changelog" }
  ]
}

Les deux tâches bench sont rapportées dans un message groupé ; le scan du changelog atterrit tout seul dès qu’il se termine — fini d’attendre des heures qu’un enfant coincé laisse voir les autres résultats. Les tâches non groupées occupent chacune leur propre unité, mais l’appel entier compte toujours pour un seul slot contre delegation.max_concurrent_children.

3. Les enfants rendent les processus en cours d’exécution au parent

Un subagent peut désormais vous transférer un processus d’arrière-plan de longue durée avant de se terminer : process_manage(action="handoff", session_id=<id>, data="<purpose>") fait basculer la propriété vers le parent, et l’avis de fin atterrit dans votre chat, avec le purpose attaché (#105125). Tout ce qu’un enfant laisse derrière lui est explicitement rapporté comme terminé dans l’avis de délégation du parent, au lieu d’être tué en silence, et l’enfant est prévenu d’emblée que son notify=true n’est pas une promesse — fini les orchestrateurs qui attendent des heures une complétion qui ne peut jamais arriver.

4. Connexions MCP sans navigateur : les device codes

Les serveurs MCP qui supportent la RFC 8628 peuvent désormais s’autoriser depuis un terminal, sans aucun listener de callback navigateur (#104891) — le flux de travail qui vous forçait à vous installer sur une machine dotée d’un navigateur fonctionne désormais sur n’importe quel hôte headless :

hermes mcp login <server> --flow device

Hermes découvre l’endpoint device annoncé par le serveur, imprime l’URI de vérification et le code utilisateur, puis interroge jusqu’à ce que vous approuviez depuis n’importe quel appareil. oauth.flow: device dans votre config de serveur MCP fait du device flow le défaut pour la connexion et la ré-authentification (le PKCE navigateur reste le défaut global ; --flow browser surcharge la config pour une seule connexion). Les octrois refusés ou expirés ne remplacent jamais les identifiants existants.

5. Épingles OpenRouter par modèle + sélecteurs toujours à jour

provider_routing.models.<model-id> épingle désormais un ensemble de providers OpenRouter différent par modèle, si bien que les règles de routage ne peuvent plus envoyer en silence un modèle vers un provider que vous n’avez pas choisi (#104159) :

provider_routing:
  sort: price
  models:
    "openai/gpt-6-astra":         { only: [openai] }
    "anthropic/claude-fable-5.1": { only: [anthropic] }

L’entrée par modèle est appliquée au point de passage unique que tous les chemins de requête empruntent déjà : CLI, gateway, desktop, cron, /model et les enfants délégués l’honorent donc tous. Pendant ce temps, le sélecteur /model a cessé de périmer : les catalogues se rafraîchissent désormais toutes les 20 minutes (contre un TTL d’une heure), et une boucle d’arrière-plan du gateway les garde au chaud même quand personne n’ouvre le sélecteur (#101319). Le provider Meta Model API traite désormais sa réponse live /v1/models comme le catalogue faisant autorité, en excluant les préfixes non-chat comme muse-image-* et muse-voice-* (#101503).

6. Fichiers locaux et recherches nettement plus rapides

search_files sur un hôte POSIX local exécute désormais ripgrep en tant que sous-processus direct au lieu de passer par deux spawns bash par appel (#104502) : les recherches de contenu passent de ~85 ms à ~15 ms, les recherches par nom de fichier de ~73 ms à ~12 ms (5 à 6× de latence d’outil en moins, résultats identiques ; HERMES_NATIVE_FILE_READ=0 restaure le chemin shell). Deux victoires compagnes maintiennent la facture de tokens basse dans les longues sessions de codage : les reconstructions de compaction épinglent désormais l’instantané du workspace de codage par session, au lieu de re-sonder git status à chaque fois, ce qui préserve le cache de préfixe du prompt à travers les frontières de compaction (#104455) ; et les subagents terminés libèrent leurs transcripts du heap du parent, le contenu des subagents étant exclu de l’index FTS trigramme (schema v30) — une exécution de 1 320 enfants laissait auparavant un heap parent de 1,9 Go et 1 Go de shadow tables derrière elle (#102032).

Améliorations

  • Démarrage : hermes serve — la commande que le desktop lance à chaque démarrage à froid — transite par un parseur léger autonome et saute la construction de l’arbre argparse d’environ 40 sous-commandes (repli sur le parseur complet pour l’aide, les flags inconnus et le routage conteneur) (#101265).
  • Visibilité cron : hermes cron list imprime désormais une ligne Dispatch: par job, et hermes cron status ajoute un encart pour les jobs en retard, si bien qu’un rattrapage après échec de déclenchement affiche ⚠ catch-up after missed fire au lieu de se faire passer pour un succès à l’heure (#100445).
  • Config de délégation : un enfant délégué épinglé à un provider/modèle ne se reroute plus en silence par la chaîne de fallback du parent en cas d’échec ; delegation.fallback_providers donne aux enfants leur propre chaîne ([] désactive, absent hérite quand rien n’est épinglé) (#105347). Les enfants n’héritent plus non plus du palier prompt cache d’une heure du parent — les subagents écrivent au palier de 5 minutes qu’ils utilisent réellement, évitant un prix d’écriture en cache 2× pour une rétention qu’ils ne collectent jamais (#104168).
  • Hygiène des tokens : write_file signale désormais une réécriture de fichier entier qui renvoie en grande partie ce qui est déjà sur le disque (≥20 000 caractères, ≥80 % de lignes inchangées), orientant l’agent vers patch pour les petites éditions — 661 écritures de ce type (~24,9 M de caractères, ≈155 $ de tokens de sortie) ont été attrapées dans une seule passe de refactor (#103551).
  • Desktop : les horodatages des transcripts sont de nouveau lisibles dans les deux thèmes, et un nouveau curseur Message Bubble (Settings → Appearance) contrôle l’opacité de vos bulles, du plein au contour seul (#103146).

Corrections

  • Les règles approvals.deny sont désormais appliquées à l’intérieur des sandboxes Docker/cloud isolées — elles sautaient auparavant le chemin rapide conteneur, si bien qu’une liste de refus pouvait être contournée avec un shell sandboxé même sous --yolo ou approvals.mode: off ; hermes approvals test reflète l’ordre corrigé (#103649).
  • Cron : les ticks silencieux (monitor ou script-gated) ne remplacent plus un contexte de continuité utile par un stub vide — la sélection de sortie parcourt les fichiers du plus récent au plus ancien et saute les documents vides ou silencieux, tout en gardant les documents d’erreur éligibles à la récupération (#104877). Les stores d’incidents et de blocs-notes cron survivent aussi aux mises à jour qui laissent un module d’exécution plus ancien en cache (#104939).

Mise à jour

hermes update

Après la mise à jour, lancez hermes doctor pour vérifier l’installation et redémarrez le gateway (hermes gateway) pour que les changements de plateforme prennent effet. La refonte structurelle conserve chaque point d’entrée public, si bien que les plugins tiers et les configs sont repris sans changement. Pour voir ce que la prochaine mise à jour touchera avant de la lancer : hermes update --plan.

← Hermes Agent Changelog