Перейти к содержанию

Webhooks

On this page Получайте события от внешних сервисов (GitHub, GitLab, JIRA, Stripe и т.д.) и автоматически запускайте выполнение агента Hermes. Адаптер вебхуков запускает HTTP-сервер, который принимает POST-запросы, проверяет HMAC-подписи, преобразует полезные нагрузки в промпты для агента и направляет ответы обратно источнику или на другую настроенную платформу. Агент обрабатывает событие и может отвечать, оставляя комментарии в PR, отправляя сообщения в Telegram/Discord или записывая результат в лог.

Video Tutorial


Quick Start

  1. Включите через hermes gateway setup или переменные окружения
  2. Определите маршруты в config.yaml или создайте их динамически с помощью hermes webhook subscribe
  3. Укажите вашему сервису URL http://your-server:8644/webhooks/<route-name>

Setup

Есть два способа включить адаптер вебхуков.

Via setup wizard

[code] hermes gateway setup

[/code] Следуйте подсказкам, чтобы включить вебхуки, задать порт и глобальный HMAC-секрет.

Via environment variables

Добавьте в ~/.hermes/.env: [code] WEBHOOK_ENABLED=true
WEBHOOK_PORT=8644 # по умолчанию
WEBHOOK_SECRET=your-global-secret

[/code]

Verify the server

После запуска шлюза: [code] curl http://localhost:8644/health

[/code] Ожидаемый ответ: [code]

[/code]


Configuring Routes

Маршруты определяют, как обрабатываются различные источники вебхуков. Каждый маршрут — это именованная запись в разделе platforms.webhook.extra.routes вашего config.yaml.

Route properties

Свойство Обязательно Описание
events Нет Список типов событий для приёма (например, ["pull_request"]). Если пусто, принимаются все события. Тип события читается из X-GitHub-Event, X-GitLab-Event или event_type в полезной нагрузке.
secret Да HMAC-секрет для проверки подписи. Если не задан на маршруте, используется глобальный secret. Установите "INSECURE_NO_AUTH" только для тестирования (пропускает проверку).
prompt Нет Шаблонная строка с доступом к полям через точечную нотацию (например, {pull_request.title}). Если не указан, полная JSON-полезная нагрузка подставляется в промпт.
skills Нет Список названий навыков для загрузки в сессию агента.
deliver Нет Куда отправлять ответ: github_comment, telegram, discord, slack, signal, sms, whatsapp, matrix, mattermost, homeassistant, email, dingtalk, feishu, wecom, weixin, bluebubbles, qqbot или log (по умолчанию).
deliver_extra Нет Дополнительные настройки доставки — ключи зависят от типа deliver (например, repo, pr_number, chat_id). Значения поддерживают те же шаблоны {dot.notation}, что и prompt.
deliver_only Нет Если true, пропустить агента полностью — отрендеренный шаблон prompt становится буквальным сообщением для доставки. Нулевая стоимость LLM, доставка за доли секунды. Подробнее см. Direct Delivery Mode. Требует, чтобы deliver был реальной целью (не log).
### Full example
[code]
platforms:
webhook:
enabled: true
extra:
port: 8644
secret: "global-fallback-secret"
routes:
github-pr:
events: ["pull_request"]
secret: "github-webhook-secret"
prompt:
Review this pull request:
Repository:
PR #{number}:
Author:
URL:
Diff URL:
Action:
skills: ["github-code-review"]
deliver: "github_comment"
deliver_extra:
repo: "{repository.full_name}"
pr_number: "{number}"
deploy-notify:
events: ["push"]
secret: "deploy-secret"
prompt: "New push to {repository.full_name} branch {ref}: {head_commit.message}"
deliver: "telegram"

[/code]

Prompt Templates

Промпты используют точечную нотацию для доступа к вложенным полям в полезной нагрузке вебхука: * {pull_request.title} преобразуется в payload["pull_request"]["title"] * {repository.full_name} преобразуется в payload["repository"]["full_name"] * {__raw__} — специальный токен, который подставляет всю полезную нагрузку в виде JSON с отступами (обрезается до 4000 символов). Полезен для мониторинговых оповещений или вебхуков общего назначения, где агенту нужен полный контекст. * Отсутствующие ключи остаются как буквальная строка {key} (без ошибки) * Вложенные словари и списки сериализуются в JSON и обрезаются до 2000 символов

