Skip to content

Slack

Ongrid интегрируется со Slack в двух различных режимах, настраиваемых на отдельных Settings-панелях:

РежимИспользуйте дляТокены
NotificationПушить сработавшие алерты в каналТолько webhook URL
Socket Mode (IM)Разговаривать с агентом из Slackxapp-… + xoxb-…

Вы можете запускать оба. Они ничем не делятся.

Notification (incoming webhook)

Самая простая интеграция. Slack назначает workspace-specific URL вида https://hooks.slack.com/services/T…/B…/…; Ongrid POST-ит туда payload алерта.

Как выглядит payload

Slack sender рендерит один notify.Message в attachments-формат (выбран поверх Block Kit, потому что он несёт цветной боковой рельс, который операторы читают как severity, и потому что схема — JSON-flat и универсально поддерживается):

json
{
  "text": "[CRITICAL] node-01 swap_high",
  "attachments": [
    {
      "color": "#d92f2f",
      "fallback": "[CRITICAL] node-01 swap_high",
      "title": "node-01 swap_high",
      "text": "swap_in_pages > 1000 for 5m",
      "mrkdwn_in": ["text"],
      "fields": [
        {"title": "Severity", "value": "CRITICAL", "short": true},
        {"title": "Source",   "value": "alert",    "short": true},
        {"title": "Rule",     "value": "swap_high","short": true},
        {"title": "Incident", "value": "#1234",    "short": true},
        {"title": "Device",   "value": "#7",       "short": true},
        {"title": "Dedupe key", "value": "alert:swap_high:device=7", "short": false}
      ],
      "footer": "ongrid",
      "ts": 1717012345
    }
  ]
}

Поле text остаётся заполненным, так что Slack push / email-digest preview показывают полезный one-liner, даже когда клиент срезает attachments.

Severity → цвет

SeverityHex
critical#d92f2f
warning#f2c037
info#36a64f
(unknown)#6f7a87

Закреплённый hex (не sentinel danger / warning Slack), так что оттенок стабилен между версиями Slack-клиента.

Настройка

  1. В Slack: Apps → Incoming Webhooks → Add to Slack, выберите канал.
  2. Скопируйте webhook URL.
  3. В Ongrid: Settings → Channels → New → Provider = slack → вставьте URL в Endpoint.

Поле Secret в форме игнорируется для Slack incoming webhook. URL — это credential; нет отдельной поверхности подписи. Channel builder отбрасывает secret до конструирования NewSlackSender.

Протестируйте канал

Кнопка Test на Settings → Channels отправляет синтетический notify.Message{Severity: "info", Subject: "Ongrid test", …}. Если attachment появляется в целевом канале с зелёным рельсом, канал подключён.

Socket Mode (IM bridge)

Socket Mode — это двусторонняя интеграция. Входящий пользовательский текст доставляется по исходящему WebSocket (публичный ingress не требуется — та же форма, что у Telegram getUpdates), а manager отвечает, используя стандартный Web API (chat.postMessage, chat.update).

Почему Socket Mode, а не Events API

Events API требует, чтобы Slack дотянулся до manager входящим, что означает публичный HTTPS-эндпоинт с валидным сертификатом. Большинство Ongrid- развёртываний — приватные. Socket Mode — поддерживаемая альтернатива, где manager дозванивается наружу — он учитывает HTTPS_PROXY / NO_PROXY и работает за NAT'ами и GFW. Валидатор отвергает mode != stream для Slack:

slack only supports stream mode (Socket Mode)

Требуемые токены

Slack использует два токена для Socket Mode. Они имеют разные scope:

ТокенПрефиксИспользуется для
App-level tokenxapp-…apps.connections.open (получает WebSocket URL).
Bot tokenxoxb-…chat.postMessage, chat.update, все остальные Web API вызовы.

