跳转到内容

Slack

OpenCorvus 通过唯一 channel runtime 提供的首选远程 channel。

Slack 是 OpenCorvus 的首选远程 channel,也是 channel-runtime 对接最成熟的平台。托管运行时和独立 channel-runtime package 共用同一个规范适配器。

状态

生产可用README.md 已列为 Available。

快速配置

1. 创建 Slack App

api.slack.com/apps 创建一个 App,必须开启 Socket Mode(代码在 packages/channel-runtime/src/adapters/slack.ts 强制 socketMode: true)。

2. Scopes

Bot Token Scopes(最小集):

Scope用途
chat:write回复消息
chat:write.public在未加入的频道回复(可选)
files:write上传截图 / 附件
im:history / channels:history读取 DM / 频道消息
reactions:writeAck emoji(可选)

App-Level Token Scope:

Scope用途
connections:writeSocket Mode 连接

3. 订阅事件

Event Subscriptions 中订阅:

  • message.channels
  • message.im

.env.example 说明)

4. 环境变量

Terminal window
export SLACK_BOT_TOKEN=xoxb-... # Bot User OAuth Token
export SLACK_APP_TOKEN=xapp-... # App-Level Token
export SLACK_SIGNING_SECRET=... # Signing Secret(Socket Mode 下可选)
# 可选:allowlist,逗号分隔的 Slack User ID
export SLACK_ALLOWED_USER_IDS=U01234567,U09876543

5. 启动

启动唯一 channel runtime:

Terminal window
bun run --cwd packages/channel-runtime dev

会同时启动所有配置了 env 的 channel。

托管产品路径中,在 OpenCorvus 配置 Slack 后启动 opencorvus serve; project bootstrap 会通过托管 channel-runtime supervisor 启动同一个适配器。

Token 模型

三种 token 职责分明:

Token前缀职责
Bot Tokenxoxb-代表 bot 的身份调 API(发消息、上传文件)
App Tokenxapp-建立 Socket Mode WebSocket
Signing Secret无前缀验证 HTTP webhook 签名(Socket Mode 下不用)

消息流

用户在 Slack 频道/DM 发消息
↓ Socket Mode WebSocket
SlackAdapter.app.message() [packages/channel-runtime/src/adapters/slack.ts]
过滤:忽略 bot_id、非支持 subtype、去重
↓ IncomingMessage { platform: "slack", channel: C..., thread_ts: 123.456 }
ChannelRuntime.handleMessage() [packages/channel-runtime/src/core.ts]
SessionCoordinator.get("slack:C...:123")
↓ 新 thread → 新 session;同 thread → 复用
client.session.prompt(sessionId, message)

Thread 语义:Slack 的 thread_ts 唯一标识一条对话;同 thread 内的后续消息会作为 follow-up 注入同一任务循环。

回复流

OpenCorvus 后端 SSE 推事件
handleEvent(event) [packages/channel-runtime/src/core.ts]
message.updated → 文本缓冲 → safeSend()
assistant completed → 结算当前直接 prompt 请求
part.updated(image) → uploadImage() 调 files.uploadV2
permission.asked → 若开启自动回复则直接 reply;否则 @ 用户等人工

回帖时:所有回复都会带上原 thread_ts,保持在同一 thread 内。

权限交互

在 Slack 里审批权限:

允许一次: allow / 同意 / yes
始终允许: always / allow always
拒绝: reject / no / 拒绝

关键字识别由 channel-runtime 在通用层处理(不是 Slack 特有)。

Ack 反应

Slack 适配器会在接收到消息后立刻给原消息加一个 emoji 反应作为”已收到”的回执(避免用户以为消息没送达)。可通过 config 关闭。

语音消息

Slack 的 file_share 子类型(语音消息)会被下载并走已配置的 STT pipeline(STT_PROVIDER 指定的单一提供者),转写文本后当作普通消息处理。

故障排查

问题not_in_channelchannel_not_found 检查:bot 是否被邀请进入该频道;DM 场景是否开启 Messages Tab

问题:消息送达延迟高 检查:是否用了 Socket Mode;HTTP Request URL 模式在国内网络下延迟高。

问题:同一消息被处理两次 检查:去重事实由 OpenCorvus channel ingress 的稳定消息 ID 持久化;若看到重复,检查是否有两个托管或独立 channel-runtime owner 使用了同一组 Slack app 凭据。

问题:权限审批消息无人回复 检查:默认权限模式是 Full access。如果项目显式选择了 Ask me,请从操作员界面审批,或把项目切换为 Full access