Вы можете смешивать {__raw__} с обычными переменными шаблона: [code] prompt: "PR #{pull_request.number} by {pull_request.user.login}: {raw}"

[/code] Если для маршрута не настроен шаблон prompt, вся полезная нагрузка подставляется в виде JSON с отступами (обрезается до 4000 символов). Те же шаблоны с точечной нотацией работают в значениях deliver_extra.

Forum Topic Delivery

При доставке ответов вебхуков в Telegram можно указать конкретную тему форума, включив message_thread_id (или thread_id) в deliver_extra: [code] webhooks:
routes:
alerts:
events: ["alert"]
prompt: "Alert: {raw}"
deliver: "telegram"
deliver_extra:
chat_id: "-1001234567890"
message_thread_id: "42"

[/code] Если chat_id не указан в deliver_extra, доставка выполняется в домашний канал, настроенный для целевой платформы.


GitHub PR Review (Step by Step)

Это пошаговое руководство настраивает автоматическое ревью кода на каждый pull request.

1\. Create the webhook in GitHub

  1. Перейдите в ваш репозиторий → SettingsWebhooksAdd webhook
  2. Установите Payload URL на http://your-server:8644/webhooks/github-pr
  3. Установите Content type на application/json
  4. Установите Secret в соответствии с вашей конфигурацией маршрута (например, github-webhook-secret)
  5. В разделе Which events? выберите Let me select individual events и отметьте Pull requests
  6. Нажмите Add webhook

2\. Add the route config

Добавьте маршрут github-pr в ваш ~/.hermes/config.yaml, как показано в примере выше.

3\. Ensure gh CLI is authenticated

Тип доставки github_comment использует GitHub CLI для публикации комментариев: [code] gh auth login

[/code]

4\. Test it

Откройте pull request в репозитории. Вебхук срабатывает, Hermes обрабатывает событие и публикует комментарий с ревью в PR.


GitLab Webhook Setup

Вебхуки GitLab работают аналогично, но используют другой механизм аутентификации. GitLab отправляет секрет в виде обычного заголовка X-Gitlab-Token (точное совпадение строки, не HMAC).

1\. Create the webhook in GitLab

  1. Перейдите в ваш проект → SettingsWebhooks
  2. Установите URL на http://your-server:8644/webhooks/gitlab-mr
  3. Введите ваш Secret token
  4. Выберите Merge request events (и любые другие нужные события)
  5. Нажмите Add webhook

2\. Add the route config

[code] platforms:
webhook:
enabled: true
extra:
routes:
gitlab-mr:
events: ["merge_request"]
secret: "your-gitlab-secret-token"
prompt: |
Review this merge request:
Project: {project.path_with_namespace}
MR !{object_attributes.iid}: {object_attributes.title}
Author: {object_attributes.last_commit.author.name}
URL: {object_attributes.url}
Action: {object_attributes.action}
deliver: "log"

[/code]


Delivery Options