Ongrid хранит их как JSON-объект внутри im_apps.app_secret. Функция ParseSecret валидирует префиксы заранее, так что неправильно вставленный токен всплывает как чистая ошибка, а не как chat.postMessage 401.

json
{
  "app_token": "xapp-1-A0…",
  "bot_token": "xoxb-1234567890-1234567890-…"
}

Требуемые app-scope

В конфиге Slack app:

OAuth & Permissions → Bot Token Scopes

  • app_mentions:read — получать события app_mention.
  • channels:history — получать события message в публичных каналах.
  • groups:history — то же для приватных каналов.
  • im:history — то же для DM.
  • chat:writechat.postMessage / chat.update.

Socket Mode → Enable, затем Basic Information → App-Level Tokens со scope connections:write, чтобы получить токен xapp-….

Event Subscriptions должны быть включены (toggle on), с ботом, подписанным на message.channels, message.groups, message.im, app_mention. Slack отгружает их через Socket Mode так же, как отгружал бы через webhook.

allow_from

Список Slack user ID через запятую, которые могут разговаривать с ботом. User ID начинаются с U (или W для Enterprise guests). Минимум один ID требуется:

slack requires allow_from — at least one Slack user ID (e.g. UABC123, find via Profile → ⋯ → Copy member ID). Without it any workspace member could command a tool-equipped agent

Найдите свой собственный ID в Slack: кликните по аватару → Profile → меню Copy member ID.

Не-allowlisted отправители молча отбрасываются в handleEvent. Бот не отвечает — он не подтверждает, что существует. Поведение зеркалит Telegram allow_from.

Поведение streaming-ответа

Когда allowlisted-пользователь отправляет сообщение:

  1. Bridge вызывает chat.postMessage один раз с placeholder-текстом (Working on it…) и записывает возвращённый ts.
  2. Агент запускается. Каждый streaming-чанк триггерит chat.update на том же (channel, ts).
  3. Терминальный токен флашит финальный текст в то же сообщение.

Slack принимает no-op chat.update (тот же текст) молча — в отличие от Telegram, который возвращает 400. Нет специального swallow на Slack-стороне. См. senderAdapter в stream.go.

Bot-петли, edits и thread ID

  • Сообщения с bot_id != "" отбрасываются — это собственные ответы manager и они создали бы feedback-петлю.
  • Сообщения с любым непустым subtype (message_changed, channel_join, …) отбрасываются.
  • thread_ts сохраняется как ImThread.ImThreadID, так что ответ внутри треда продолжает ту же сессию разговора.
  • Slack <@U…> mention-разметка переписывается в голый @U… токен stripMentions, так что модель видит стабильную ссылку без round-trip к users.info на каждое сообщение.

Настройка

  1. Создайте Slack app: api.slack.com → Create New App → from scratch, выберите workspace.
  2. Включите Socket Mode, сгенерируйте app-level token с connections:write. Скопируйте значение xapp-….
  3. Установите Bot Token Scopes, перечисленные выше.
  4. Установите app в workspace. Скопируйте xoxb-… Bot User OAuth Token.
  5. Включите Event Subscriptions, подпишите бота на события, перечисленные выше.
  6. В Ongrid: Settings → IM bridge → New → Provider = slack → Mode = stream → вставьте app_id (handle бота, например, ongrid-bot), two-token JSON в App secret и как минимум один Slack user ID в allow_from.

Переустановите app после добавления scope

Slack ретроактивно не выдаёт scope уже установленным ботам. Если chat.postMessage возвращает missing_scope после того, как вы добавили chat:write, переустановите app в workspace.

Keep-alive

Stream-цикл пингует каждые 20с (pingInterval). Slack закрывает idle Socket Mode-соединения после ~30с. Ping работает в горутине, так что read-цикл никогда не блокирован за write. Slack- initiated envelope disconnect чисто закрывает, и supervisor переподключается немедленно (без backoff-sleep) со свежим URL apps.connections.open.