TL;DR : Hermes Agent prend désormais en charge la délégation non bloquante de sous-agents. Le nouvel ensemble d’outils async_delegation lance des agents en arrière-plan et renvoie immédiatement un task_id — les chats parents restent libres pendant que les enfants s’exécutent. Six outils de cycle de vie vous offrent un contrôle total : lancer, vérifier, orienter, collecter, annuler et lister. Exécutez hermes update pour activer cette fonctionnalité.
Le problème : la délégation synchrone bloquait le parent
Depuis que Hermes Agent a introduit la délégation de sous-agents, l’outil delegate_task fonctionnait de manière synchrone : l’agent parent restait bloqué dans l’appel à l’outil jusqu’à ce que tous les enfants lancés aient terminé. Pour une tâche unique et courte, cela convenait. Pour des tâches longues en parallèle — analyses de marché, refontes de codebase, recherches multi-sources — cela gelait complètement le chat parent.
Vous ne pouviez pas continuer à rédiger, orienter les exécutions de manière interactive ou suivre la progression sans attendre. Les workflows reposant sur des tâches concurrentes en arrière-plan devenaient lourds.
Ce qui a changé : async_delegation
Le 16 juin, Nous Research a publié l’ensemble d’outils async_delegation (suivi dans GitHub issue #5586). Les agents en arrière-plan s’exécutent désormais sous forme de threads dans le processus et réutilisent le mécanisme AIAgent, les identifiants et les ensembles d’outils existants. Le parent reçoit immédiatement un task_id et reste réactif.
L’API complète du cycle de vie asynchrone :
delegate_task_async— lance un agent en arrière-plan, renvoie immédiatement untask_idcheck_task— statut non bloquant avec les résultats récentssteer_task— injecte un message dans une tâche en cours d’exécutioncollect_task— bloque jusqu’à la fin, renvoie le résultat completcancel_task— arrête une tâche en courslist_tasks— liste toutes les tâches asynchrones de la session
Voici à quoi ressemble le changement en pratique :
# Avant (synchrone) : le parent était bloqué jusqu'à ce que tous les enfants aient terminé
delegate_task(tasks=[
{"goal": "Rechercher le sujet A", "toolsets": ["web"]},
{"goal": "Corriger la build", "toolsets": ["terminal", "file"]},
])
# Après (asynchrone) : le parent reste libre
t1 = delegate_task_async(goal="Rechercher le sujet A")
t2 = delegate_task_async(goal="Rechercher le sujet B")
check_task(t1["task_id"]) # statut, sans blocage
steer_task(t2["task_id"], "Utiliser uniquement des sources post-2024")
results = [collect_task(t["task_id"]) for t in (t1, t2)]
Ce qui reste inchangé
Les sous-agents restent strictement isolés — chacun possède sa propre conversation, session terminal et ensemble d’outils. Seul le résumé final entre dans la fenêtre de contexte du parent. L’héritage des identifiants et le routage des niveaux de coût via config.yaml fonctionnent de manière identique pour les chemins synchrones et asynchrones.
Limites à surveiller
Les sous-agents asynchrones sont limités à une seule session — ils s’exécutent dans le processus et ne persistent pas après un redémarrage ou un nouveau tour de chat. La persistance inter-tours est suivie séparément sous ACP #4949. De plus, les sous-agents héritent des identifiants du parent, donc examinez les règles de moindre privilège avant de déléguer des tâches sensibles.
Pour commencer
Les utilisateurs existants activent la fonctionnalité avec une seule commande :
hermes update
Ensuite, auditez config.yaml pour le routage des coûts, ajustez delegation.max_concurrent_children en fonction de vos ressources hôte, et mettez à jour les runbooks d’équipe avec les nouvelles commandes du cycle de vie des tâches. Le TUI de Hermes expose déjà une superposition /agents (alias /tasks) affichant les sous-agents en cours d’exécution et terminés.
Cette fonctionnalité transforme Hermes Agent d’un exécuteur de tâches linéaire en un véritable orchestrateur d’exécution parallèle — le genre de capacité qui distingue les simples wrappers de chat des systèmes d’exploitation pour agents.
Sources : Teknium on X, Nous Research, Hermes Agent docs, GitHub issue #5586