Déboguer Hermes Agent : logs, traces, angles morts
Guide pratique pour déboguer Hermes Agent : où sont les logs, lequel ouvrir en premier, comment lire un arbre de trace et où l'observabilité pèche encore.
Votre agent a fait un truc bizarre. Où regarder ?
Hermes Agent a deux modes d'échec, douloureux chacun à sa manière. Le premier est bruyant : une exception avec stack trace ou un crash au démarrage. Le second est silencieux : l'agent produit une réponse cohérente mais fausse, appelle le mauvais outil ou s'éteint après le résultat d'un tool. Le bruyant apparaît dans errors.log. Le silencieux est le debug difficile et il vit dans l'audit log de la session précise qui a déraillé.
Voici une carte pratique de l'emplacement des logs, du fichier qui correspond à quel symptôme et des petits outils autour qui transforment 800 lignes de JSONL en quelque chose de vraiment lisible. Elle nomme aussi les angles morts qui restent, pour que vous sachiez ce qu'Hermes ne vous dira pas aujourd'hui.
Où vivent les logs
Tout ce qu'Hermes écrit atterrit dans votre répertoire Hermes, par défaut ~/.hermes/logs/ (et <profile>/logs/ pour les profils non par défaut). Quatre fichiers comptent :
| Fichier | Niveau | Contenu |
|---|---|---|
agent.log |
INFO+ | Activité principale de l'agent, des outils et des sessions. Point d'entrée par défaut. |
errors.log |
WARNING+ | Warnings et erreurs uniquement. Triage rapide pour "quelque chose a planté". |
gateway.log |
INFO+ | Événements du gateway uniquement, cycle de vie de session par utilisateur sur Telegram/Discord/Slack. |
gui.log |
INFO+ | Dashboard, websocket et événements du TUI-gateway. |
Les quatre sont écrits par le RotatingFileHandler de Python. Quand un fichier atteint sa limite de taille, il roule vers agent.log.1, agent.log.2, jusqu'au backup_count configuré. Le fichier actif est toujours celui sans suffixe. Cela compte quand vous chassez un bug d'hier, parce qu'"hier" a peut-être déjà tourné. Récupérez aussi les numérotés, pas seulement l'actuel.
Le point d'entrée de tout ça est hermes_logging.setup_logging(). Le gateway l'appelle avec mode="gateway" au démarrage et n'attache que des handlers de fichier, jamais un handler console. Donc hermes gateway start est silencieux par conception. Si votre gateway a l'air mort, il ne l'est pas. Faites un tail sur gateway.log.
Quel log ouvrir en premier
Le symptôme choisit le fichier, pas l'inverse. Un arbre de décision rapide :
- L'agent a planté au démarrage, ou une requête renvoie 500. Ouvrez
errors.logavechermes logs errors --since 30m -f. Les stack traces atterrissent ici en premier. - L'agent a répondu, mais la réponse est fausse. Sautez
errors.log. Les tool calls à l'origine de la mauvaise réponse sont dans le transcript JSONL de cette session (voir la section suivante sur trace-tree). - Un utilisateur Telegram ou Discord dit "il est devenu muet". Ouvrez
gateway.loget filtrez sur sa session.hermes logs gateway --session abc123cible. - Le dashboard ne se met pas à jour.
gui.log. Les coupures websocket et les erreurs de sync du TUI-gateway apparaissent ici avant partout ailleurs. - Vous ne savez pas du tout ce qui se passe.
hermes logs -fsuragent.logavec un second panneau surerrors.log. La grande majorité des réponses à "qu'est-ce que fait mon agent" est à untail -fprès.
La CLI hermes logs est votre alliée. Quelques flags gagnent leur place dans une session de debug en direct :
hermes logs # 50 dernières lignes d'agent.log
hermes logs -f # suit agent.log en temps réel
hermes logs gateway -n 100 # 100 dernières lignes de gateway.log
hermes logs --level WARNING --since 1h # dernière heure, warnings et erreurs
hermes logs --session abc123 # cible un id de session
hermes logs errors --since 30m -f # suit les erreurs depuis 30 min
hermes logs list # inventaire des fichiers et tailles
Lire une session comme un arbre, pas comme un mur de JSONL
Quand une session se termine, sa trajectoire complète est écrite en JSON par ligne dans le fichier de transcript. C'est l'artefact le plus utile pour déboguer la classe de bug "cohérent mais faux", car chaque appel de modèle, chaque tool call et chaque résultat sont capturés en ordre avec leurs arguments. Et à l'état brut, c'est illisible. 800 lignes d'audit log pour une session moyennement complexe est la norme.
L'outil communautaire trace-tree (voir l'article de Mukunda Katta sur dev.to) lit ce JSONL et imprime un arbre dans le terminal. Une session devient une racine, chaque tool call est un enfant, les appels refusés apparaissent comme enfants avec leur erreur attachée. Vous l'ouvrez, vous lisez l'arbre, vous fermez. Pas de login, pas d'upload, pas de vendor lock-in. Pointez-le sur un fichier de session :
trace-tree ~/.hermes/logs/sessions/2026-07-21T09-42-11.jsonl
Pour des diagnostics plus profonds vous pouvez aussi piper le même JSONL dans jq et filtrer par nom d'outil, latence ou statut d'erreur. Les transcripts sont stables entre versions d'une façon qu'agent.log n'est pas, donc construisez vos requêtes ponctuelles contre le transcript, pas contre un grep sur le log humain.
Pour l'investigation apparentée "l'agent est muet, est-il coincé ?" sur les canaux de messagerie, notre guide de troubleshooting Telegram parcourt d'abord les symptômes côté livraison (bot token, webhook, permissions de groupe), qui se révèlent souvent être la vraie cause avant même d'avoir besoin de l'arbre de trace.
Monter le niveau de log sans fuiter de secrets
Le mode verbeux est à une flag. hermes chat --verbose (ou -v) met verbose_logging=True sur AIAgent, ce qui appelle setup_verbose_logging() et ajoute un StreamHandler console en niveau DEBUG par-dessus les handlers de fichier. Vous voyez tout ce que l'agent voit, en direct.
Le détail critique est que chaque enregistrement de log, à tous les niveaux, passe par RedactingFormatter de agent/redact.py avant d'être écrit. Le formatter reconnaît les formes connues de credential (sk-, sk-or-, sk-ant-, patterns OAuth courants et secrets de type variable d'environnement) et remplace la valeur en ligne. En pratique cela veut dire que vous pouvez monter le niveau de log en production, ou coller un agent.log expurgé dans un rapport de bug, sans fuiter votre clé OpenRouter.
Il y a un piège qui vaut la peine d'être nommé. Si vous écrivez votre propre logger ou votre propre formatter en sautant la pipeline, la redaction ne s'applique pas. Le crash au démarrage du gateway NameError: name 'RedactingFormatter' is not defined rapporté en issue #8090 est la même classe d'erreur à l'envers. Considérez le formatter comme critique, ne le contournez pas, et si vous écrivez du logging sur mesure, enveloppez-le via hermes_logging.setup_logging(), pas autour.
Les angles morts d'observabilité qui restent
Hermes est honnête sur ce qu'il ne sait pas encore faire. Deux feature requests ouvertes décrivent le plafond actuel :
- Spans structurés avec timestamps de début et de fin. Aujourd'hui la plupart des lignes de log portent un seul timestamp et certaines sorties de tool incluent un
duration_secondsad hoc. Il n'existe pas de schéma stable pourstart_ts,end_ts,duration_msetparent_idsur toute la trajectoire. C'est l'issue #6741, et elle bloque les dashboards propres de latence par outil que vous voudrez quand une session ralentira. - Attach en direct à une session gateway en cours. À la release actuelle, une fois qu'une session gateway tourne vous ne pouvez pas l'observer en temps réel depuis l'extérieur.
agent.lograttrape quand la session se termine, mais il n'y a pas de hook "regarde la session de cet utilisateur pendant qu'elle se passe". C'est l'issue #18127, et c'est le plus gros angle mort pour quiconque exploite Hermes comme service partagé.
Deux contournements comblent une partie du trou en attendant. Le premier est un tracing façon OpenTelemetry vers un backend comme SigNoz, qui vous laisse transformer l'activité Hermes en spans en aval sans émission native. Le second est Langfuse (issue #1501), que certaines équipes câblent par tour comme couche d'instrumentation manuelle. Aucun n'est officiellement first-class, mais tous deux tournent en production quelque part aujourd'hui.
Quand vous préférez juste ne pas posséder la couche de logs
Tout ce qui précède suppose que vous exécutez l'agent vous-même. Si c'est justement la partie que vous préféreriez déléguer, Hermify exécute un Hermes Agent managé pour vous sur Telegram, avec le même logging et le même audit trail disponibles sur le container sous-jacent. Vous gardez la mémoire persistante, les transcripts de session et la possibilité d'escalader un problème précis chez nous, sans avoir à garder hermes logs -f ouvert sur votre propre VPS. Si vous hésitez entre self-hosting et une configuration managée pour des raisons qui incluent la charge opérationnelle de l'observabilité, notre analyse Hermes managé versus self-hosted couvre les compromis en entier.
Lancez-vous avec Hermify et sautez complètement le travail de rotation de logs et d'observabilité. Ou gardez les logs locaux et utilisez ce guide la prochaine fois que votre agent se taira. Les deux voies sont valables, et le même audit trail est disponible sur l'une ou l'autre.
Sources
- Chapter 9: Observability and Debugging (Claude Code vs. Hermes Agent) - Ken Huang
- Put a Microscope on Hermes: Full Visibility into Agent Execution - Alibaba Cloud
- I had 800 lines of Hermes agent audit log. trace-tree turned it into a tree I could read.
- hermes-agent/hermes_logging.py source
- Issue #18127: Observability for in-flight gateway sessions
- Issue #6741: Structured session tracing with start/end timestamps
- Hermes Monitoring and Observability with OpenTelemetry - SigNoz
Lancez votre propre agent Hermes
Apportez votre clé API, connectez Telegram et obtenez un agent IA auto-améliorant opérationnel en 60 secondes.
Commencer