Conecte Webhooks do Hermes: Deixe Seus Sistemas de Negócio Enviarem Alertas para Telegram, Discord e Slack


A maioria dos sistemas de negócio acaba precisando da mesma automação: quando o status de um pedido muda, um pagamento é aprovado, um monitor dispara ou um pipeline de CI termina, publicar uma mensagem no canal da equipe. A primeira versão mais rápida costuma ser um script que faz polling em um banco de dados ou API e depois envia a mensagem para o Telegram, Discord, Slack ou outra plataforma de chat.

Polling funciona, mas tem custos reais de longo prazo:

  • Latência e cota de API. Escanear a cada minuto significa que a maioria das requisições não retorna nada; passar para polling em nível de segundos multiplica a pressão sobre a API e os custos.
  • Acoplamento. O sistema de negócio acaba com templates de mensagem e tokens de plataformas de chat hard-coded. Trocar de canal ou grupo exige mudança de código.
  • Extensibilidade. O mesmo alerta pode precisar ir para o Telegram, o Slack, ou ser resumido por uma IA primeiro. Scripts de polling crescem em complexidade rapidamente.

O Hermes Agent vem com uma plataforma de webhooks — um receptor de eventos HTTP. Seu sistema de negócio faz um POST de um evento, o Hermes valida a assinatura, renderiza um template e envia a mensagem para a plataforma de chat que você configurou. Se o evento for uma notificação pura que não precisa de raciocínio de IA, você pode ativar o modo Direct Delivery: sem chamada de LLM, sem loop de agente, entrega em menos de um segundo e custo zero de tokens.

Este post é um guia prático para conectar sistemas de negócio aos webhooks do Hermes: habilitar a plataforma, configurar rotas, três cenários reais completos e endurecimento de segurança.

Dois modos: processamento por agente vs. Direct Delivery

Os webhooks do Hermes suportam dois caminhos de entrega. Escolher o certo importa.

Modo Chama LLM? Melhor para Latência Custo
Processamento por agente Sim Eventos que precisam de compreensão, resumo ou uma decisão antes de responder/encaminhar Segundos Custo de tokens
Direct Delivery Não Notificações puras: pedidos, pagamentos, alertas, status de CI Menos de um segundo Custo zero de LLM

O Direct Delivery é o foco aqui. O fluxo é simples:

  1. O sistema de negócio assina e faz um POST de um payload JSON para https://your-server:8644/webhooks/<route-name>.
  2. O Hermes valida a assinatura HMAC para confirmar que o remetente é confiável.
  3. Um template renderiza os campos do JSON em uma mensagem legível.
  4. A mensagem é entregue diretamente ao Telegram, Discord, Slack, Feishu, etc., e o Hermes retorna 200 OK.

Nenhum LLM está envolvido, então velocidade, custo e confiabilidade ficam mais próximos de um gateway de mensagens tradicional — mas a configuração e a extensibilidade continuam tão flexíveis quanto o resto do Hermes.

Passo 1: Habilite a plataforma de webhooks

Você pode habilitar webhooks via variáveis de ambiente para um início rápido ou via config.yaml para implantações de longo prazo.

Variáveis de ambiente (mais rápido)

Adicione estas linhas ao ~/.hermes/.env:

WEBHOOK_ENABLED=true
WEBHOOK_PORT=8644        # default
WEBHOOK_SECRET=your-global-secret

Reinicie o gateway:

hermes gateway restart

Confirme que o servidor está escutando:

curl http://localhost:8644/health

Uma resposta {"status": "ok", "platform": "webhook"} significa que está no ar.

Arquivo de configuração (recomendado para produção)

Declare o bloco platforms.webhook no ~/.hermes/config.yaml:

platforms:
  webhook:
    enabled: true
    extra:
      port: 8644
      secret: "your-global-secret"

Após reiniciar o gateway, o Hermes escuta na porta 8644. Se o servidor estiver na internet pública, certifique-se de que o firewall permite essa porta. Se estiver atrás de NAT ou sem IP público, exponha-o com um Cloudflare Tunnel ou ngrok.

Passo 2: Configure uma rota de notificação de negócio

As rotas ficam em platforms.webhook.extra.routes. Cada rota tem um nome, filtro de eventos, secret, template de mensagem e destino de entrega. Abaixo está um exemplo completo de notificação de pedidos de e-commerce que envia novos pedidos para o Telegram.

platforms:
  webhook:
    enabled: true
    extra:
      port: 8644
      secret: "global-fallback-secret"
      routes:
        order-notify:
          events: ["order.created"]
          secret: "shopify-webhook-secret"
          prompt: |
            🛒 New order #{order.id}
            Amount: {order.total_price} {order.currency}
            Customer: {order.customer.email}
            Item: {order.line_items[0].title}
          deliver: "telegram"
          deliver_only: true
          deliver_extra:
            chat_id: "-1001234567890"

