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 preview mais 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.