Перейти к основному содержимому

Вебхуки

Получайте события от внешних сервисов (GitHub, GitLab, JIRA, Stripe и др.) и автоматически запускайте агентов VibeOS. Адаптер вебхуков запускает HTTP-сервер, который принимает POST-запросы, проверяет HMAC-подписи, преобразует полезные данные в промпты для агента и направляет ответы обратно источнику или на другую настроенную платформу.

Агент обрабатывает событие и может ответить, оставляя комментарии к PR, отправляя сообщения в Telegram/Discord или записывая результат в лог.

Видеоурок​


Быстрый старт​

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

Настройка​

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

Через мастер настройки​

vibeos gateway setup

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

Через переменные окружения​

Добавьте в ~/.vibeos/.env:

WEBHOOK_ENABLED=true
WEBHOOK_PORT=8644 # по умолчанию
WEBHOOK_SECRET=ваш-глобальный-секрет

Проверка сервера​

После запуска шлюза:

curl http://localhost:8644/health

Ожидаемый ответ:

{"status": "ok", "platform": "webhook"}

Настройка маршрутов​

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

Свойства маршрута​

СвойствоОбязательноОписание
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, доставка за доли секунды. См. Режим прямой доставки для примеров использования. Требует, чтобы deliver был реальной целью (не log).

Полный пример​

platforms:
webhook:
enabled: true
extra:
port: 8644
secret: "глобальный-запасной-секрет"
routes:
github-pr:
events: ["pull_request"]
secret: "секрет-вебхука-github"
prompt: |
Проверьте этот pull request:
Репозиторий: {repository.full_name}
PR #{number}: {pull_request.title}
Автор: {pull_request.user.login}
URL: {pull_request.html_url}
URL diff: {pull_request.diff_url}
Действие: {action}
skills: ["github-code-review"]
deliver: "github_comment"
deliver_extra:
repo: "{repository.full_name}"
pr_number: "{number}"
deploy-notify:
events: ["push"]
secret: "секрет-развёртывания"
prompt: "Новый push в {repository.full_name} ветка {ref}: {head_commit.message}"
deliver: "telegram"

Шаблоны промптов​

Промпты используют точечную нотацию для доступа к вложенным полям в полезных данных вебхука:

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

Вы можете смешивать {__raw__} с обычными переменными шаблона:

prompt: "PR #{pull_request.number} от {pull_request.user.login}: {__raw__}"

Если для маршрута не настроен шаблон prompt, все полезные данные выгружаются в виде форматированного JSON (обрезается до 4000 символов).

Те же шаблоны точечной нотации работают в значениях deliver_extra.

Доставка в тему форума​

При доставке ответов вебхука в Telegram вы можете указать конкретную тему форума, включив message_thread_id (или thread_id) в deliver_extra:

webhooks:
routes:
alerts:
events: ["alert"]
prompt: "Оповещение: {__raw__}"
deliver: "telegram"
deliver_extra:
chat_id: "-1001234567890"
message_thread_id: "42"

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


Проверка PR на GitHub (пошагово)​

Это руководство настраивает автоматическую проверку кода для каждого pull request.

1. Создайте вебхук в GitHub​

  1. Перейдите в ваш репозиторий → Settings → Webhooks → Add 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. Добавьте конфигурацию маршрута​

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

3. Убедитесь, что CLI gh аутентифицирован​

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

gh auth login

4. Протестируйте​

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


Настройка вебхука GitLab​

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

1. Создайте вебхук в GitLab​

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

2. Добавьте конфигурацию маршрута​

platforms:
webhook:
enabled: true
extra:
routes:
gitlab-mr:
events: ["merge_request"]
secret: "ваш-секретный-токен-gitlab"
prompt: |
Проверьте этот merge request:
Проект: {project.path_with_namespace}
MR !{object_attributes.iid}: {object_attributes.title}
Автор: {object_attributes.last_commit.author.name}
URL: {object_attributes.url}
Действие: {object_attributes.action}
deliver: "log"

Варианты доставки​

Поле 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, ответ отправляется в настроенный домашний канал этой платформы.


Режим прямой доставки​

По умолчанию каждый POST-запрос вебхука запускает агента — полезные данные становятся промптом, агент обрабатывает их, и ответ агента доставляется. Это расходует токены LLM на каждое событие.

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

Когда использовать прямую доставку​

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

Преимущества:

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

Пример: Push в Telegram из Supabase​

platforms:
webhook:
enabled: true
extra:
port: 8644
secret: "глобальный-секрет"
routes:
antenna-matches:
secret: "секрет-вебхука-антенны"
deliver: "telegram"
deliver_only: true
prompt: "🎉 Новое совпадение: {match.user_name} совпал с вами!"
deliver_extra:
chat_id: "{match.telegram_chat_id}"

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

Пример: Динамическая подписка через CLI​

vibeos webhook subscribe antenna-matches \
--deliver telegram \
--deliver-chat-id "123456789" \
--deliver-only \
--prompt "🎉 Новое совпадение: {match.user_name} совпал с вами!" \
--description "Уведомления о совпадениях антенны"

Коды ответов​

