Материал для команд, которым нужны уведомления о сборке в Discord без развёртывания полноценного бота: через Incoming Webhook и шлюз OpenClaw на удалённом Mac. Ниже — согласование Node, пути установки curl или npm, openclaw onboard, проверка Dashboard, шаблон JSON для embed и разбор доставки при 403, 429 и таймаутах. Смежные материалы: мультиэндпоинты и сводка CI, установка и типовые сбои, health-check шлюза и LaunchAgent. Без входа: главная, помощь, покупка.
  • Рассинхрон Node: интерактивный SSH показывает one version, а сервис шлюза под launchd стартует с другой — падает CLI или не совпадают зависимости после обновления.
  • Утечка URL Webhook: строка https://discord.com/api/webhooks/… в репозитории позволяет посторонним спамить канал; ротация не всегда быстро доводится до CI и до LaunchAgent.
  • Шторм уведомлений: матрица пайплайна шлёт десятки POST подряд — Discord отвечает 429, а сводка «успешной» сборки теряется среди повторов и ручных ретраев.

① Предпосылки среды и принцип минимальных привилегий

В 2026 году типовой путь для OpenClaw на Mac остаётся двойным: официальный curl-install либо npm i -g openclaw@latest. После установки выполните openclaw onboard и зафиксируйте документацией ожидаемую ветку Node — на практике это 22.16+ или 24 LTS, причём одинаковую для вашей SSH-сессии и для plist launchd, иначе «у вас работает, у демона нет».

Команда openclaw doctor быстро подсветит однотипные проблемы с PATH и TLS. Для корпоративного периметра заранее согласуйте HTTPS_PROXY, NO_PROXY и при необходимости NODE_EXTRA_CA_CERTS так, чтобы curl к discord.com и процесс шлюза видели один и тот же доверенный корень.

Минимальные права в Discord: достаточно Incoming Webhook в конкретном канале; не подключайте к каналу избыточные приложения ради одной пары «сборка упала». URL храните в секрете CI, в файле окружения с правами chmod 600 на хосте или в менеджере секретов — но не в Git и не в скриншотах в общем чате.

Критерий Рекомендуется Избегать
Версия Node Единая 24 LTS на шлюзе и в скриптах Разные major между shell и сервисом
Секрет Webhook Переменная DISCORD_WEBHOOK_URL вне VCS Жёстко прошитый URL в репозитории
Наблюдаемость Отдельный каталог логов шлюза с ротацией Бесконтрольный рост отладочных логов на системном томе

② Создание Discord Webhook и привязка на стороне шлюза

После openclaw onboard откройте Dashboard шлюза (как правило 127.0.0.1 и порт из конфигурации) и убедитесь, что процесс слушает ожидаемый интерфейс. Если Dashboard доступен только локально, а CI работает на другой машине, спланируйте либо обратный прокси с mTLS, либо прямой POST из раннера в Discord — ниже оба сценария совместимы с одним и тем же шаблоном JSON.

В Discord: канал → настройки интеграций → Webhooks → создать, скопировать полный URL. На стороне OpenClaw укажите его в настройках уведомлений или прокиньте в небольшой relay-скрипт, который читает тело от CI и добавляет служебные поля. После изменения переменных перезапустите сервис (launchctl kickstart -k для вашего label) и проверьте, что новая среда подхватилась.

Шаг Действие Критерий готовности
1 onboard + открыт Dashboard Локальный curl к корню или health возвращает ожидаемый код
2 Записать DISCORD_WEBHOOK_URL и перезапустить демон launchctl print показывает обновлённое окружение
3 Ручной POST теста (см. блок кода) HTTP 204 и сообщение в канале
4 Подключить секрет в CI dry-run job отправляет одно короткое сообщение без утечки логов
5 Разделить stage и prod URL Разные webhook на разные каналы, без общей переменной
export WH='https://discord.com/api/webhooks/ID/TOKEN'
curl -sS -o /dev/null -w "%{http_code}\n" -X POST "$WH" \
  -H "Content-Type: application/json" \
  -d '{"content":"Проверка OpenClaw → Discord с удалённого Mac OK"}'

