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
Центр помощи, покупка и главная доступны без входа; продолжите тему в блоге.