O que o seu agent fez a noite passada? Ligando o Hermes ao OpenTelemetry

Você acorda, abre o notebook e descobre que aquela tarefa de “só ajustar a config” que ficou rodando a noite toda custou alguns dólares a mais que o de costume. O /status te diz o total de tokens e nada além disso. O que você quer saber de verdade é qual chamada de modelo foi lenta, qual tool tentou três vezes e qual aprovação ficou dois minutos parada esperando um clique. O Hermes não entrega essa linha do tempo por chamada, mas o plugin da comunidade hermes-otel cobre exatamente essa lacuna: ele liga o Hermes ao OpenTelemetry e transforma um turn em um trace que você abre camada por camada.
As duas superfícies de observabilidade nativas não cobrem “esta chamada específica”
O Hermes já vem com duas. A primeira é o gateway monitoring (monitoring.export.otlp), que acompanha a saúde do gateway e do cron e é sem conteúdo por design — sem prompts, sem chamadas de tool, sem tokens. A segunda é o plugin Langfuse embutido, que registra traces por execução, mas só envia para o Langfuse.
O hermes-otel é a terceira, uma superfície no nível de execução, e roda em paralelo às outras duas. Ele se pendura nos lifecycle hooks do host e instala o próprio TracerProvider, então nunca mexe nos objetos privados de provider que o exportador do core monta. Os dois conjuntos de dados não se sobrescrevem.
Instalação: um comando, um restart do gateway
O plugin está no catálogo curado (nível community, fixado na 1.18.2):
hermes plugins install hermes_otel
hermes plugins enable hermes_otel
O Hermes 0.21 e mais recentes instala as três dependências opentelemetry-* do plugin no próprio virtualenv e as reaplica a cada hermes update. Depois disso, reinicie qualquer gateway que esteja rodando.
Em versões anteriores à 0.21, ou se você instalou com --no-deps? Adicione as dependências na mão:
<hermes venv>/bin/pip install -r ~/.hermes/plugins/hermes_otel/requirements.txt
Como um turn aparece quando você o expande
O plugin mapeia os eventos do host em spans, mais ou menos assim:
agent / cron <- o span raiz do turn inteiro
├── skill.{name} <- uma skill carregada, aberta até o turn terminar
└── llm.{model} <- um run_conversation
├── api.{model} <- um round-trip HTTP, com tokens e finish reason
│ ├── tool.{name} <- cada chamada de tool: args, resultado, desfecho
│ └── approval.{pattern} <- esperando um humano ou o smart guardian
└── subagent.{role} <- delegate_task, o trace do filho aninha aqui
Os spans api.* carregam o atributo hermes.query_source, que diz se a chamada veio do próprio loop do agent (main), de um filho delegado (subagent) ou foi feita em nome do agent (auxiliary — títulos, compressão, agregação de Mixture-of-Agents), com hermes.auxiliary.task nomeando o trabalho. Spans de tool carregam hermes.tool.outcome: completed, error, timeout, blocked ou cancelled. Os atributos saem tanto nas convenções OpenInference quanto nas OTel GenAI, então Phoenix e Langfuse funcionam sem mapeamento customizado.
Configure com um arquivo YAML — ou uma variável de ambiente
Para um único backend você não precisa de arquivo de config nenhum:
export OTEL_PHOENIX_ENDPOINT=http://localhost:6006/v1/traces
Para vários, crie ~/.hermes/hermes_otel.yaml:
project_name: hermes-agent
backends:
- type: phoenix
endpoint: http://localhost:6006/v1/traces # apenas traces
- type: lgtm
endpoint: http://localhost:4318/v1/traces # traces + métricas + logs
metrics: true
- type: honeycomb
api_key: ${HONEYCOMB_API_KEY} # ${VAR} é expandido no carregamento
capture_logs: true
Os backends são alimentados em paralelo, cada um com a própria fila de exportação. O diretório docker-compose/ do repositório traz uma stack pronta para cada backend self-hostable, então subir Phoenix ou Jaeger localmente é o caminho mais curto até o primeiro trace.
Privacidade: conteúdo completo por padrão, então mude para preview
Leia esta parte primeiro. O padrão content_capture: full envia o prompt e a resposta completos de cada chamada de modelo, além dos argumentos e da saída das tools cortados em 1.200 caracteres, para o backend que você configurou.
| Valor | O que sai do processo |
|---|---|
full |
Prompt e resposta completos, conteúdo das tools cortado em 1.200 caracteres |
preview |
Apenas previews cortados |
off |
Nenhum conteúdo, só a estrutura |
Sem backend configurado, o plugin mantém um store SQLite local em $HERMES_HOME para o dashboard e não envia nada. Com vários profiles, lembre que cada profile tem instalação, configurações e telemetria próprias, e um gateway multiplexado traça cada profile que ele atende sob o próprio nome.
Pergunte pelo chat, sem tocar em nenhum backend
O plugin traz uma skill, hermes_otel:observability, com uma ferramenta de consulta no terminal. Depois de instalado, você pode simplesmente perguntar “por que meu último turn foi lento?” ou “quanto custou esta session?”, e ela lê o store local ao vivo — sem backend:
python3 ~/.hermes/plugins/hermes_otel/skills/observability/scripts/otel.py trace last
A saída é uma cascata legível com duração por span, tokens, cache hits e finish reason. Os subcomandos incluem status, traces, span, sessions, stats, metrics, logs e um sql somente leitura, todos com --json, --since e --source.
Quando vale a pena deixar de lado
- Se você só quer saber se o gateway está vivo, o gateway monitoring nativo é mais leve e sem conteúdo por design.
- Se o Langfuse é seu único backend, o plugin Langfuse embutido já resolve.
- Numa máquina pequena rodando muitas tarefas minúsculas, spans por turn custam caro. Comece com
previewmais amostragem por uma semana antes de tornar permanente.
Dois limites honestos: ligar spans de servidores MCP ao trace do agent está implementado do lado do plugin, mas ainda depende de suporte no host, e o plugin falha aberto — os exportadores rodam em threads próprias, então ele não é um log de auditoria. Se você precisa de evidência que sobreviva a um crash, mantenha o store local ou exporte para um backend que você controla.
Se você ainda está escolhendo plugins, comece por como o catálogo de plugins funciona — o hermes plugins search mostra em qual commit um plugin está fixado. Para navegar esses spans num workspace de browser, o Hermes Workspace combina bem, e os detalhes dos comandos estão na referência de hermes plugins.