Поле deliver определяет, куда направляется ответ агента после обработки события вебхука. Тип доставки| Описание
---|---
log| Записывает ответ в лог шлюза. Это значение по умолчанию, полезно для тестирования.
github_comment| Публикует ответ как комментарий в PR/issue через CLI gh. Требует deliver_extra.repo и deliver_extra.pr_number. CLI gh должен быть установлен и аутентифицирован на хосте шлюза (gh auth login).
telegram| Направляет ответ в Telegram. Использует домашний канал или chat_id в deliver_extra.
discord| Направляет ответ в Discord. Использует домашний канал или chat_id в deliver_extra.
slack| Направляет ответ в Slack. Использует домашний канал или chat_id в deliver_extra.
signal| Направляет ответ в Signal. Использует домашний канал или chat_id в deliver_extra.
sms| Направляет ответ в SMS через Twilio. Использует домашний канал или chat_id в deliver_extra.
whatsapp| Направляет ответ в WhatsApp. Использует домашний канал или chat_id в deliver_extra.
matrix| Направляет ответ в Matrix. Использует домашний канал или chat_id в deliver_extra.
mattermost| Направляет ответ в Mattermost. Использует домашний канал или chat_id в deliver_extra.
homeassistant| Направляет ответ в Home Assistant. Использует домашний канал или chat_id в deliver_extra.
email| Направляет ответ на Email. Использует домашний канал или chat_id в deliver_extra.
dingtalk| Направляет ответ в DingTalk. Использует домашний канал или chat_id в deliver_extra.
feishu| Направляет ответ в Feishu/Lark. Использует домашний канал или chat_id в deliver_extra.
wecom| Направляет ответ в WeCom. Использует домашний канал или chat_id в deliver_extra.
weixin| Направляет ответ в Weixin (WeChat). Использует домашний канал или chat_id в deliver_extra.
bluebubbles| Направляет ответ в BlueBubbles (iMessage). Использует домашний канал или chat_id в deliver_extra.
Для кросс-платформенной доставки целевая платформа также должна быть включена и подключена в шлюзе. Если chat_id не указан в deliver_extra, ответ отправляется в настроенный домашний канал этой платформы.


Direct Delivery Mode

По умолчанию каждый POST-запрос вебхука запускает сессию агента — полезная нагрузка становится промптом, агент обрабатывает его, и ответ агента доставляется. Это消耗 токены LLM на каждое событие. Для случаев, когда вам нужно просто отправить простое уведомление — без рассуждений, без цикла агента, просто доставить сообщение — установите deliver_only: true на маршруте. Отрендеренный шаблон prompt становится буквальным телом сообщения, и адаптер отправляет его напрямую в настроенный канал доставки.

When to use direct delivery

  • Внешний push от сервиса — вебхук Supabase/Firebase срабатывает при изменении в БД → мгновенно уведомить пользователя в Telegram
  • Оповещения мониторинга — вебхук оповещения Datadog/Grafana → отправить в канал Discord
  • Межагентские уведомления — Агент A уведомляет пользователя Агента B о завершении долгой задачи
  • Завершение фоновых задач — Cron-задача завершилась → отправить результат в Slack

Преимущества: * Нулевая стоимость LLM — агент никогда не вызывается * Доставка за доли секунды — один вызов адаптера, без цикла рассуждений * Та же безопасность, что в режиме агента — HMAC-аутентификация, лимиты запросов, идемпотентность и ограничения размера тела всё ещё действуют * Синхронный ответ — POST возвращает 200 OK после успешной доставки или 502, если цель отклонила запрос, чтобы ваш вышестоящий сервис мог интеллектуально повторить попытку

Example: Telegram push from Supabase

[code] platforms:
webhook:
enabled: true
extra:
port: 8644
secret: "global-secret"
routes:
antenna-matches:
secret: "antenna-webhook-secret"
deliver: "telegram"
deliver_only: true
prompt: "🎉 New match: {match.user_name} matched with you!"
deliver_extra:
chat_id: "{match.telegram_chat_id}"

[/code] Ваша edge-функция Supabase подписывает полезную нагрузку с помощью HMAC-SHA256 и отправляет POST на https://your-server:8644/webhooks/antenna-matches. Адаптер вебхуков проверяет подпись, рендерит шаблон из полезной нагрузки, доставляет в Telegram и возвращает 200 OK.

Example: Dynamic subscription via CLI

[code] hermes webhook subscribe antenna-matches \
--deliver telegram \
--deliver-chat-id "123456789" \
--deliver-only \
--prompt "🎉 New match: {match.user_name} matched with you!" \
--description "Antenna match notifications"

[/code]

Response codes

