Plugin pro Hermes Agent que SUBSTITUI o WebhookAdapter built-in pra
suportar session_chat_id estável derivado de campo no payload.
Por que existe
--------------
O WebhookAdapter built-in monta a chave de sessão como:
session_chat_id = f"webhook:{route}:{delivery_id}"
delivery_id é único por POST → cada msg cria sessão nova no Hermes. OK pra
webhooks one-shot, ERRADO pra integração de chat onde múltiplas mensagens
da mesma conversa precisam compartilhar memória de sessão.
Como funciona
-------------
Quando o caller (Captain) inclui `conversation_id` ou `hermes_session_id`
no payload, o plugin reescreve chat_id pra:
session_chat_id = f"webhook:{route}:session:{conversation_id}"
Mesma conversation_id em múltiplas POSTs → mesma sessão Hermes →
contexto e memória preservados. Sem o campo, fallback ao comportamento
default (session nova por POST). 100% backward-compatible.
Implementação
-------------
- kind: platform — registra com name="webhook" pra substituir built-in
(Hermes prioriza platform_registry sobre código built-in em
gateway/run.py:_create_adapter)
- Herda WebhookAdapter — só override `handle_message` (rewrite chat_id)
e `connect` (recupera gateway_runner via _gateway_runner_ref pq o
plugin path não seta isso explicitamente)
- Outros adapters (HMAC, rate limit, idempotency, parsing, deliver
dispatch) — herdados sem cópia
Validado end-to-end na VPS (profile valentina):
- POST com conversation_id=99999 (msg 1) → session:99999 criada
- POST com conversation_id=99999 (msg 2) → MESMA session reutilizada
- Hermes responde via Codex em ~10s (2 turnos cumulativos)
- http_callback faz POST de volta no Captain (HTTP 200)
- Logs mostram: [captain-webhook] Stable session: ... -> session:99999
Combinado com captain-http-callback, completa o ciclo Captain ↔ Hermes:
Captain manda webhook com conversation_id → Hermes processa em sessão
estável → http_callback POSTa resposta de volta → Captain envia ao
WhatsApp.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adiciona plugin externo pro Hermes Agent que entrega a resposta do agente
como POST HTTP a uma URL configurável — em vez de empurrar pra plataforma
de mensageria (Telegram, Slack, etc) como o Hermes faz por default.
Por quê:
O Hermes nativamente entrega respostas em plataformas conhecidas. Quando
integramos o Hermes como cérebro de outro backend (Captain / Chatwoot),
precisamos da resposta de volta via HTTP pro backend continuar o fluxo
(mandar pro cliente WhatsApp, atualizar conversa, etc). O Hermes não tem
deliver type "http_callback" built-in, então criamos via API de plugin
oficial deles (kind: platform).
Arquivos:
- plugin.yaml — manifest (kind=platform)
- __init__.py — entrypoint (re-exporta register)
- adapter.py — HttpCallbackAdapter implementando BasePlatformAdapter
- README.md — uso, formato do POST, signing HMAC opcional
Como funciona:
1. Backend (Captain) → POST /webhooks/<rota> no Hermes (entrada)
2. Hermes processa via Codex/Anthropic/Gemini conforme config dele
3. Hermes invoca este plugin (deliver=http_callback)
4. Plugin POSTa resposta na URL configurada via --deliver-chat-id
5. Backend recebe e roteia pro destinatário real
Validado end-to-end no Hermes da VPS com:
- Subscription criada via `hermes webhook subscribe ... --deliver http_callback`
- POST simulando msg do cliente → resposta chegou no servidor de teste
em ~11s (tempo de processamento via subscription Codex)
- Plugin enabled e descoberto via `hermes plugins list`
Próximo passo (separado, em outro PR): cliente Captain (outgoing + incoming
endpoint) que conecta o Captain ao Hermes via este plugin.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>