Cron спрашивает: «Пора ли?». Вебхуки сообщают: «Это только что произошло, действуйте». Для работы агентов это различие имеет значение. Запланированная проверка входящих писем отличается от событий «в Stripe открыта претензия» или «создан запрос на включение изменений в ветку main».
Вебхуки агента Hermes преобразуют аутентифицированные HTTP POST-события в запуски агентов, результаты которых отправляются настроенной цели доставки. При грамотном использовании они представляют собой небольшие двери с замками и чёткими задачами. При неграмотном использовании они становятся открытым портом с одним мега-промптом, который пытается обработать любой JSON-объект, отправляемый интернетом.
В этой статье рассматриваются проектирование маршрута, подходящая источнику аутентификация, документированная проверка работоспособности и практический дымовой тест. Сопоставьте её с укреплением безопасности на первой неделе в /articles/hermes-first-week-memory-and-skills, прежде чем выставлять что-либо за пределы localhost.
Когда вебхуки являются правильным триггером
Отдавайте предпочтение вебхукам, когда:
- важна задержка (проверка запроса на включение изменений, пока автор ещё не переключился на другую задачу);
- исходная система уже генерирует события (GitHub, GitLab, Jira, Stripe, внутренние формы);
- каждое событие должно становиться одной сфокусированной задачей, а не длительной разговорной сессией.
Отдавайте предпочтение cron, когда:
- вы опрашиваете систему на наличие расхождений («есть ли сертификаты, истекающие через 14 дней?»);
- источник не может отправлять данные;
- вам нужен спокойный периодический отчёт, а не прерывания по каждому событию.
Официальные рекомендации Hermes соответствуют этому разделению: cron служит для запланированных проверок, а вебхуки для запусков по событиям.
Архитектура в одном изображении
Исходная система (GitHub / GitLab / n8n / собственное приложение)
| HTTPS POST + подходящая источнику аутентификация
v
Адаптер вебхуков Hermes (порт по умолчанию 8644)
| маршрут: /webhooks/<name>
v
Конфигурация именованного маршрута (фильтры + промпт + доставка)
v
Запуск агента (навыки/инструменты в рамках вашей политики одобрения)
v
Настроенная доставка (чат-канал, комментарий GitHub или журнал)
n8n может выступать слоем валидации и объединения входящих событий: проверять поля, отбрасывать лишнее, затем отправлять минимизированную полезную нагрузку POST-запросом в Hermes. Это иллюстративная архитектура из /articles/hermes-vs-n8n-choose-by-job, а не документированная готовая интеграция поставщика. Если n8n должен получить результат агента обратно в свой рабочий процесс, вызывайте отдельный API-сервер Hermes на порту 8642 по умолчанию с bearer-аутентификацией, а не считайте адаптер вебхуков синхронным обратным вызовом.
Путь настройки (проверяйте по актуальной документации)
Документация по вебхукам описывает следующий путь:
- Включите платформу вебхуков (
hermes gateway setupили переменную окружения, такую какWEBHOOK_ENABLED=true). - Настройте секрет для каждого маршрута. В зависимости от источника используйте HMAC-заголовок GitHub, заголовок GitLab с открытым токеном или общий V2 HMAC с временной меткой.
- Создайте именованный маршрут в конфигурации или через
hermes webhook subscribe(команда согласно текущей документации). - Проверка работоспособности:
curl http://localhost:8644/health - Укажите внешнюю систему на адрес
https://your-host/webhooks/<name> - Отправьте аутентифицированную тестовую полезную нагрузку; подтвердите ожидаемые маршрут, промпт, область инструментов и цель доставки.
Документированный порт по умолчанию равен 8644. По умолчанию маршрут также ограничен 30 запросами в минуту, а тела размером более 1 МБ отклоняются. Если вы изменили эти значения, тестируйте настроенные ограничения, а не полагайтесь на значения по умолчанию.
Изменения статической конфигурации могут потребовать процедуры жизненного цикла шлюза, описанной для установленного выпуска. Динамические маршруты, созданные с помощью
hermes webhook subscribe, загружаются без перезапуска и получают автоматически созданный секрет. В любом случае убедитесь, что процесс шлюза видит нужный профиль и окружение; успешное выполнение команды в интерактивной оболочке не доказывает, что демон имеет ту же конфигурацию.
Аутентификация маршрута обязательна
Каждый маршрут должен наследовать или определять секрет, иначе адаптер завершится с ошибкой при запуске. Аутентификация зависит от поставщика: GitHub использует X-Hub-Signature-256, GitLab требует точного совпадения X-Gitlab-Token, а общим пользовательским отправителям следует использовать V2 HMAC с временной меткой. Аутентификация отправителя доказывает, какой владелец секрета отправил запрос, но не делает инструкции в полезной нагрузке доверенными.
Правила, которые работают в продакшене:
- Сгенерируйте длинный случайный секрет; храните его в менеджере секретов или файле окружения с ограниченными правами, но не в markdown навыка, который агент может читать.
- Предпочитайте маршрутные секреты, когда системы имеют разные уровни доверия (приложение GitHub против внутренней формы против партнерского вебхука).
- Отклоняйте неподписанные или недействительные подписи на периметре; не «логируйте и продолжайте».
- Используйте
INSECURE_NO_AUTHтолько для временного тестирования через loopback. Адаптер отказывается запускаться, если это значение сочетается с привязкой не к loopback, например к0.0.0.0или адресу LAN.
Используйте текущую общую схему V2 Hermes для пользовательских отправителей: X-Webhook-Timestamp содержит секунды Unix; X-Webhook-Signature-V2 содержит шестнадцатеричный HMAC-SHA256 дайджест в нижнем регистре от <timestamp>.<raw-body>. Hermes отклоняет временные метки вне окна ±300 секунд. V1 подписывает только тело и не имеет защиты от повторного воспроизведения, поэтому не создавайте новые отправители на его основе (официальный контракт безопасности вебхуков).
Воспроизводимый дымовой тест с подписью
После создания маршрута с именем support-triage поместите нечувствительный полезный блок в payload.json. Убедитесь, что ваш утвержденный механизм внедрения секрета установил WEBHOOK_SECRET до запуска этой оболочки; не вводите производственный секрет вручную в историю команд. Приведенная ниже команда Node считывает ключ из окружения, а не раскрывает его в аргументах процесса, и подписывает точные байты файла:
: "${WEBHOOK_SECRET:?inject a disposable route secret before running this test}"
timestamp="$(date +%s)"
signature="$(TIMESTAMP="$timestamp" node -e '
const { createHmac } = require("node:crypto");
const { readFileSync } = require("node:fs");
const hmac = createHmac("sha256", process.env.WEBHOOK_SECRET);
hmac.update(`${process.env.TIMESTAMP}.`, "utf8");
hmac.update(readFileSync("payload.json"));
process.stdout.write(hmac.digest("hex"));
')"
curl --fail-with-body \
-H 'Content-Type: application/json' \
-H "X-Webhook-Timestamp: $timestamp" \
-H "X-Webhook-Signature-V2: $signature" \
--data-binary @payload.json \
http://127.0.0.1:8644/webhooks/support-triage
Затем повторите запрос без обоих заголовков подписи и с временной меткой старше 300 секунд. Оба запроса должны быть отклонены. Не вставляйте реальный секретный ключ на скриншоты, в тикеты или историю командной оболочки; используйте одноразовый секрет маршрута для тестирования документации и меняйте его после завершения.
Открытый вебхук, способный передать контролируемый злоумышленником текст агенту с доступом к терминалу, создаёт риск удалённого выполнения инструментов. Аутентификация ограничивает круг отправителей событий, но даже текст аутентифицированной полезной нагрузки может быть враждебным. Используйте TLS и сетевые ограничения, минимизируйте полезные нагрузки, ограничьте или отключите инструменты терминала, файлов и исходящих действий, а выполнение изолируйте от хоста. Запросы подтверждения защищают намерение оператора, а не изолируют враждебный ввод.
Что помещать в полезную нагрузку
Отправляйте агенту контракт, а не сырой поток данных:
{
"event_type": "github.pull_request.opened",
"repo": "acme/api",
"pr_number": 1842,
"title": "Add billing retry worker",
"author": "ada",
"base_ref": "main",
"html_url": "https://github.example.invalid/acme/agent-service/pull/1842",
"task": "Summarize risk for main. List missing tests. Do not approve or merge."
}
Удаляйте неиспользуемые поля. Огромные дампы рабочих процессов расходуют контекст и провоцируют некорректное использование инструментов. «Небольшая явная полезная нагрузка с ясной задачей» является рекомендацией этой статьи по проектированию, а не утверждением об официальной интеграции n8n.
Проектирование маршрутов: много маленьких дверей
Не создавайте /webhooks/everything. Создавайте именованные маршруты с фильтрами и промптами:
| Имя маршрута | Источник | Задача | Доставка |
|---|---|---|---|
gh-pr-opened | Открыт PR в GitHub | Сводка рисков + пробелы тестов | Тема Telegram для инженеров |
stripe-dispute | Создан спор Stripe | Черновик контрольного списка | Slack финансов + журнал |
support-form | n8n после валидации | Классификация + черновик ответа | Настроенный приватный канал Slack |
uptime-alert | Вебхук мониторинга | Сбор контекста последних деплоев | Канал дежурных |
Каждый маршрут должен отвечать на вопросы:
- Какие события принимаются?
- Какой единственный ожидаемый результат?
- Какие инструменты разрешены для профиля агента этого маршрута?
- Куда направляется результат?
- Что происходит при сбое (повтор? очередь недоставленных сообщений? уведомление специалиста?)?
Полезные нагрузки вебхуков часто содержат адреса электронной почты, идентификаторы аккаунтов или тексты сообщений. Минимизируйте количество полей до их попадания в Hermes. Схема маршрута не документирует отдельный переключатель записи в память для каждого маршрута. Используйте отдельный профиль с отключённой памятью или включённым
memory.write_approvalи проверьте, что сохраняется. Если рассуждение агента не требуется, используйте документированный режимdeliver_onlyвместо запуска агента.
Контроль работоспособности и эксплуатация
Документированная конечная точка для проверки состояния: http://localhost:8644/health (или ваш хост/порт). Используйте её для:
- Локальных дымовых тестов после включения
- Проб готовности в Docker/Kubernetes
- Внешних проверок доступности по приватному URL состояния, а не по публичному маршруту вебхука без аутентификации
Также логируйте:
- Ошибки проверки подписи (возможная атака или неверно настроенный секрет)
- Ошибки валидации полезной нагрузки
- Длительность выполнения агента и отказы в одобрении инструментов
- Ошибки доставки на стороне получателя (например, недоступность чат-API)
Без этих сигналов фраза «агент работал нестабильно» станет вашим единственным отчётом об инциденте. Эти записи улучшают наблюдаемость, но сами по себе не образуют полный защищённый от изменений аудиторский журнал.
Пример: открытие PR в GitHub → сфокусированное выполнение
Цель: Когда PR открывается в main, Hermes формирует заметку о рисках для человека. Он не сливает, не одобряет и не комментирует код, если вы позже не добавите маршрут доставки с проверкой.
- Создайте маршрут
gh-pr-opened. Для прямой доставки GitHub настройте общий секрет, используемый для проверкиX-Hub-Signature-256; для общего ретранслятора n8n реализуйте вместо этого контракт V2 HMAC с временной меткой. - Фильтруйте по событиям
pull_request/openedи базовомуmain. - Промпт с контрактом: кратко изложите цель, область возможных последствий, отсутствующие тесты и риски развёртывания; отмечайте неизвестные данные; не давайте инструкций по слиянию.
- Инструменты: чтение из GitHub только если настроено; оболочка (shell) отключена или требует одобрения.
- Доставка: публикуйте markdown во внутренний канал; человек принимает решение о дальнейших шагах.
Показана структура хорошего результата агента (иллюстративная структура; формулировки вашей модели могут отличаться):
PR #1842: Добавить воркер повторных попыток выставления счетов (из ветки ada в main)
Факты
- Внесены изменения в воркер выставления счетов и конфигурацию очереди (на основе названия и списка файлов).
- Связанный URL: `https://github.example.invalid/acme/agent-service/pull/1842` (иллюстративный)
Риски
- Возможны лавины повторных попыток при отсутствии механизма экспоненциальной задержки [inference; verify in diff]
- В названии не указаны ключи идемпотентности [unclear]
Отсутствуют тесты для подтверждения
- Поведение при дублировании доставки / возникновении «отравленных» сообщений
- Настройка оповещений при исчерпании бюджета повторных попыток
Не сливать изменения на основе данного примечания. Требуется проверка человеком.
Это выполнение агента, управляемое событиями, с правилом остановки. Это не автономный владелец кода.
Упражнение: спроектируйте три маршрута перед включением хотя бы одного
На бумаге (или в вашей книге инструкций) опишите три маршрута вебхуков для вашего стека. Для каждого укажите:
- Имя
- Источник + фильтр событий
- Метод аутентификации и владелец секрета
- Поля полезной нагрузки: начните максимум с 10 полей, чтобы намеренно ограничить бюджет упражнения
- Промпт: начните максимум с 8 строк, затем добавляйте только то, что требуют оценки маршрута
- Разрешённые инструменты
- Цель доставки
- Поведение при сбое
Сначала реализуйте маршрут с наименьшим риском, обычно внутреннее оповещение или черновик сводки PR. Выполните curl к /health, затем аутентифицированный тестовый POST-запрос и тест с недействительной аутентификацией, после чего отправьте одно реальное событие в непроизводственном репозитории или тестовом проекте.
Ожидаемые режимы сбоев
- Несоответствие секрета после ротации: аутентификация не проходит; исправьте окружение процесса шлюза, а не только оболочку ноутбука.
- Слишком широкий промпт: агент импровизирует с инструментами; разделите маршрут.
- Лавина повторных попыток: источник повторяет POST-запросы. Hermes кэширует идентификаторы доставки в течение часа, но для содержательной дедупликации требуется стабильный
X-GitHub-DeliveryилиX-Request-ID. Действия, видимые клиенту, всё равно требуют устойчивой бизнес-идемпотентности со сроком хранения, соответствующим окну повтора. - Загрязнение памяти: большой поток оповещений достигает долговременной памяти; используйте отдельный профиль и явные настройки памяти.
- Открытый порт: проверки работоспособности и вебхуки доступны без предусмотренных TLS и сетевых ограничений; исправьте сеть до добавления инструментов.
Ссылки, которые стоит держать открытыми
- Адаптер вебхуков Hermes
- API-сервер Hermes
- Модель безопасности Hermes
- Документация Hermes
- Внутренние материалы: /articles/first-ai-agent-in-n8n, /articles/hermes-vs-n8n-choose-by-job
Агенты, управляемые событиями, наиболее эффективны, когда каждый маршрут узок, аутентифицирован и наблюдаем и имеет настроенную цель доставки. Адаптер вебхуков является входной точкой событий, а не API запрос-ответ с bearer-аутентификацией. Проектируйте и тестируйте его соответственно.



