Skip to content

Slack ​

Ongrid 集成 Slack 有两种独立模式,在 Settings 的不同面板上配置:

模式用于Token
Notification把触发的告警推到频道只要 webhook URL
Socket Mode(IM)在 Slack 里和 Agent 对话xapp-… + xoxb-…

两者可以同时跑。它们什么状态都不共享。

Notification(incoming webhook) ​

最简单的集成。Slack 分配给工作区一个形如 https://hooks.slack.com/services/T…/B…/… 的 URL;Ongrid 把告警载荷 POST 上去。

载荷长什么样 ​

Slack sender 把单个 notify.Message 渲染成 attachments 格式(之所以不用 Block Kit,是因为 attachments 自带按 severity 染色的侧栏 —— 运维一眼就能看出严重程度,而且 schema 是 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 字段保持填充,这样即使客户端剥掉 attachments,Slack 的推送/邮件摘要预览也能有一条可读的一句话。

Severity → 颜色 ​

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

写死的 hex(不用 Slack 的 danger / warning 哨兵值),保证不同 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 就是凭据,没有独立签名面。通道构造器会在创建 NewSlackSender 之前把 secret 丢掉。

测试通道

Settings → Channels 上的 Test 按钮会发一条合成 notify.Message{Severity: "info", Subject: "Ongrid test", …}。目标频道里出现带绿色侧栏的 attachment,就说明通道接通了。

Socket Mode(IM bridge) ​

Socket Mode 是双向集成。入站用户文本通过出站 WebSocket 传过来(不需要任何公网入口 —— 形态和 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 后面都能跑。校验器拒绝 Slack 上 mode != stream:

slack only supports stream mode (Socket Mode)

必填 token ​

Slack Socket Mode 用两个 token,权限范围不同:

Token前缀用途
App-level tokenxapp-…apps.connections.open(拿 WebSocket URL)。
Bot tokenxoxb-…chat.postMessage、chat.update,以及所有其他 Web API。

Ongrid 把它们以 JSON 对象的形式存到 im_apps.app_secret。ParseSecret 会预先校验前缀,所以贴错 token 会以一个清晰的错误冒出来,而不是后面 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:write —— chat.postMessage / chat.update。

Socket Mode → Enable,然后 Basic Information → App-Level Tokens,scope 选 connections:write,拿到 xapp-… token。

Event Subscriptions 必须开启(toggle on),机器人订阅 message.channels、message.groups、message.im、app_mention。Slack 通过 Socket Mode 推这些事件,方式和 webhook 一致。

allow_from ​

允许跟机器人对话的 Slack user ID 逗号分隔列表。user ID 以 U 开头(Enterprise guest 是 W)。至少一个:

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 处被静默丢弃。机器人不回复 —— 它甚至不会确认自己存在。行为和 Telegram allow_from 一致。

流式回复行为 ​

白名单用户发消息后:

  1. bridge 用占位文本(Working on it…)调一次 chat.postMessage,记下返回的 ts。
  2. Agent 开跑。每个流式 chunk 触发一次对 (channel, ts) 的 chat.update。
  3. 终止 token 把最终文本刷到同一条消息。

Slack 对 no-op 的 chat.update(同文本)会静默接受 —— Telegram 会返 400。所以 Slack 这边不需要特殊吞错。见 stream.go 里的 senderAdapter。

机器人回环、编辑事件、thread ID ​

  • bot_id != "" 的消息直接丢 —— 那是 manager 自己的回复,留下会产生反馈环。
  • subtype 非空(message_changed、channel_join…)的消息也丢。
  • thread_ts 存到 ImThread.ImThreadID,这样 thread 内回复延续同一个会话。
  • Slack 的 <@U…> mention 标记由 stripMentions 改写成纯 @U… token,模型看到稳定的引用,不需要每条消息都 users.info 一次。

配置步骤 ​

  1. 建一个 Slack app:api.slack.com → Create New App → from scratch,选工作区。
  2. 启用 Socket Mode,生成带 connections:write 的 app-level token。复制 xapp-…。
  3. 配上面那些 Bot Token Scopes。
  4. 把 app 安装到工作区。复制 xoxb-…(Bot User OAuth Token)。
  5. 启用 Event Subscriptions,订阅上面列的事件。
  6. 在 Ongrid:Settings → IM bridge → New → Provider = slack → Mode = stream → 粘 app_id(机器人 handle,比如 ongrid-bot)、两 token 的 JSON 粘到 App secret、至少一个 Slack user ID 粘到 allow_from。

加完 scope 之后要重新安装 app

Slack 不会自动把新 scope 追加给已安装机器人。如果加了 chat:write 之后 chat.postMessage 返回 missing_scope,重新装一次 app 到工作区。

保活 ​

stream 循环每 20 秒 ping 一次(pingInterval)。Slack 大约 30 秒后会关掉空闲 Socket Mode 连接。ping 跑在独立 goroutine 里,读循环不会被写阻塞。Slack 主动发的 disconnect envelope 会干净关闭,supervisor 立刻用新的 apps.connections.open URL 重连(不退避)。