Skip to content

Slack

Ongrid は 2 つの異なるモード で Slack と連携し、別々の Settings パネルで設定します:

モード用途トークン
通知発火アラートをチャネルに pushwebhook URL のみ
Socket Mode (IM)Slack からエージェントと対話xapp-… + xoxb-…

両方運用できます。両者は何も共有しません。

通知(incoming webhook)

最もシンプルな統合。Slack は https://hooks.slack.com/services/T…/B…/… 形式のワークスペース固有 URL を割り当て、 Ongrid がそこにアラートペイロードを POST します。

ペイロードの見え方

Slack sender は notify.Message 1 つを attachments 形式 に描画します (Block Kit でなくこれを選んだ理由は、オペレーターが severity として読むカラーサイドレールを運び、 スキーマが JSON 平坦で普遍的にサポートされているから):

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 / メールダイジェストプレビューは クライアントが attachments を剥がしても有用な 1 行を表示します。

Severity → 色

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

ピン留めされた hex(Slack の danger / warning sentinel ではなく)—— Slack クライアントの バージョン間で陰影が安定するように。

セットアップ

  1. Slack で:Apps → Incoming Webhooks → Add to Slack、チャネルを選択。
  2. webhook URL をコピー。
  3. Ongrid で:Settings → Channels → New → Provider = slackEndpoint に URL を貼り付け。

フォームの Secret フィールドは Slack incoming webhook では無視されます。URL が認証情報で、 独立した署名面はありません。チャネルビルダーは NewSlackSender 構築前に secret を落とします。

チャネルをテスト

Settings → Channels の Test ボタンが notify.Message{Severity: "info", Subject: "Ongrid test", …} を合成して送ります。 ターゲットチャネルに緑のレールで attachment が現れれば、チャネルは配線済みです。

Socket Mode(IM bridge)

Socket Mode は 双方向 統合。受信ユーザーテキストはアウトバウンド WebSocket で配信され (パブリック ingress 不要 —— Telegram getUpdates と同形)、manager は標準 Web API (chat.postMessagechat.update)で返信します。

なぜ Socket Mode、Events API ではなく

Events API は Slack が manager にインバウンド到達できる必要があり、つまり有効な証明書を持つ 公開 HTTPS エンドポイントが必要です。多くの Ongrid デプロイはプライベートです。 Socket Mode は manager がダイヤルアウトするサポート対象の代替 —— HTTPS_PROXY / NO_PROXY を尊重し、 NAT や GFW の背後でも動きます。バリデーターは Slack で mode != stream を拒否します:

slack only supports stream mode (Socket Mode)

必要なトークン

Slack は Socket Mode で 2 つのトークンを使用。スコープが異なります:

トークンプレフィックス用途
App レベルトークンxapp-…apps.connections.open(WebSocket URL を取得)。
Bot トークンxoxb-…chat.postMessagechat.update、その他全 Web API 呼び出し。

Ongrid は im_apps.app_secret 内に JSON オブジェクトとして保存します。 ParseSecret 関数がプレフィックスを事前に検証するので、貼り間違いが chat.postMessage 401 ではなくきれいなエラーとして浮上します。

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

必要なアプリスコープ

Slack アプリ設定で:

OAuth & Permissions → Bot Token Scopes

  • app_mentions:read —— app_mention イベント受信。
  • channels:history —— パブリックチャネルで message イベント受信。
  • groups:history —— プライベートチャネルで同上。
  • im:history —— DM で同上。
  • chat:write —— chat.postMessage / chat.update

Socket Mode → Enable、次に Basic Information → App-Level Tokensconnections:write スコープ付きの xapp-… トークンを取得。

Event Subscriptions を有効化(トグル ON)、bot を message.channelsmessage.groupsmessage.imapp_mention にサブスクライブ。 Slack は webhook 経由と同じものを Socket Mode で配信します。

allow_from

bot と会話できる Slack ユーザー ID のカンマ区切りリスト。ユーザー ID は U で始まります (Enterprise ゲストは W)。少なくとも 1 つの 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

非許可リスト送信者は handleEvent で 静かにドロップ。bot は返信しない —— 存在を確認しない。 振る舞いは Telegram allow_from と同様。

ストリーミング返信の振る舞い

許可リストユーザーがメッセージを送ると:

  1. ブリッジが chat.postMessage を 1 回呼び、プレースホルダーテキスト (Working on it…)を投稿し、返ってきた ts を記録。
  2. エージェントが動作。各ストリーミングチャンクが同じ (channel, ts) への chat.update をトリガー。
  3. ターミナルトークンが最終テキストを同じメッセージにフラッシュ。

Slack は no-op chat.update(同じテキスト)を静かに受け入れます —— 400 を返す Telegram と違って。 Slack 側に特別な吞み込みはありません。 stream.gosenderAdapter を参照。

bot ループ、編集、スレッド ID

  • bot_id != "" のメッセージはドロップ —— manager 自身の返信であり、フィードバックループを生むため。
  • 任意の非空 subtypemessage_changedchannel_join、…)のメッセージはドロップ。
  • thread_tsImThread.ImThreadID として保存され、スレッド内の返信は同じ会話セッションを継続。
  • Slack の <@U…> メンション markup は stripMentions でベアな @U… トークンに書き換え —— モデルが安定した参照を見るように、メッセージごとに users.info ラウンドトリップしません。

セットアップ

  1. Slack アプリ作成:api.slack.com → Create New App → from scratch、ワークスペース選択。
  2. Socket Mode を有効化、connections:write 付き app レベルトークン生成。 xapp-… 値をコピー。
  3. 上記の Bot Token Scopes を設定。
  4. ワークスペースにアプリをインストール。xoxb-… Bot User OAuth Token をコピー。
  5. Event Subscriptions を有効化、bot を上記イベントにサブスクライブ。
  6. Ongrid で:Settings → IM bridge → New → Provider = slack → Mode = stream → app_id(bot のハンドル、例 ongrid-bot)、二トークン JSON を App secret に、 少なくとも 1 つの Slack ユーザー ID を allow_from に貼り付け。

スコープ追加後はアプリを再インストール

Slack は既インストール bot にスコープを遡及付与しません。chat:write を追加した後に chat.postMessagemissing_scope を返したら、ワークスペースにアプリを再インストール。

keep-alive

stream ループは 20 秒ごとに ping (pingInterval)。 Slack はアイドル Socket Mode 接続を約 30 秒で閉じます。ping は goroutine で動くので、 読み取りループが書き込み待ちでブロックされません。Slack 起動の disconnect 封筒が クリーンにクローズし、スーパーバイザーが即時再接続(バックオフ sleep なし) 新しい apps.connections.open URL で。