Статус Значение
200 OK Доставлено успешно. Тело: {"status": "delivered", "route": "...", "target": "...", "delivery_id": "..."}
200 OK (status=duplicate) Дубликат X-GitHub-Delivery ID в пределах TTL идемпотентности (1 час). Повторно не доставляется.
401 Unauthorized HMAC-подпись недействительна или отсутствует.
400 Bad Request Некорректное JSON-тело.
404 Not Found Неизвестное имя маршрута.
413 Payload Too Large Тело превысило max_body_bytes.
429 Too Many Requests Превышен лимит запросов для маршрута.
502 Bad Gateway Целевой адаптер отклонил сообщение или вызвал ошибку. Ошибка логируется на сервере; тело ответа — общее Delivery failed для предотвращения утечки внутренних данных адаптера.
### Configuration gotchas
* deliver_only: true требует, чтобы deliver был реальной целью. deliver: log (или отсутствие deliver) вызывает ошибку при запуске — адаптер отказывается запускаться, если находит неправильно настроенный маршрут.
* Поле skills игнорируется в режиме прямой доставки (запуск агента не происходит, поэтому некуда внедрять навыки).
* Рендеринг шаблонов использует тот же синтаксис {dot.notation}, что и в режиме агента, включая токен {__raw__}.
* Идемпотентность использует тот же заголовок X-GitHub-Delivery / X-Request-ID — повторные попытки с тем же ID возвращают status=duplicate и НЕ выполняют повторную доставку.

Dynamic Subscriptions (CLI)

В дополнение к статическим маршрутам в config.yaml вы можете динамически создавать подписки на вебхуки с помощью CLI-команды hermes webhook. Это особенно полезно, когда самому агенту нужно настроить управляемые событиями триггеры.

Create a subscription

[code] hermes webhook subscribe github-issues \
--events "issues" \
--prompt "New issue #{issue.number}: {issue.title}\nBy: {issue.user.login}\n\n{issue.body}" \
--deliver telegram \
--deliver-chat-id "-100123456789" \
--description "Triage new GitHub issues"

[/code] Эта команда возвращает URL вебхука и автоматически сгенерированный HMAC-секрет. Настройте ваш сервис на отправку POST-запросов на этот URL.

List subscriptions

[code] hermes webhook list

[/code]

Remove a subscription

[code] hermes webhook remove github-issues

[/code]

Test a subscription

[code] hermes webhook test github-issues
hermes webhook test github-issues --payload '{"issue": {"number": 42, "title": "Test"}}'

[/code]

How dynamic subscriptions work

  • Подписки хранятся в ~/.hermes/webhook_subscriptions.json
  • Адаптер вебхуков автоматически перезагружает этот файл при каждом входящем запросе (проверка mtime, минимальные накладные расходы)
  • Статические маршруты из config.yaml всегда имеют приоритет над динамическими с тем же именем
  • Динамические подписки используют тот же формат и возможности маршрутов, что и статические (события, шаблоны промптов, навыки, доставка)
  • Перезапуск шлюза не требуется — подписка создаётся и сразу работает

Agent-driven subscriptions

Агент может создавать подписки через инструмент терминала, если ему предоставлен навык webhook-subscriptions. Попросите агента «настроить вебхук для GitHub issues», и он выполнит соответствующую команду hermes webhook subscribe.


Security

Адаптер вебхуков включает несколько уровней безопасности:

HMAC signature validation

Адаптер проверяет входящие подписи вебхуков, используя соответствующий метод для каждого источника: * GitHub : заголовок X-Hub-Signature-256 — HMAC-SHA256 шестнадцатеричный дайджест с префиксом sha256= * GitLab : заголовок X-Gitlab-Token — обычное совпадение строки секрета * Generic : заголовок X-Webhook-Signature — сырой HMAC-SHA256 шестнадцатеричный дайджест

Если секрет настроен, но ни один распознанный заголовок подписи не присутствует, запрос отклоняется.

Secret is required

Каждый маршрут должен иметь секрет — либо заданный непосредственно на маршруте, либо унаследованный от глобального secret. Маршруты без секрета вызывают ошибку при запуске адаптера. Только для разработки/тестирования вы можете установить секрет в "INSECURE_NO_AUTH", чтобы полностью пропустить проверку.

Rate limiting

Каждый маршрут ограничен 30 запросами в минуту по умолчанию (фиксированное окно). Настройте глобально: [code] platforms:
webhook:
extra:
rate_limit: 60 # запросов в минуту

[/code] Запросы, превышающие лимит, получают ответ 429 Too Many Requests.

Idempotency

Идентификаторы доставки (из X-GitHub-Delivery, X-Request-ID или запасной вариант на основе временной метки) кэшируются на 1 час. Повторные доставки (например, повторные попытки вебхука) молча пропускаются с ответом 200, предотвращая повторные запуски агента.