Pontos-chave:

  • events é opcional. Se o seu sistema de negócio envia um tipo de evento via X-Webhook-Event ou event_type, você pode restringir a rota a order.created.
  • secret é usado para validação da assinatura HMAC. Se a rota não tiver secret, ela recai no secret global.
  • deliver_only: true ativa o Direct Delivery e pula o LLM.
  • prompt é um template. Use notação de ponto como {order.total_price} para acessar campos do JSON. {__raw__} despeja o payload inteiro.
  • deliver_extra.chat_id aponta para um grupo específico. Se omitido, o Hermes entrega para o canal doméstico configurado da plataforma (o que exige que essa plataforma esteja habilitada e conectada).

Passo 3: Envie eventos do seu sistema de negócio

Seu sistema de negócio faz um POST para a URL correta. Para o exemplo acima:

POST https://your-server:8644/webhooks/order-notify

Use a assinatura Generic V2: concatene timestamp.body, calcule o HMAC-SHA256 e envie-o no header X-Webhook-Signature-V2 junto com X-Webhook-Timestamp. A janela de timestamp é de ±300 segundos, o que bloqueia ataques de replay.

import hmac
import hashlib
import time
import json
import requests

secret = b"shopify-webhook-secret"
body = json.dumps({
    "event_type": "order.created",
    "order": {
        "id": 10086,
        "total_price": "199.00",
        "currency": "USD",
        "customer": {"email": "[email protected]"},
        "line_items": [{"title": "Hermes sticker pack"}]
    }
}).encode()

timestamp = str(int(time.time()))
signature = hmac.new(secret, f"{timestamp}.{body.decode()}".encode(), hashlib.sha256).hexdigest()

requests.post(
    "https://your-server:8644/webhooks/order-notify",
    data=body,
    headers={
        "Content-Type": "application/json",
        "X-Webhook-Signature-V2": signature,
        "X-Webhook-Timestamp": timestamp,
    }
)

As assinaturas do GitHub e do GitLab também são detectadas automaticamente. Para sistemas de negócio customizados, prefira a Generic V2.

Passo 4: Teste a rota

Você não precisa esperar o sistema de negócio entrar em produção. Teste localmente primeiro:

hermes webhook test order-notify \
  --payload '{"event_type":"order.created","order":{"id":10086,"total_price":"199.00","currency":"USD","customer":{"email":"[email protected]"},"line_items":[{"title":"Hermes sticker pack"}]}}'

hermes webhook test simula um POST para que você possa verificar a renderização do template e a entrega. Se a mensagem não chegar, verifique o gateway.log ou execute hermes gateway run em primeiro plano para ver se a assinatura falhou, o evento foi filtrado ou o destino de entrega não está conectado.

Cenário 1: Notificações de pedidos de e-commerce → Telegram

O exemplo order-notify acima já está completo. Alguns detalhes que valem destaque:

  • Os valores de chat_id de grupos do Telegram costumam ser negativos e começam com -100.
  • Para apontar para um tópico específico do fórum, adicione message_thread_id: "42" em deliver_extra.
  • {order.line_items[0].title} mostra apenas o primeiro item. Para listar tudo, pré-processe o payload no sistema de negócio ou use o modo agente com {__raw__} e deixe o LLM resumir.

Cenário 2: Pagamento aprovado → Discord

Sistemas de pagamento como o Stripe já emitem webhooks. Mapeie o evento de sucesso do Stripe para uma mensagem no Discord:

routes:
  payment-success:
    events: ["payment_intent.succeeded"]
    secret: "stripe-webhook-secret"
    prompt: |
      💰 Payment received: {amount} {currency}
      Order: {metadata.order_id}
      Customer: {receipt_email}
    deliver: "discord"
    deliver_only: true
    deliver_extra:
      chat_id: "123456789012345678"

O Stripe envia type em vez de event_type. Se o Hermes não reconhecer o header de evento, envolva o payload no seu sistema de negócio ou deixe events vazio e use filters:

routes:
  payment-success:
    secret: "stripe-webhook-secret"
    filters:
      - field: "type"
        equals: "payment_intent.succeeded"
    prompt: "..."
    deliver: "discord"
    deliver_only: true

Cenário 3: Alertas de monitoramento → Slack

O Grafana, o Datadog ou qualquer monitor customizado podem fazer um POST de alertas. Envie apenas alertas críticos para o Slack:

routes:
  critical-alert:
    events: ["alert"]
    secret: "monitoring-webhook-secret"
    filters:
      - field: "severity"
        equals: "critical"
    prompt: |
      🚨 Critical alert
      Service: {service}
      Metric: {metric}
      Current value: {current_value}
      Threshold: {threshold}
    deliver: "slack"
    deliver_only: true
    deliver_extra:
      chat_id: "your-slack-channel-id"

