Вебхуки при изменении заметок

Вызывайте внешние сервисы автоматически, когда заметки создаются, обновляются или удаляются.

Без вебхуков каждое изменение заметки требует ручных действий: зайти в сервис, нажать «обновить», запустить скрипт. Когда заметок сотни — это не работает. Вебхуки делают это автоматически: сохранил заметку — поисковый индекс обновился, орфография проверена, уведомление отправлено.

Кому подходит

Разработчик с внешним поиском — при изменении документации автоматически обновляет Algolia, Elasticsearch или свой индекс.

Автор с AI-ассистентом — при сохранении поста агент проверяет орфографию и возвращает исправления.

Команда с уведомлениями — при публикации новой заметки Slack или Discord получает сообщение.

Администратор сайта — при создании контента агент автоматически добавляет мета-описание, теги или форматирует frontmatter.

Настройка занимает 5–10 минут: нужен URL вашего сервиса и понимание, какие заметки отслеживать.

Как это работает

  1. Создаёте вебхук: URL + паттерны путей
  2. При изменении подходящей заметки — сервер отправляет POST
  3. Ваш сервис обрабатывает данные: запускает AI, обновляет индекс, отправляет уведомление

Настройка

URL — адрес вашего сервиса.

Паттерны — какие заметки отслеживать. Используют glob-синтаксис:

Паттерн Что совпадает
blog/* Файлы в папке blog (без подпапок)
blog/** Файлы в blog и всех подпапках
docs/** Все файлы в docs
* Все заметки

Можно задать исключения. Заметка попадает в вебхук если подходит хотя бы под один include и не подходит ни под один exclude:

include: ["docs/**", "blog/**"]
exclude: ["docs/internal/**", "*.draft.md"]

События — на что реагировать: создание, обновление, удаление. По умолчанию все три.

Инструкция — текстовая подсказка для AI-агента. Например: «Проверь орфографию и верни исправленный текст». Позволяет использовать один endpoint для разных задач.

Что приходит в запросе

{
  "id": 42,
  "instruction": "Проверь орфографию",
  "depth": 0,
  "changes": [
    {
      "path": "blog/my-post.md",
      "event": "update",
      "title": "My Post",
      "content": "# My Post\n\nТекст заметки..."
    }
  ],
  "api_token": "eyJhbGc..."
}

Если за один коммит изменились несколько подходящих заметок — они приходят в одном запросе массивом.

api_token присутствует только если включён Pass API key.

Проверка подписи

Каждый запрос подписан HMAC-SHA256. Заголовок X-Webhook-Signature: sha256={hex} гарантирует, что запрос пришёл от trip2g.

Secret создаётся автоматически при создании вебхука и показывается один раз. Регенерировать можно в любой момент.

Ответ агента: применение изменений

Агент может вернуть изменения прямо в ответе — сервер применит их автоматически:

{
  "status": "ok",
  "changes": [
    {
      "path": "blog/my-post.md",
      "content": "# My Post\n\nИсправленный текст...",
      "expected_hash": "abc123"
    }
  ]
}

expected_hash — хеш полученной заметки. Защищает от конфликтов: если заметка изменилась пока агент работал, применение будет отклонено. Для новых файлов оставьте пустым.

API-токен для агентов

Включите Pass API key — агент получит временный токен для работы с API:

  • Читать и создавать заметки
  • Токен действует ограниченное время
  • Доступ ограничен паттернами чтения и записи из настроек вебхука

По умолчанию: читать всё, писать ничего. Явно задайте write_patterns если агент должен создавать/обновлять заметки.

Защита от рекурсии

Если агент правит заметку через API — это снова вызовет вебхук. Система отслеживает глубину цепочки:

  • max_depth: 1 (по умолчанию) — вебхук срабатывает только на прямые изменения
  • max_depth: 2 — срабатывает и на изменения от агентов

Пример: линтер (max_depth: 1) правит пост → индексатор (max_depth: 2) видит правку линтера → линтер не реагирует на правку индексатора.

Что может пойти не так

Сервис не отвечает или возвращает ошибку — проверьте, что URL доступен извне, не только с localhost. Если сервис развёрнут локально, используйте ngrok или аналог для тестирования.

Подпись не проходит проверку — убедитесь, что вычисляете HMAC от сырого тела запроса (bytes), а не от распарсенного JSON. Любое изменение порядка ключей или пробелов сломает подпись.

Вебхук срабатывает бесконечно — агент правит заметку через API, это снова триггерит вебхук. Установите max_depth: 1 (по умолчанию) — тогда изменения от самого агента не вызовут повторный запуск.

Паттерн не совпадаетblog/* не захватывает подпапки, только файлы прямо в blog/. Для вложенных папок используйте blog/**.

Агент не успевает ответить — сервер ждёт ответ ограниченное время. Долгие операции (генерация, внешние API) лучше запускать асинхронно: ответьте {"status": "ok"} сразу, а результат примените через API отдельным запросом.

Изменения от агента отклоненыexpected_hash не совпал: заметка изменилась пока агент работал. Перечитайте заметку и повторите операцию с актуальным хешем.

Примеры использования

AI-линтер — при сохранении поста запускает проверку орфографии и возвращает исправления в ответе. Пользователь видит «само исправилось».

Модератор — только на создание (on_create: true, остальные выключены) проверяет новые заметки на нежелательный контент, помечает или скрывает.

Индексатор — при изменении документации обновляет поисковый индекс или внешний кеш.

Уведомления — при публикации отправляет сообщение в Slack, Discord или email.

SEO-агент — при создании новой заметки генерирует мета-описание и добавляет в frontmatter.