Если сообщения нет: сверьте, что не перепутаны каналы для staging и production; одновременно пустые content и embeds недопустимы; слишком длинный текст обрежьте или перенесите в embed.description с запасом по лимитам Discord.

③ Шаблон payload сводки CI и маппинг полей

Для читаемости в канале лучше embed: заголовок фиксирует репозиторий, поля несут ветку, SHA, автора, длительность и ссылку на job. Ниже — ориентир по источникам в GitHub Actions; для GitLab или Jenkins замените переменные на аналоги.

Поле для людей Типичный источник Поле Discord
Репозиторий GITHUB_REPOSITORY embeds[0].title или field «Repo»
Ветка / тег GITHUB_REF_NAME field или footer.text
Коммит GITHUB_SHA (короткий slice) field + URL коммита
Статус и время exit code шага, SECONDS color (зелёный/красный) и description
PAYLOAD=$(printf '%s' '{"embeds":[{"title":"CI сводка","description":"main @ abc1234 — success — 3m12s","color":3066993}]}')
curl -sS --connect-timeout 5 --max-time 20 -X POST "$DISCORD_WEBHOOK_URL" \
  -H "Content-Type: application/json" -d "$PAYLOAD"

Архитектурно иногда выгоднее, чтобы раннер POSTил во внутренний endpoint шлюза, а уже шлюз вызывал Discord: так проще маскировать внутренние имена, добавлять request_id и единый аудит без раскрытия прямого webhook наружу.

④ Подпись, ограничение частоты и параметры повторов

Прямой вызов Discord опирается на секретность URL и транспорт HTTPS; дополнительно можно задать username и avatar_url, чтобы визуально отделить prod от staging. Если перед Discord стоит ваш REST-слой, добавьте HMAC заголовок от тела запроса и проверку на шлюзе — это не заменит ACL, но усложнит случайные реплеи.

При 429 читайте Retry-After и ждите указанное число секунд; при отсутствии заголовка используйте экспоненциальную задержку с потолком. Для curl разумный базис: --connect-timeout 5 и --max-time 20, до трёх попыток с паузами порядка 2 с, 4 с, 8 с и небольшим случайным сдвигом, чтобы несколько job не бились об один фронт синхронно.

Параметры, которые стоит задокументировать в runbook:

1) целевая major Node для шлюза и дата её согласования с безопасностью;
2) верхняя граница параллельных POST в один канал (агрегация матрицы);
3) политика ротации webhook после инцидента утечки URL.

⑤ Частые ошибки: FAQ по 403, 429 и таймаутам

HTTP 403 Forbidden от discord.com

Webhook удалён или URL скопирован не полностью; интеграция потеряла доступ к каналу после изменения прав. Пересоздайте webhook, обновите секрет во всех окружениях и убедитесь, что канал не архивирован.

HTTP 429 Too Many Requests

Сократите частоту: объединяйте статусы матрицы в одно embed, вводите краткий debounce в шлюзе и строго соблюдайте Retry-After. Не запускайте десятки независимых POST из разных шардов без бюджета.

Таймаут соединения или обрыв TLS

Проверьте прокси, MTU и DNS на пути к discord.com; воспроизведите curl из того же пользователя и окружения, что и у процесса CI. Расхождение NO_PROXY между раннером и Mac-шлюзом — частая причина «flaky» уведомлений.

204 No Content, но визуально «тишина»

Уточните правильный канал и ветку треда; откройте клиент Discord с другого устройства. Иногда сообщение ушло в архивный канал или webhook указывает на тестовый сервер с тем же именем канала в UI.

Итог: выровняйте Node, пройдите onboard, защитите URL Webhook, проверьте канал через curl, затем подключайте embed из CI с дисциплиной повторов. Стабильный удалённый Mac в нужном регионе снижает сетевой разброс и упрощает круглосуточную работу шлюза без сонного ноутбука инженера. Материалы без входа: центр помощи, оформление аренды, другие статьи про OpenClaw.

Шлюз OpenClaw и CI на удалённом Mac

Центр помощи, покупка и главная доступны без входа; продолжите тему в блоге.