СтатусЗначение
200 OKУспешно доставлено. Тело: {"status": "delivered", "route": "...", "target": "...", "delivery_id": "..."}
200 OK (status=duplicate)Дубликат ID X-GitHub-Delivery в пределах TTL идемпотентности (1 час). Не доставляется повторно.
401 UnauthorizedHMAC-подпись недействительна или отсутствует.
400 Bad RequestНекорректное JSON-тело.
404 Not FoundНеизвестное имя маршрута.
413 Payload Too LargeТело превысило max_body_bytes.
429 Too Many RequestsПревышен лимит запросов маршрута.
502 Bad GatewayЦелевой адаптер отклонил сообщение или вызвал ошибку. Ошибка логируется на стороне сервера; тело ответа — общее Delivery failed, чтобы не раскрывать внутренности адаптера.

Особенности конфигурации​

  • deliver_only: true требует, чтобы deliver был реальной целью. deliver: log (или опускание deliver) отклоняется при запуске — адаптер отказывается запускаться, если находит неправильно настроенный маршрут.
  • Поле skills игнорируется в режиме прямой доставки (агент не запускается, поэтому некуда внедрять навыки).
  • Рендеринг шаблона использует тот же синтаксис {dot.notation}, что и в режиме агента, включая токен {__raw__}.
  • Идемпотентность использует тот же заголовок X-GitHub-Delivery / X-Request-ID — повторные попытки с тем же ID возвращают status=duplicate и НЕ доставляются повторно.

Динамические подписки (CLI)​

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

Создание подписки​

vibeos webhook subscribe github-issues \
--events "issues" \
--prompt "Новый issue #{issue.number}: {issue.title}\nОт: {issue.user.login}\n\n{issue.body}" \
--deliver telegram \
--deliver-chat-id "-100123456789" \
--description "Триаж новых issues GitHub"

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

Список подписок​

vibeos webhook list

Удаление подписки​

vibeos webhook remove github-issues

Тестирование подписки​

vibeos webhook test github-issues
vibeos webhook test github-issues --payload '{"issue": {"number": 42, "title": "Test"}}'

Как работают динамические подписки​

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

Подписки, управляемые агентом​

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


Безопасность​

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

Проверка HMAC-подписи​

Адаптер проверяет входящие подписи вебхуков, используя соответствующий метод для каждого источника:

  • GitHub: заголовок X-Hub-Signature-256 — шестнадцатеричный дайджест HMAC-SHA256 с префиксом sha256=
  • GitLab: заголовок X-Gitlab-Token — простое совпадение строки секрета
  • Общий: заголовок X-Webhook-Signature — сырой шестнадцатеричный дайджест HMAC-SHA256

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

Секрет обязателен​

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

INSECURE_NO_AUTH принимается только тогда, когда шлюз привязан к адресу loopback (127.0.0.1, localhost, ::1). Если он используется с не-loopback привязкой, такой как 0.0.0.0 или LAN IP, адаптер отказывается запускаться — это предотвращает случайное раскрытие неаутентифицированной конечной точки на публичном интерфейсе.

Лимитирование запросов​

Каждый маршрут ограничен 30 запросами в минуту по умолчанию (фиксированное окно). Настройте это глобально:

platforms:
webhook:
extra:
rate_limit: 60 # запросов в минуту

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

Идемпотентность​

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

Ограничения размера тела​

Полезные данные, превышающие 1 МБ, отклоняются до чтения тела. Настройте это:

platforms:
webhook:
extra:
max_body_bytes: 2097152 # 2 МБ

Аутентификация не означает доверие​

предупреждение

HMAC-валидация аутентифицирует отправителя, а не содержимое. Действительная подпись только доказывает, что запрос пришёл от стороны, владеющей секретом маршрута (например, GitHub). Она ничего не говорит о том, кто написал бизнес-поля внутри полезных данных — заголовки PR, сообщения коммитов, описания issues и любой другой текст из вышестоящего источника созданы произвольными третьими лицами и должны рассматриваться как ненадёжные.

Это та же модель доверия, которая применяется ко всему, что читает агент: веб-страницы, файлы и вывод инструментов — всё это ненадёжный ввод. VibeOS не может и не должен надёжно очищать ненадёжный текст с помощью блок-листа; формулировки, кодировка и перевод делают это тривиально обходимым. Граница доверия — это поверхность возможностей агента, а не канал ввода. Укрепляйте её:

  • Изолируйте среду выполнения. Запускайте шлюз с бэкендом Docker или SSH-терминала (или в VM) при доступе из интернета, чтобы захваченный поворот не мог затронуть хост.
  • Ограничьте набор инструментов. Отключайте инструменты terminal, file и исходящие действия на сессиях, запущенных вебхуками, если маршруту нужно только читать и обобщать. Меньше возможностей — меньше радиус поражения, если поле полезных данных содержит внедрённые инструкции.
  • Оставьте подтверждения включёнными для любых деструктивных или исходящих операций, чтобы внедрённая инструкция не могла действовать без присмотра.
  • Шаблонизируйте узко. Предпочитайте конкретный prompt с именованными полями ({pull_request.title}) вместо {__raw__} или пустого шаблона, который выгружает все полезные данные, чтобы в промпт попадали только те поля, которые вы планируете.

Устранение неполадок​

Вебхук не приходит​

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

Ошибка проверки подписи​

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

Событие игнорируется​

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

Агент не отвечает​

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

Дублирующиеся ответы​

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

Ошибки CLI gh (доставка комментариев GitHub)​

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

Переменные окружения​

ПеременнаяОписаниеПо умолчанию
WEBHOOK_ENABLEDВключить адаптер платформы вебхуковfalse
WEBHOOK_PORTПорт HTTP-сервера для приёма вебхуков8644
WEBHOOK_SECRETГлобальный HMAC-секрет (используется как запасной, когда маршруты не указывают свой)(нет)