O Slack deve estar habilitado e conectado no gateway. Se você usa o Slack apenas para notificações de webhook, não precisa dele como sua plataforma de chat principal; basta configurar platforms.slack com um canal doméstico ou especificar o chat_id em deliver_extra.

Avançado: filtre e transforme payloads com scripts

Se o JSON do sistema de negócio for bagunçado ou você quiser notificar apenas sob condições específicas, escreva um script de pré-processamento. Os scripts devem ficar em ~/.hermes/scripts/; caminhos relativos são resolvidos ali.

# ~/.hermes/scripts/alert-filter.py
import json
import sys

payload = json.load(sys.stdin)
if payload.get("severity") != "critical":
    print("[SILENT]")
    raise SystemExit(0)

payload["body"] = f"{payload['service']} critical: {payload['metric']}"
print(json.dumps(payload))

Referencie-o na rota:

routes:
  critical-alert:
    events: ["alert"]
    secret: "monitoring-webhook-secret"
    script: "alert-filter.py"
    prompt: "{body}"
    deliver: "slack"
    deliver_only: true

O stdout em JSON substitui o payload; o stdout em texto puro é injetado como script_output; saída vazia ou [SILENT] faz o Hermes ignorar o webhook.

Segurança: não confie apenas no HMAC

O HMAC prova que o remetente é confiável, não que o conteúdo do payload é seguro. Títulos de PRs, corpos de issues, notas de pedidos e mensagens de alerta são escritos por terceiros e podem conter instruções injetadas. Então:

  1. Isole o runtime. Se o webhook estiver exposto à internet, execute o gateway com um backend de terminal Docker ou SSH; não exponha o host diretamente a eventos.
  2. Direct Delivery é inerentemente mais seguro. Como ele pula o LLM, não há risco de prompt injection que possa disparar ações do agente.
  3. Escopelize o conjunto de ferramentas. Se uma rota precisar entrar em modo agente, desabilite ferramentas perigosas como terminal e file para essa rota.
  4. Mantenha as aprovações ativas. Se o agente acionado por webhook precisar executar comandos, deixe as aprovações habilitadas para que instruções injetadas não possam ser executadas sem supervisão.
  5. Faça templates estreitos. Evite abusar de {__raw__}; inclua apenas os campos de que você precisa no prompt.

O Hermes também vem com salvaguardas: 30 requisições por minuto por rota por padrão, um limite de tamanho de corpo de 1 MB e um cache de idempotência de 1 hora. Esses padrões são suficientes para a maioria das notificações, mas você pode ajustá-los em extra:

extra:
  rate_limit: 60
  max_body_bytes: 2097152

Checklist de solução de problemas

Sintoma Causa provável O que verificar
O POST do sistema de negócio falha Porta/firewall não abertos curl http://your-server:8644/health
401 Unauthorized Assinatura incompatível Verifique o secret e o algoritmo HMAC; leia os logs do gateway
200 OK mas sem mensagem Tipo de evento incompatível Verifique a lista de events e o campo event_type
Mensagens duplicadas Retries + falha de idempotência Garanta que o remetente envie X-Request-ID ou X-GitHub-Delivery
Variáveis do template não expandidas Nomes de campo errados Itere com hermes webhook test

Assinaturas dinâmicas vs. rotas no arquivo de configuração

Além das rotas estáticas no config.yaml, você pode criar assinaturas dinamicamente via CLI:

hermes webhook subscribe order-notify \
  --events "order.created" \
  --prompt "New order #{order.id}, amount {order.total_price} {order.currency}" \
  --deliver telegram \
  --deliver-chat-id "-1001234567890" \
  --deliver-only \
  --description "E-commerce order notifications"

As assinaturas dinâmicas são armazenadas em ~/.hermes/webhook_subscriptions.json e recarregadas a quente pelo gateway — sem necessidade de reinício. Rotas estáticas com o mesmo nome têm precedência. Para a referência completa de comandos, veja nossa página de comando hermes webhook.

Resumo

A plataforma de webhooks do Hermes não é um chatbot; é um roteador de mensagens orientado a eventos. Para sistemas de negócio, seu principal valor é:

  • Transformar polling em push, economizando cota de API e cortando latência.
  • Centralizar templates de mensagem e destinos de entrega no Hermes, de modo que mudar de plataforma de chat ou grupo não exija um deploy do sistema de negócio.
  • O modo Direct Delivery para notificações com custo zero de tokens e entrega em menos de um segundo.

Se você já roda o Hermes para tarefas diárias, adicionar um endpoint de webhook é quase de graça: o mesmo gateway já está em execução, ele só passa a escutar mais uma porta. Seus sistemas de negócio podem começar a falar proativamente, e você decide o que eles dizem e onde dizem.

Novo no Hermes? Comece com o guia de instalação. Para a referência completa de comandos de webhook, veja a página de comando hermes webhook. Se você se interessa por automação orientada a eventos, leia também nosso guia de cron apenas com scripts e o explicador do modo yolo.