Body size limits

Полезные нагрузки, превышающие 1 МБ, отклоняются до чтения тела. Настройка: [code] platforms:
webhook:
extra:
max_body_bytes: 2097152 # 2 МБ

[/code]

Prompt injection risk

warning Полезные нагрузки вебхуков содержат данные, контролируемые атакующим — заголовки PR, сообщения коммитов, описания issues и т.д. могут содержать вредоносные инструкции. Запускайте шлюз в изолированной среде (Docker, ВМ) при доступе из интернета. Рассмотрите использование Docker или SSH бэкенда терминала для изоляции.


Troubleshooting

Webhook not arriving

  • Убедитесь, что порт открыт и доступен из источника вебхука
  • Проверьте правила брандмауэра — порт 8644 (или настроенный вами порт) должен быть открыт
  • Проверьте, что путь URL совпадает: http://your-server:8644/webhooks/<имя-маршрута>
  • Используйте эндпоинт /health чтобы убедиться, что сервер запущен

Signature validation failing

  • Убедитесь, что секрет в вашей конфигурации маршрута точно совпадает с секретом, настроенным в источнике вебхука
  • Для GitHub секрет основан на HMAC — проверьте X-Hub-Signature-256
  • Для GitLab секрет — это обычный токен — проверьте X-Gitlab-Token
  • Проверьте логи шлюза на наличие предупреждений Invalid signature

Event being ignored

  • Проверьте, что тип события входит в список events вашего маршрута
  • События GitHub используют значения, такие как pull_request, push, issues (значение заголовка X-GitHub-Event)
  • События GitLab используют значения, такие как merge_request, push (значение заголовка X-GitLab-Event)
  • Если events пуст или не задан, принимаются все события

Agent not responding

  • Запустите шлюз в режиме переднего плана, чтобы видеть логи: hermes gateway run
  • Проверьте, что шаблон промпта рендерится корректно
  • Убедитесь, что целевой канал доставки настроен и подключён

Duplicate responses

  • Кэш идемпотентности должен предотвращать это — проверьте, что источник вебхука отправляет заголовок с ID доставки (X-GitHub-Delivery или X-Request-ID)
  • Идентификаторы доставки кэшируются на 1 час

gh CLI errors (GitHub comment delivery)

  • Запустите gh auth login на хосте шлюза
  • Убедитесь, что аутентифицированный пользователь GitHub имеет права на запись в репозиторий
  • Проверьте, что gh установлен и находится в PATH

Environment Variables

Переменная Описание По умолчанию
WEBHOOK_ENABLED Включить адаптер платформы вебхуков false
WEBHOOK_PORT Порт HTTP-сервера для приёма вебхуков 8644
WEBHOOK_SECRET Глобальный HMAC-секрет (используется, когда маршруты не указывают свой собственный) (нет)
* Video Tutorial
* Quick Start
* Setup
* Via setup wizard
* Via environment variables
* Verify the server
* Configuring Routes
* Route properties
* Full example
* Prompt Templates
* Forum Topic Delivery
* GitHub PR Review (Step by Step)
* 1\. Create the webhook in GitHub
* 2\. Add the route config
* 3\. Ensure gh CLI is authenticated
* 4\. Test it
* GitLab Webhook Setup
* 1\. Create the webhook in GitLab
* 2\. Add the route config
* Delivery Options
* Direct Delivery Mode
* When to use direct delivery
* Example: Telegram push from Supabase
* Example: Dynamic subscription via CLI
* Response codes
* Configuration gotchas
* Dynamic Subscriptions (CLI)
* Create a subscription
* List subscriptions
* Remove a subscription
* Test a subscription
* How dynamic subscriptions work
* Agent-driven subscriptions
* Security
* HMAC signature validation
* Secret is required
* Rate limiting
* Idempotency
* Body size limits
* Prompt injection risk
* Troubleshooting
* Webhook not arriving
* Signature validation failing
* Event being ignored
* Agent not responding
* Duplicate responses
* gh CLI errors (GitHub comment delivery)
* Environment Variables