---
read_when:
    - 設定 Slack 或偵錯 Slack 通訊端/HTTP 模式
summary: Slack 設定與執行階段行為（通訊端模式 + HTTP 請求 URL）
title: Slack
x-i18n:
    generated_at: "2026-05-11T20:21:34Z"
    model: gpt-5.5
    provider: openai
    source_hash: 34e740fd5cb0ca936edce1843316cde17570d77778bdf4fc761cad77c51ee9cf
    source_path: channels/slack.md
    workflow: 16
---

可透過 Slack 應用程式整合，在 DM 和頻道中達到生產環境可用。預設模式為 Socket Mode；也支援 HTTP Request URLs。

<CardGroup cols={3}>
  <Card title="Pairing" icon="link" href="/zh-TW/channels/pairing">
    Slack DM 預設使用配對模式。
  </Card>
  <Card title="Slash commands" icon="terminal" href="/zh-TW/tools/slash-commands">
    原生命令行為與命令目錄。
  </Card>
  <Card title="Channel troubleshooting" icon="wrench" href="/zh-TW/channels/troubleshooting">
    跨頻道診斷與修復手冊。
  </Card>
</CardGroup>

## 選擇 Socket Mode 或 HTTP Request URLs

兩種傳輸方式都已可用於生產環境，並且在訊息、slash commands、App Home 和互動功能上達到功能一致。請依部署型態選擇，而不是依功能選擇。

| 考量                         | Socket Mode（預設）                                                                 | HTTP Request URLs                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| 公開 Gateway URL             | 不需要                                                                               | 需要（DNS、TLS、反向代理或通道）                                                                  |
| 輸出網路                     | 必須能連到 `wss-primary.slack.com` 的輸出 WSS                                         | 無輸出 WS；僅限輸入 HTTPS                                                                         |
| 需要的 Token                 | Bot token (`xoxb-...`) + 具備 `connections:write` 的 App-Level Token (`xapp-...`)     | Bot token (`xoxb-...`) + Signing Secret                                                           |
| 開發筆電 / 位於防火牆後方    | 可直接運作                                                                           | 需要公開通道（ngrok、Cloudflare Tunnel、Tailscale Funnel）或預備環境 Gateway                      |
| 水平擴充                     | 每個 app 每台主機一個 Socket Mode 工作階段；多個 Gateways 需要個別 Slack apps        | 無狀態 POST 處理常式；多個 Gateway 複本可在負載平衡器後共用同一個 app                            |
| 單一 Gateway 上的多帳號      | 支援；每個帳號會開啟自己的 WS                                                        | 支援；每個帳號都需要唯一的 `webhookPath`（預設 `/slack/events`），避免註冊衝突                    |
| Slash command 傳輸           | 透過 WS 連線遞送；會忽略 `slash_commands[].url`                                       | Slack 會 POST 至 `slash_commands[].url`；此欄位為命令分派的必要欄位                               |
| 請求簽署                     | 不使用（驗證使用 App-Level Token）                                                   | Slack 會簽署每個請求；OpenClaw 使用 `signingSecret` 驗證                                         |
| 連線中斷復原                 | Slack SDK 會自動重新連線；會套用 gateway 的 pong-timeout 傳輸調校                    | 沒有會中斷的持久連線；重試由 Slack 逐請求處理                                                     |

<Note>
  **選擇 Socket Mode**：適用於單一 Gateway 主機、開發筆電，以及可連到 `*.slack.com` 輸出但無法接受輸入 HTTPS 的內部部署網路。

**選擇 HTTP Request URLs**：適用於在負載平衡器後方執行多個 Gateway 複本、輸出 WSS 被封鎖但允許輸入 HTTPS，或你已經在反向代理終止 Slack Webhook 的情境。
</Note>

## 快速設定

<Tabs>
  <Tab title="Socket Mode (default)">
    <Steps>
      <Step title="Create a new Slack app">
        開啟 [api.slack.com/apps](https://api.slack.com/apps/new) → **Create New App** → **From a manifest** → 選取你的工作區 → 貼上下方其中一份 manifest → **Next** → **Create**。

        <CodeGroup>

```json Recommended
{
  "display_information": {
    "name": "OpenClaw",
    "description": "Slack connector for OpenClaw"
  },
  "features": {
    "bot_user": { "display_name": "OpenClaw", "always_online": true },
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "slash_commands": [
      {
        "command": "/openclaw",
        "description": "Send a message to OpenClaw",
        "should_escape": false
      }
    ]
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "emoji:read",
        "files:read",
        "files:write",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "mpim:history",
        "mpim:read",
        "mpim:write",
        "pins:read",
        "pins:write",
        "reactions:read",
        "reactions:write",
        "usergroups:read",
        "users:read"
      ]
    }
  },
  "settings": {
    "socket_mode_enabled": true,
    "event_subscriptions": {
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "channel_rename",
        "member_joined_channel",
        "member_left_channel",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim",
        "pin_added",
        "pin_removed",
        "reaction_added",
        "reaction_removed"
      ]
    }
  }
}
```

```json Minimal
{
  "display_information": {
    "name": "OpenClaw",
    "description": "Slack connector for OpenClaw"
  },
  "features": {
    "bot_user": { "display_name": "OpenClaw", "always_online": true },
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "slash_commands": [
      {
        "command": "/openclaw",
        "description": "Send a message to OpenClaw",
        "should_escape": false
      }
    ]
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "users:read"
      ]
    }
  },
  "settings": {
    "socket_mode_enabled": true,
    "event_subscriptions": {
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "message.channels",
        "message.groups",
        "message.im"
      ]
    }
  }
}
```

        </CodeGroup>

        <Note>
          **Recommended** 符合內建 Slack Plugin 的完整功能集：App Home、slash commands、檔案、回應、釘選、群組 DM，以及 emoji/usergroup 讀取。當工作區政策限制 scopes 時，請選擇 **Minimal**：它涵蓋 DM、頻道/群組歷史記錄、提及和 slash commands，但移除檔案、回應、釘選、群組 DM (`mpim:*`)、`emoji:read` 和 `usergroups:read`。如需每個 scope 的理由，以及額外 slash commands 等可加選項，請參閱 [Manifest 與 scope 檢查清單](#manifest-and-scope-checklist)。
        </Note>

        Slack 建立 app 後：

        - **Basic Information → App-Level Tokens → Generate Token and Scopes**：新增 `connections:write`、儲存，並複製 `xapp-...` 值。
        - **Install App → Install to Workspace**：複製 `xoxb-...` Bot User OAuth Token。

      </Step>

      <Step title="Configure OpenClaw">

        建議的 SecretRef 設定：

```bash
export SLACK_APP_TOKEN=xapp-...
export SLACK_BOT_TOKEN=xoxb-...
cat > slack.socket.patch.json5 <<'JSON5'
{
  channels: {
    slack: {
      enabled: true,
      mode: "socket",
      appToken: { source: "env", provider: "default", id: "SLACK_APP_TOKEN" },
      botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" },
    },
  },
}
JSON5
openclaw config patch --file ./slack.socket.patch.json5 --dry-run
openclaw config patch --file ./slack.socket.patch.json5
```

        Env 備援（僅限預設帳號）：

```bash
SLACK_APP_TOKEN=xapp-...
SLACK_BOT_TOKEN=xoxb-...
```

      </Step>

      <Step title="Start gateway">

```bash
openclaw gateway
```

      </Step>
    </Steps>

  </Tab>

  <Tab title="HTTP Request URLs">
    <Steps>
      <Step title="Create a new Slack app">
        開啟 [api.slack.com/apps](https://api.slack.com/apps/new) → **Create New App** → **From a manifest** → 選取你的工作區 → 貼上下方其中一份 manifest → 將 `https://gateway-host.example.com/slack/events` 替換為你的公開 Gateway URL → **Next** → **Create**。

        <CodeGroup>

```json Recommended
{
  "display_information": {
    "name": "OpenClaw",
    "description": "Slack connector for OpenClaw"
  },
  "features": {
    "bot_user": { "display_name": "OpenClaw", "always_online": true },
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "slash_commands": [
      {
        "command": "/openclaw",
        "description": "Send a message to OpenClaw",
        "should_escape": false,
        "url": "https://gateway-host.example.com/slack/events"
      }
    ]
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "emoji:read",
        "files:read",
        "files:write",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "mpim:history",
        "mpim:read",
        "mpim:write",
        "pins:read",
        "pins:write",
        "reactions:read",
        "reactions:write",
        "usergroups:read",
        "users:read"
      ]
    }
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "https://gateway-host.example.com/slack/events",
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "channel_rename",
        "member_joined_channel",
        "member_left_channel",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim",
        "pin_added",
        "pin_removed",
        "reaction_added",
        "reaction_removed"
      ]
    },
    "interactivity": {
      "is_enabled": true,
      "request_url": "https://gateway-host.example.com/slack/events",
      "message_menu_options_url": "https://gateway-host.example.com/slack/events"
    }
  }
}
```

```json Minimal
{
  "display_information": {
    "name": "OpenClaw",
    "description": "Slack connector for OpenClaw"
  },
  "features": {
    "bot_user": { "display_name": "OpenClaw", "always_online": true },
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "slash_commands": [
      {
        "command": "/openclaw",
        "description": "Send a message to OpenClaw",
        "should_escape": false,
        "url": "https://gateway-host.example.com/slack/events"
      }
    ]
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "users:read"
      ]
    }
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "https://gateway-host.example.com/slack/events",
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "message.channels",
        "message.groups",
        "message.im"
      ]
    },
    "interactivity": {
      "is_enabled": true,
      "request_url": "https://gateway-host.example.com/slack/events",
      "message_menu_options_url": "https://gateway-host.example.com/slack/events"
    }
  }
}
```

        </CodeGroup>

        <Note>
          **建議** 會符合內建 Slack Plugin 的完整功能集；**最小** 會移除檔案、表情反應、釘選、群組私訊（`mpim:*`）、`emoji:read` 和 `usergroups:read`，適用於限制較嚴格的工作區。各 scope 的理由請參閱[資訊清單與 scope 檢查清單](#manifest-and-scope-checklist)。
        </Note>

        <Info>
          三個 URL 欄位（`slash_commands[].url`、`event_subscriptions.request_url`，以及 `interactivity.request_url` / `message_menu_options_url`）都指向同一個 OpenClaw 端點。Slack 的資訊清單結構描述要求它們分別命名，但 OpenClaw 會依 payload 類型路由，因此單一 `webhookPath`（預設 `/slack/events`）就足夠。沒有 `slash_commands[].url` 的斜線命令會在 HTTP 模式中靜默無動作。
        </Info>

        Slack 建立應用程式後：

        - **Basic Information → App Credentials**：複製 **Signing Secret** 以進行請求驗證。
        - **Install App → Install to Workspace**：複製 `xoxb-...` Bot User OAuth Token。

      </Step>

      <Step title="Configure OpenClaw">

        建議的 SecretRef 設定：

```bash
export SLACK_BOT_TOKEN=xoxb-...
export SLACK_SIGNING_SECRET=...
cat > slack.http.patch.json5 <<'JSON5'
{
  channels: {
    slack: {
      enabled: true,
      mode: "http",
      botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" },
      signingSecret: { source: "env", provider: "default", id: "SLACK_SIGNING_SECRET" },
      webhookPath: "/slack/events",
    },
  },
}
JSON5
openclaw config patch --file ./slack.http.patch.json5 --dry-run
openclaw config patch --file ./slack.http.patch.json5
```

        <Note>
        對多帳號 HTTP 使用唯一的 webhook 路徑

        為每個帳號指定不同的 `webhookPath`（預設 `/slack/events`），讓註冊不會互相衝突。
        </Note>

      </Step>

      <Step title="Start gateway">

```bash
openclaw gateway
```

      </Step>
    </Steps>

  </Tab>
</Tabs>

## Socket Mode 傳輸調校

OpenClaw 預設會將 Socket Mode 的 Slack SDK 用戶端 pong 逾時設為 15 秒。只有在需要針對工作區或主機做特定調校時，才覆寫傳輸設定：

```json5
{
  channels: {
    slack: {
      mode: "socket",
      socketMode: {
        clientPingTimeout: 20000,
        serverPingTimeout: 30000,
        pingPongLoggingEnabled: false,
      },
    },
  },
}
```

只有在 Socket Mode 工作區記錄 Slack websocket pong/server-ping 逾時，或執行於已知事件迴圈飢餓的主機上時，才使用此設定。`clientPingTimeout` 是 SDK 傳送用戶端 ping 後等待 pong 的時間；`serverPingTimeout` 是等待 Slack 伺服器 ping 的時間。應用程式訊息和事件仍屬於應用程式狀態，不是傳輸存活訊號。

## 資訊清單與 scope 檢查清單

基礎 Slack 應用程式資訊清單對 Socket Mode 和 HTTP Request URLs 都相同。只有 `settings` 區塊（以及斜線命令 `url`）不同。

基礎資訊清單（Socket Mode 預設）：

```json
{
  "display_information": {
    "name": "OpenClaw",
    "description": "Slack connector for OpenClaw"
  },
  "features": {
    "bot_user": { "display_name": "OpenClaw", "always_online": true },
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "slash_commands": [
      {
        "command": "/openclaw",
        "description": "Send a message to OpenClaw",
        "should_escape": false
      }
    ]
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "emoji:read",
        "files:read",
        "files:write",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "mpim:history",
        "mpim:read",
        "mpim:write",
        "pins:read",
        "pins:write",
        "reactions:read",
        "reactions:write",
        "usergroups:read",
        "users:read"
      ]
    }
  },
  "settings": {
    "socket_mode_enabled": true,
    "event_subscriptions": {
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "channel_rename",
        "member_joined_channel",
        "member_left_channel",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim",
        "pin_added",
        "pin_removed",
        "reaction_added",
        "reaction_removed"
      ]
    }
  }
}
```

對於 **HTTP Request URLs 模式**，請以 HTTP 變體取代 `settings`，並將 `url` 加到每個斜線命令。需要公開 URL：

```json
{
  "features": {
    "slash_commands": [
      {
        "command": "/openclaw",
        "description": "Send a message to OpenClaw",
        "should_escape": false,
        "url": "https://gateway-host.example.com/slack/events"
      }
    ]
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "https://gateway-host.example.com/slack/events",
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "channel_rename",
        "member_joined_channel",
        "member_left_channel",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim",
        "pin_added",
        "pin_removed",
        "reaction_added",
        "reaction_removed"
      ]
    },
    "interactivity": {
      "is_enabled": true,
      "request_url": "https://gateway-host.example.com/slack/events",
      "message_menu_options_url": "https://gateway-host.example.com/slack/events"
    }
  }
}
```

### 其他資訊清單設定

呈現可延伸上述預設值的不同功能。

預設資訊清單會啟用 Slack App Home 的 **Home** 分頁，並訂閱 `app_home_opened`。當工作區成員開啟 Home 分頁時，OpenClaw 會使用 `views.publish` 發佈安全的預設 Home 檢視；不會包含對話 payload 或私密設定。**Messages** 分頁仍會為 Slack 私訊啟用。

<AccordionGroup>
  <Accordion title="Optional native slash commands">

    可使用多個[原生斜線命令](#commands-and-slash-behavior)取代單一已設定命令，但有以下細節：

    - 使用 `/agentstatus` 而不是 `/status`，因為 `/status` 命令是保留命令。
    - 一次最多只能提供 25 個斜線命令。

    將現有的 `features.slash_commands` 區段取代為[可用命令](/zh-TW/tools/slash-commands#command-list)的子集：

    <Tabs>
      <Tab title="Socket Mode (default)">

```json
{
  "slash_commands": [
    {
      "command": "/new",
      "description": "Start a new session",
      "usage_hint": "[model]"
    },
    {
      "command": "/reset",
      "description": "Reset the current session"
    },
    {
      "command": "/compact",
      "description": "Compact the session context",
      "usage_hint": "[instructions]"
    },
    {
      "command": "/stop",
      "description": "Stop the current run"
    },
    {
      "command": "/session",
      "description": "Manage thread-binding expiry",
      "usage_hint": "idle <duration|off> or max-age <duration|off>"
    },
    {
      "command": "/think",
      "description": "Set the thinking level",
      "usage_hint": "<level>"
    },
    {
      "command": "/verbose",
      "description": "Toggle verbose output",
      "usage_hint": "on|off|full"
    },
    {
      "command": "/fast",
      "description": "Show or set fast mode",
      "usage_hint": "[status|on|off]"
    },
    {
      "command": "/reasoning",
      "description": "Toggle reasoning visibility",
      "usage_hint": "[on|off|stream]"
    },
    {
      "command": "/elevated",
      "description": "Toggle elevated mode",
      "usage_hint": "[on|off|ask|full]"
    },
    {
      "command": "/exec",
      "description": "Show or set exec defaults",
      "usage_hint": "host=<auto|sandbox|gateway|node> security=<deny|allowlist|full> ask=<off|on-miss|always> node=<id>"
    },
    {
      "command": "/model",
      "description": "Show or set the model",
      "usage_hint": "[name|#|status]"
    },
    {
      "command": "/models",
      "description": "List providers/models",
      "usage_hint": "[provider] [page] [limit=<n>|size=<n>|all]"
    },
    {
      "command": "/help",
      "description": "Show the short help summary"
    },
    {
      "command": "/commands",
      "description": "Show the generated command catalog"
    },
    {
      "command": "/tools",
      "description": "Show what the current agent can use right now",
      "usage_hint": "[compact|verbose]"
    },
    {
      "command": "/agentstatus",
      "description": "Show runtime status, including provider usage/quota when available"
    },
    {
      "command": "/tasks",
      "description": "List active/recent background tasks for the current session"
    },
    {
      "command": "/context",
      "description": "Explain how context is assembled",
      "usage_hint": "[list|detail|json]"
    },
    {
      "command": "/whoami",
      "description": "Show your sender identity"
    },
    {
      "command": "/skill",
      "description": "Run a skill by name",
      "usage_hint": "<name> [input]"
    },
    {
      "command": "/btw",
      "description": "Ask a side question without changing session context",
      "usage_hint": "<question>"
    },
    {
      "command": "/side",
      "description": "Ask a side question without changing session context",
      "usage_hint": "<question>"
    },
    {
      "command": "/usage",
      "description": "Control the usage footer or show cost summary",
      "usage_hint": "off|tokens|full|cost"
    }
  ]
}
```

      </Tab>
      <Tab title="HTTP Request URLs">
        使用與上方 Socket Mode 相同的 `slash_commands` 清單，並將 `"url": "https://gateway-host.example.com/slack/events"` 加到每個項目。例如：

```json
{
  "slash_commands": [
    {
      "command": "/new",
      "description": "Start a new session",
      "usage_hint": "[model]",
      "url": "https://gateway-host.example.com/slack/events"
    },
    {
      "command": "/help",
      "description": "Show the short help summary",
      "url": "https://gateway-host.example.com/slack/events"
    }
  ]
}
```

        在清單中的每個命令都重複該 `url` 值。

      </Tab>
    </Tabs>

  </Accordion>
  <Accordion title="選用的作者身分範圍（寫入操作）">
    如果你希望外送訊息使用作用中代理程式身分（自訂使用者名稱與圖示），而不是預設的 Slack app 身分，請加入 `chat:write.customize` bot 範圍。

    如果你使用 emoji 圖示，Slack 會預期採用 `:emoji_name:` 語法。

  </Accordion>
  <Accordion title="選用的使用者權杖範圍（讀取操作）">
    如果你設定 `channels.slack.userToken`，典型的讀取範圍為：

    - `channels:history`, `groups:history`, `im:history`, `mpim:history`
    - `channels:read`, `groups:read`, `im:read`, `mpim:read`
    - `users:read`
    - `reactions:read`
    - `pins:read`
    - `emoji:read`
    - `search:read`（如果你依賴 Slack 搜尋讀取）

  </Accordion>
</AccordionGroup>

## 權杖模型

- `botToken` + `appToken` 是 Socket Mode 的必要項目。
- HTTP 模式需要 `botToken` + `signingSecret`。
- `botToken`、`appToken`、`signingSecret` 和 `userToken` 可接受明文
  字串或 SecretRef 物件。
- 設定權杖會覆寫 env 後援。
- `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` env 後援只套用至預設帳戶。
- `userToken` (`xoxp-...`) 僅能透過設定提供（沒有 env 後援），且預設為唯讀行為（`userTokenReadOnly: true`）。

狀態快照行為：

- Slack 帳戶檢查會追蹤每個憑證的 `*Source` 和 `*Status`
  欄位（`botToken`、`appToken`、`signingSecret`、`userToken`）。
- 狀態為 `available`、`configured_unavailable` 或 `missing`。
- `configured_unavailable` 表示帳戶已透過 SecretRef
  或其他非內嵌秘密來源設定，但目前的命令/執行階段路徑
  無法解析實際值。
- 在 HTTP 模式中，會包含 `signingSecretStatus`；在 Socket Mode 中，
  必要配對是 `botTokenStatus` + `appTokenStatus`。

<Tip>
對於動作/目錄讀取，設定使用者權杖時可優先使用。對於寫入，bot 權杖仍為優先選項；只有在 `userTokenReadOnly: false` 且 bot 權杖不可用時，才允許使用者權杖寫入。
</Tip>

## 動作與門檻

Slack 動作由 `channels.slack.actions.*` 控制。

目前 Slack 工具中可用的動作群組：

| 群組      | 預設 |
| ---------- | ------- |
| 訊息   | 已啟用 |
| 回應  | 已啟用 |
| 釘選       | 已啟用 |
| 成員資訊 | 已啟用 |
| emoji 清單  | 已啟用 |

目前 Slack 訊息動作包含 `send`、`upload-file`、`download-file`、`read`、`edit`、`delete`、`pin`、`unpin`、`list-pins`、`member-info` 和 `emoji-list`。`download-file` 接受入站檔案預留位置中顯示的 Slack 檔案 ID，並針對圖片回傳圖片預覽，或針對其他檔案類型回傳本機檔案中繼資料。

## 存取控制與路由

<Tabs>
  <Tab title="DM 政策">
    `channels.slack.dmPolicy` 控制 DM 存取。`channels.slack.allowFrom` 是正式的 DM 允許清單。

    - `pairing`（預設）
    - `allowlist`
    - `open`（需要 `channels.slack.allowFrom` 包含 `"*"`）
    - `disabled`

    DM 旗標：

    - `dm.enabled`（預設為 true）
    - `channels.slack.allowFrom`
    - `dm.allowFrom`（舊版）
    - `dm.groupEnabled`（群組 DM 預設為 false）
    - `dm.groupChannels`（選用 MPIM 允許清單）

    多帳戶優先順序：

    - `channels.slack.accounts.default.allowFrom` 只套用至 `default` 帳戶。
    - 已命名帳戶在自身 `allowFrom` 未設定時，會繼承 `channels.slack.allowFrom`。
    - 已命名帳戶不會繼承 `channels.slack.accounts.default.allowFrom`。

    舊版 `channels.slack.dm.policy` 和 `channels.slack.dm.allowFrom` 仍會為了相容性而讀取。`openclaw doctor --fix` 在可不改變存取權的情況下，會將它們遷移至 `dmPolicy` 和 `allowFrom`。

    DM 中的配對使用 `openclaw pairing approve slack <code>`。

  </Tab>

  <Tab title="頻道政策">
    `channels.slack.groupPolicy` 控制頻道處理：

    - `open`
    - `allowlist`
    - `disabled`

    頻道允許清單位於 `channels.slack.channels` 下，且**必須使用穩定的 Slack 頻道 ID**（例如 `C12345678`）作為設定鍵。

    執行階段注意事項：如果完全缺少 `channels.slack`（僅 env 設定），執行階段會後援為 `groupPolicy="allowlist"` 並記錄警告（即使已設定 `channels.defaults.groupPolicy`）。

    名稱/ID 解析：

    - 頻道允許清單項目和 DM 允許清單項目會在啟動時，在權杖存取允許的情況下解析
    - 無法解析的頻道名稱項目會保留其設定，但預設會在路由中忽略
    - 入站授權和頻道路由預設以 ID 優先；直接的使用者名稱/slug 比對需要 `channels.slack.dangerouslyAllowNameMatching: true`

    <Warning>
    以名稱為基礎的鍵（`#channel-name` 或 `channel-name`）在 `groupPolicy: "allowlist"` 下**不會**符合。頻道查詢預設以 ID 優先，因此以名稱為基礎的鍵永遠無法成功路由，該頻道中的所有訊息都會被靜默封鎖。這不同於 `groupPolicy: "open"`；在該模式下，路由不需要頻道鍵，而以名稱為基礎的鍵看起來會正常運作。

    請一律使用 Slack 頻道 ID 作為鍵。若要尋找它：在 Slack 中以右鍵點選頻道 → **複製連結** — ID（`C...`）會出現在 URL 末尾。

    正確：

    ```json5
    {
      channels: {
        slack: {
          groupPolicy: "allowlist",
          channels: {
            C12345678: { allow: true, requireMention: true },
          },
        },
      },
    }
    ```

    不正確（在 `groupPolicy: "allowlist"` 下會被靜默封鎖）：

    ```json5
    {
      channels: {
        slack: {
          groupPolicy: "allowlist",
          channels: {
            "#eng-my-channel": { allow: true, requireMention: true },
          },
        },
      },
    }
    ```
    </Warning>

  </Tab>

  <Tab title="提及與頻道使用者">
    頻道訊息預設受提及門檻控管。

    提及來源：

    - 明確的 app 提及（`<@botId>`）
    - 當 bot 使用者是該使用者群組成員時的 Slack 使用者群組提及（`<!subteam^S...>`）；需要 `usergroups:read`
    - 提及 regex 模式（`agents.list[].groupChat.mentionPatterns`，後援為 `messages.groupChat.mentionPatterns`）
    - 隱含的回覆 bot 執行緒行為（當 `thread.requireExplicitMention` 為 `true` 時停用）

    每頻道控制（`channels.slack.channels.<id>`；名稱只能透過啟動解析或 `dangerouslyAllowNameMatching` 使用）：

    - `requireMention`
    - `users`（允許清單）
    - `allowBots`
    - `skills`
    - `systemPrompt`
    - `tools`, `toolsBySender`
    - `toolsBySender` 鍵格式：`channel:`、`id:`、`e164:`、`username:`、`name:`，或 `"*"` 萬用字元
      （舊版未加前綴的鍵仍只會對應至 `id:`）

    對於頻道和私人頻道，`allowBots` 採保守策略：只有在傳送 bot 明確列於該聊天室的 `users` 允許清單中，或目前至少有一個來自 `channels.slack.allowFrom` 的明確 Slack 擁有者 ID 是聊天室成員時，才會接受由 bot 撰寫的聊天室訊息。萬用字元和顯示名稱擁有者項目不符合擁有者存在條件。擁有者存在使用 Slack `conversations.members`；請確保 app 具備符合該聊天室類型的讀取範圍（公開頻道為 `channels:read`，私人頻道為 `groups:read`）。如果成員查詢失敗，OpenClaw 會丟棄由 bot 撰寫的聊天室訊息。

  </Tab>
</Tabs>

## 執行緒、工作階段與回覆標籤

- DM 路由為 `direct`；頻道路由為 `channel`；MPIM 路由為 `group`。
- Slack 路由繫結接受原始對等 ID，以及 Slack 目標形式，例如 `channel:C12345678`、`user:U12345678` 和 `<@U12345678>`。
- 使用預設 `session.dmScope=main` 時，Slack DM 會收斂至代理程式主工作階段。
- 頻道工作階段：`agent:<agentId>:slack:channel:<channelId>`。
- 適用時，執行緒回覆可建立執行緒工作階段後綴（`:thread:<threadTs>`）。
- 在 OpenClaw 不需要明確提及即可處理頂層訊息的頻道中，非 `off` 的 `replyToMode` 會將每個已處理的根訊息路由至 `agent:<agentId>:slack:channel:<channelId>:thread:<rootTs>`，讓可見的 Slack 執行緒從第一輪開始對應到一個 OpenClaw 工作階段。
- `channels.slack.thread.historyScope` 預設為 `thread`；`thread.inheritParent` 預設為 `false`。
- `channels.slack.thread.initialHistoryLimit` 控制新執行緒工作階段啟動時，要擷取多少既有執行緒訊息（預設 `20`；設為 `0` 可停用）。
- `channels.slack.thread.requireExplicitMention`（預設 `false`）：當為 `true` 時，會抑制隱含執行緒提及，因此即使 bot 已參與該執行緒，bot 也只會回應執行緒內明確的 `@bot` 提及。若沒有此設定，bot 已參與執行緒中的回覆會略過 `requireMention` 門檻。

回覆執行緒控制：

- `channels.slack.replyToMode`: `off|first|all|batched`（預設 `off`）
- `channels.slack.replyToModeByChatType`: 針對每個 `direct|group|channel`
- 直接聊天的舊版後援：`channels.slack.dm.replyToMode`

支援手動回覆標籤：

- `[[reply_to_current]]`
- `[[reply_to:<id>]]`

若要從 `message` 工具明確傳送 Slack 執行緒回覆，請搭配 `action: "send"` 與 `threadId` 或 `replyTo` 設定 `replyBroadcast: true`，要求 Slack 也將執行緒回覆廣播到上層頻道。這會對應至 Slack 的 `chat.postMessage` `reply_broadcast` 旗標，且僅支援文字或 Block Kit 傳送，不支援媒體上傳。

當 `message` 工具呼叫在 Slack 執行緒內執行且目標為同一個頻道時，OpenClaw 通常會根據 `replyToMode` 繼承目前的 Slack 執行緒。在 `action: "send"` 或 `action: "upload-file"` 上設定 `topLevel: true`，可強制傳送新的上層頻道訊息。`threadId: null` 也會被接受為相同的頂層退出選項。

<Note>
`replyToMode="off"` 會停用 Slack 中的**所有**回覆執行緒，包括明確的 `[[reply_to_*]]` 標籤。這不同於 Telegram；在 Telegram 中，明確標籤在 `"off"` 模式下仍會被遵循。Slack 執行緒會從頻道中隱藏訊息，而 Telegram 回覆會保持行內可見。
</Note>

## 確認回應

`ackReaction` 會在 OpenClaw 處理入站訊息時傳送確認 emoji。

解析順序：

- `channels.slack.accounts.<accountId>.ackReaction`
- `channels.slack.ackReaction`
- `messages.ackReaction`
- 代理程式身分 emoji 後援（`agents.list[].identity.emoji`，否則為 "👀"）

注意事項：

- Slack 預期使用短碼（例如 `"eyes"`）。
- 使用 `""` 可停用 Slack 帳戶或全域的回應。

## 文字串流

`channels.slack.streaming` 控制即時預覽行為：

- `off`：停用即時預覽串流。
- `partial`（預設）：以最新的部分輸出取代預覽文字。
- `block`：附加分塊預覽更新。
- `progress`：產生期間顯示進度狀態文字，然後傳送最終文字。
- `streaming.preview.toolProgress`：草稿預覽啟用時，將工具/進度更新路由到同一則已編輯預覽訊息（預設：`true`）。設為 `false` 可保留個別工具/進度訊息。
- `streaming.preview.commandText` / `streaming.progress.commandText`：設為 `status` 可在隱藏原始 command/exec 文字的同時，保留精簡工具進度行（預設：`raw`）。

隱藏原始 command/exec 文字，同時保留精簡進度行：

```json
{
  "channels": {
    "slack": {
      "streaming": {
        "mode": "progress",
        "progress": {
          "toolProgress": true,
          "commandText": "status"
        }
      }
    }
  }
}
```

當 `channels.slack.streaming.mode` 為 `partial` 時，`channels.slack.streaming.nativeTransport` 會控制 Slack 原生文字串流（預設：`true`）。

- 必須有可用的回覆執行緒，原生文字串流和 Slack assistant 執行緒狀態才會顯示。執行緒選擇仍會遵循 `replyToMode`。
- 當原生串流不可用，或沒有回覆執行緒時，頻道、群組聊天和頂層 DM 根仍可使用一般草稿預覽。
- 頂層 Slack DM 預設保持不進入執行緒，因此不會顯示 Slack 執行緒樣式的原生串流/狀態預覽；OpenClaw 會改為在 DM 中發佈並編輯草稿預覽。
- 媒體和非文字承載內容會回退到一般傳遞。
- 媒體/錯誤最終內容會取消待處理的預覽編輯；符合條件的文字/區塊最終內容只會在能就地編輯預覽時才會清空送出。
- 如果串流在回覆中途失敗，OpenClaw 會對剩餘承載內容回退到一般傳遞。

使用草稿預覽，而不是 Slack 原生文字串流：

```json5
{
  channels: {
    slack: {
      streaming: {
        mode: "partial",
        nativeTransport: false,
      },
    },
  },
}
```

舊版鍵：

- `channels.slack.streamMode` (`replace | status_final | append`) 是 `channels.slack.streaming.mode` 的舊版執行階段別名。
- 布林值 `channels.slack.streaming` 是 `channels.slack.streaming.mode` 和 `channels.slack.streaming.nativeTransport` 的舊版執行階段別名。
- 舊版 `channels.slack.nativeStreaming` 是 `channels.slack.streaming.nativeTransport` 的執行階段別名。
- 執行 `openclaw doctor --fix`，將已保存的 Slack 串流設定重寫為標準鍵。

## 輸入中反應備援

`typingReaction` 會在 OpenClaw 處理回覆時，向傳入的 Slack 訊息加入暫時反應，並在執行完成時移除。這在執行緒回覆之外最有用，因為執行緒回覆會使用預設的「正在輸入...」狀態指示器。

解析順序：

- `channels.slack.accounts.<accountId>.typingReaction`
- `channels.slack.typingReaction`

注意事項：

- Slack 預期使用短代碼（例如 `"hourglass_flowing_sand"`）。
- 反應採盡力而為，並會在回覆或失敗路徑完成後自動嘗試清理。

## 媒體、分塊與傳遞

<AccordionGroup>
  <Accordion title="Inbound attachments">
    Slack 檔案附件會從 Slack 託管的私人 URL 下載（權杖驗證請求流程），並在擷取成功且大小限制允許時寫入媒體儲存區。檔案預留位置包含 Slack `fileId`，因此 agent 可使用 `download-file` 擷取原始檔案。

    下載會使用有界限的閒置和總逾時。如果 Slack 檔案擷取停滯或失敗，OpenClaw 會繼續處理訊息，並回退到檔案預留位置。

    執行階段傳入大小上限預設為 `20MB`，除非由 `channels.slack.mediaMaxMb` 覆寫。

  </Accordion>

  <Accordion title="Outbound text and files">
    - 文字分塊使用 `channels.slack.textChunkLimit`（預設 4000）
    - `channels.slack.chunkMode="newline"` 啟用段落優先分割
    - 檔案傳送使用 Slack 上傳 API，並可包含執行緒回覆（`thread_ts`）
    - 已設定時，傳出媒體上限會遵循 `channels.slack.mediaMaxMb`；否則頻道傳送會使用媒體管線中的 MIME 種類預設值

  </Accordion>

  <Accordion title="Delivery targets">
    偏好的明確目標：

    - `user:<id>` 用於 DM
    - `channel:<id>` 用於頻道

    僅含文字/區塊的 Slack DM 可直接發佈到使用者 ID；檔案上傳和執行緒傳送會先透過 Slack conversation API 開啟 DM，因為這些路徑需要具體的對話 ID。

  </Accordion>
</AccordionGroup>

## 指令與斜線行為

斜線指令在 Slack 中會顯示為單一已設定指令或多個原生指令。設定 `channels.slack.slashCommand` 以變更指令預設值：

- `enabled: false`
- `name: "openclaw"`
- `sessionPrefix: "slack:slash"`
- `ephemeral: true`

```txt
/openclaw /help
```

原生指令需要在你的 Slack app 中使用[額外 manifest 設定](#additional-manifest-settings)，並改由 `channels.slack.commands.native: true` 啟用，或在全域設定中使用 `commands.native: true` 啟用。

- Slack 的原生指令自動模式為**關閉**，因此 `commands.native: "auto"` 不會啟用 Slack 原生指令。

```txt
/help
```

原生引數選單使用自適應轉譯策略，會在分派所選選項值之前顯示確認互動視窗：

- 最多 5 個選項：按鈕區塊
- 6-100 個選項：靜態選取選單
- 超過 100 個選項：當 interactivity 選項處理常式可用時，使用具非同步選項篩選的外部選取
- 超出 Slack 限制：編碼後的選項值會回退為按鈕

```txt
/think
```

斜線工作階段使用像 `agent:<agentId>:slack:slash:<userId>` 這樣的隔離鍵，並仍會使用 `CommandTargetSessionKey` 將指令執行路由到目標對話工作階段。

## 互動式回覆

Slack 可以轉譯 agent 撰寫的互動式回覆控制項，但此功能預設為停用。

全域啟用：

```json5
{
  channels: {
    slack: {
      capabilities: {
        interactiveReplies: true,
      },
    },
  },
}
```

或僅為一個 Slack 帳戶啟用：

```json5
{
  channels: {
    slack: {
      accounts: {
        ops: {
          capabilities: {
            interactiveReplies: true,
          },
        },
      },
    },
  },
}
```

啟用後，代理可以發出僅限 Slack 的回覆指令：

- `[[slack_buttons: Approve:approve, Reject:reject]]`
- `[[slack_select: Choose a target | Canary:canary, Production:production]]`

這些指令會編譯成 Slack Block Kit，並透過既有的 Slack 互動事件路徑路由點擊或選取。

注意：

- 這是 Slack 專用 UI。其他通道不會將 Slack Block Kit 指令轉譯成自己的按鈕系統。
- 互動回呼值是 OpenClaw 產生的不透明權杖，而不是代理撰寫的原始值。
- 如果產生的互動區塊會超過 Slack Block Kit 限制，OpenClaw 會退回原始文字回覆，而不是傳送無效的 blocks payload。

## Slack 中的 exec 核准

Slack 可以作為具備互動按鈕與互動的原生核准用戶端，而不是退回 Web UI 或終端機。

- Exec 核准使用 `channels.slack.execApprovals.*` 進行原生 DM/頻道路由。
- 當請求已經落在 Slack 中，且核准 id 種類為 `plugin:` 時，Plugin 核准仍可透過相同的 Slack 原生按鈕介面解析。
- 仍會強制執行核准者授權：只有識別為核准者的使用者可以透過 Slack 核准或拒絕請求。

這使用與其他通道相同的共用核准按鈕介面。當你的 Slack app 設定中啟用 `interactivity` 時，核准提示會直接在對話中呈現為 Block Kit 按鈕。
當這些按鈕存在時，它們就是主要核准 UX；OpenClaw
只有在工具結果表示聊天核准無法使用，或手動核准是唯一途徑時，
才應包含手動 `/approve` 指令。

組態路徑：

- `channels.slack.execApprovals.enabled`
- `channels.slack.execApprovals.approvers`（可選；可行時會退回 `commands.ownerAllowFrom`）
- `channels.slack.execApprovals.target`（`dm` | `channel` | `both`，預設值：`dm`）
- `agentFilter`、`sessionFilter`

當 `enabled` 未設定或為 `"auto"`，且至少解析出一位核准者時，Slack 會自動啟用原生 exec 核准。設定 `enabled: false` 可明確停用 Slack 作為原生核准用戶端。
設定 `enabled: true` 可在解析出核准者時強制開啟原生核准。

沒有明確 Slack exec 核准組態時的預設行為：

```json5
{
  commands: {
    ownerAllowFrom: ["slack:U12345678"],
  },
}
```

只有在你想覆寫核准者、新增篩選器，或
選擇加入來源聊天傳遞時，才需要明確的 Slack 原生組態：

```json5
{
  channels: {
    slack: {
      execApprovals: {
        enabled: true,
        approvers: ["U12345678"],
        target: "both",
      },
    },
  },
}
```

共用的 `approvals.exec` 轉發是分開的。只有當 exec 核准提示也必須
路由到其他聊天或明確的頻外目標時才使用它。共用的 `approvals.plugin` 轉發也是
分開的；當這些請求已經落在 Slack 中時，Slack 原生按鈕仍可解析 Plugin 核准。

同一聊天中的 `/approve` 也可在已支援指令的 Slack 頻道與 DM 中運作。請參閱 [Exec 核准](/zh-TW/tools/exec-approvals)，了解完整的核准轉發模型。

## 事件與操作行為

- 訊息編輯/刪除會對應成系統事件。
- 執行緒廣播（「也傳送到頻道」的執行緒回覆）會作為一般使用者訊息處理。
- 新增/移除反應事件會對應成系統事件。
- 成員加入/離開、頻道建立/重新命名，以及新增/移除釘選事件會對應成系統事件。
- 啟用 `configWrites` 時，`channel_id_changed` 可以遷移頻道組態鍵。
- 頻道主題/用途中繼資料會被視為不受信任的脈絡，並可注入路由脈絡。
- 適用時，執行緒起始訊息與初始執行緒歷史脈絡種子會依設定的寄件者允許清單篩選。
- 區塊動作與 modal 互動會發出結構化的 `Slack interaction: ...` 系統事件，並包含豐富的 payload 欄位：
  - 區塊動作：選取值、標籤、選擇器值，以及 `workflow_*` 中繼資料
  - modal `view_submission` 與 `view_closed` 事件，包含已路由頻道中繼資料與表單輸入

## 組態參考

主要參考：[組態參考 - Slack](/zh-TW/gateway/config-channels#slack)。

<Accordion title="高訊號 Slack 欄位">

- 模式/驗證：`mode`、`botToken`、`appToken`、`signingSecret`、`webhookPath`、`accounts.*`
- DM 存取：`dm.enabled`、`dmPolicy`、`allowFrom`（舊版：`dm.policy`、`dm.allowFrom`）、`dm.groupEnabled`、`dm.groupChannels`
- 相容性切換：`dangerouslyAllowNameMatching`（緊急破窗；除非需要，否則保持關閉）
- 頻道存取：`groupPolicy`、`channels.*`、`channels.*.users`、`channels.*.requireMention`
- 執行緒/歷史：`replyToMode`、`replyToModeByChatType`、`thread.*`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit`
- 傳遞：`textChunkLimit`、`chunkMode`、`mediaMaxMb`、`streaming`、`streaming.nativeTransport`、`streaming.preview.toolProgress`
- 展開預覽：`unfurlLinks`、`unfurlMedia`，用於 `chat.postMessage` 連結/媒體預覽控制
- 維運/功能：`configWrites`、`commands.native`、`slashCommand.*`、`actions.*`、`userToken`、`userTokenReadOnly`

</Accordion>

## 疑難排解

<AccordionGroup>
  <Accordion title="頻道中沒有回覆">
    依序檢查：

    - `groupPolicy`
    - 頻道允許清單（`channels.slack.channels`）— **鍵必須是頻道 ID**（`C12345678`），而不是名稱（`#channel-name`）。在 `groupPolicy: "allowlist"` 下，名稱型鍵會無聲失敗，因為頻道路由預設以 ID 優先。若要尋找 ID：在 Slack 中以右鍵點擊頻道 → **複製連結** — URL 結尾的 `C...` 值就是頻道 ID。
    - `requireMention`
    - 每頻道 `users` 允許清單

    實用指令：

```bash
openclaw channels status --probe
openclaw logs --follow
openclaw doctor
```

  </Accordion>

  <Accordion title="DM 訊息被忽略">
    檢查：

    - `channels.slack.dm.enabled`
    - `channels.slack.dmPolicy`（或舊版 `channels.slack.dm.policy`）
    - 配對核准 / 允許清單項目
    - Slack Assistant DM 事件：提到 `drop message_changed` 的詳細記錄
      通常表示 Slack 傳送了一個已編輯的 Assistant-thread 事件，但訊息中繼資料中
      沒有可復原的人類寄件者

```bash
openclaw pairing list slack
```

  </Accordion>

  <Accordion title="Socket mode 未連線">
    在 Slack app 設定中驗證 bot + app 權杖與 Socket Mode 啟用狀態。

    如果 `openclaw channels status --probe --json` 顯示 `botTokenStatus` 或
    `appTokenStatus: "configured_unavailable"`，表示 Slack 帳戶已
    設定，但目前執行階段無法解析由 SecretRef 支援的
    值。

  </Accordion>

  <Accordion title="HTTP mode not receiving events">
    驗證：

    - 簽署密鑰
    - webhook 路徑
    - Slack Request URL（Events + Interactivity + Slash Commands）
    - 每個 HTTP 帳戶都有唯一的 `webhookPath`

    如果帳戶快照中出現 `signingSecretStatus: "configured_unavailable"`，
    表示 HTTP 帳戶已設定，但目前執行階段無法解析以 SecretRef
    支援的簽署密鑰。

  </Accordion>

  <Accordion title="Native/slash commands not firing">
    確認你原本預期使用的是：

    - 原生命令模式（`channels.slack.commands.native: true`），並已在 Slack 註冊相符的 slash commands
    - 或單一 slash command 模式（`channels.slack.slashCommand.enabled: true`）

    也請檢查 `commands.useAccessGroups` 和頻道/使用者允許清單。

  </Accordion>
</AccordionGroup>

## 附件視覺參考

當 Slack 檔案下載成功且大小限制允許時，Slack 可以將下載的媒體附加到 agent turn。圖片檔案可以透過媒體理解路徑傳遞，或直接傳給具備視覺能力的回覆模型；其他檔案則會保留為可下載的檔案情境，而不是被視為圖片輸入。

### 支援的媒體類型

| 媒體類型                       | 來源                 | 目前行為                                                                          | 備註                                                                      |
| ------------------------------ | -------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| JPEG / PNG / GIF / WebP 圖片   | Slack 檔案 URL       | 下載並附加到該 turn，以供具備視覺能力的處理使用                                  | 單檔上限：`channels.slack.mediaMaxMb`（預設 20 MB）                       |
| PDF 檔案                       | Slack 檔案 URL       | 下載並公開為檔案情境，以供 `download-file` 或 `pdf` 等工具使用                    | Slack 入站不會自動將 PDF 轉換為圖片視覺輸入                               |
| 其他檔案                       | Slack 檔案 URL       | 可行時下載並公開為檔案情境                                                        | 二進位檔案不會被視為圖片輸入                                              |
| 執行緒回覆                     | 執行緒起始檔案       | 當回覆沒有直接媒體時，可將根訊息檔案補水為情境                                    | 只有檔案的起始訊息會使用附件佔位符                                        |
| 多圖片訊息                     | 多個 Slack 檔案      | 每個檔案都會獨立評估                                                              | Slack 處理每則訊息最多八個檔案                                            |

### 入站管線

當帶有檔案附件的 Slack 訊息抵達時：

1. OpenClaw 會使用 bot token（`xoxb-...`）從 Slack 的私有 URL 下載檔案。
2. 成功後，檔案會寫入媒體儲存區。
3. 下載的媒體路徑和內容類型會加入入站情境。
4. 支援圖片的模型/工具路徑可以使用該情境中的圖片附件。
5. 非圖片檔案仍會作為檔案中繼資料或媒體參照，供能處理它們的工具使用。

### 執行緒根附件繼承

當訊息抵達執行緒中（具有 `thread_ts` 父項）時：

- 如果回覆本身沒有直接媒體，且包含的根訊息有檔案，Slack 可以將根檔案補水為執行緒起始情境。
- 直接回覆附件優先於根訊息附件。
- 只有檔案且沒有文字的根訊息會以附件佔位符表示，使 fallback 仍可包含其檔案。

### 多附件處理

當單一 Slack 訊息包含多個檔案附件時：

- 每個附件都會透過媒體管線獨立處理。
- 下載的媒體參照會彙總到訊息情境中。
- 處理順序遵循事件 payload 中的 Slack 檔案順序。
- 某個附件下載失敗不會阻擋其他附件。

### 大小、下載與模型限制

- **大小上限**：預設每個檔案 20 MB。可透過 `channels.slack.mediaMaxMb` 設定。
- **下載失敗**：Slack 無法提供的檔案、過期 URL、無法存取的檔案、超出大小限制的檔案，以及 Slack 驗證/登入 HTML 回應，都會被略過，而不是回報為不支援的格式。
- **視覺模型**：圖片分析會在現用回覆模型支援視覺時使用該模型，否則使用 `agents.defaults.imageModel` 設定的圖片模型。

### 已知限制

| 情境                                   | 目前行為                                                                 | 替代方式                                                                   |
| -------------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| 過期的 Slack 檔案 URL                  | 略過檔案；不顯示錯誤                                                     | 在 Slack 中重新上傳檔案                                                    |
| 未設定視覺模型                         | 圖片附件會儲存為媒體參照，但不會作為圖片分析                             | 設定 `agents.defaults.imageModel`，或使用具備視覺能力的回覆模型            |
| 非常大的圖片（預設 > 20 MB）           | 依大小上限略過                                                           | 如果 Slack 允許，請提高 `channels.slack.mediaMaxMb`                        |
| 轉寄/共享附件                          | 文字和 Slack 託管的圖片/檔案媒體會以盡力而為方式處理                     | 直接在 OpenClaw 執行緒中重新分享                                          |
| PDF 附件                               | 儲存為檔案/媒體情境，不會自動經由圖片視覺路徑處理                        | 使用 `download-file` 取得檔案中繼資料，或使用 `pdf` 工具進行 PDF 分析      |

### 相關文件

- [媒體理解管線](/zh-TW/nodes/media-understanding)
- [PDF 工具](/zh-TW/tools/pdf)
- Epic：[#51349](https://github.com/openclaw/openclaw/issues/51349) — Slack 附件視覺啟用
- 迴歸測試：[#51353](https://github.com/openclaw/openclaw/issues/51353)
- 即時驗證：[#51354](https://github.com/openclaw/openclaw/issues/51354)

## 相關

<CardGroup cols={2}>
  <Card title="Pairing" icon="link" href="/zh-TW/channels/pairing">
    將 Slack 使用者配對到 Gateway。
  </Card>
  <Card title="Groups" icon="users" href="/zh-TW/channels/groups">
    頻道與群組 DM 行為。
  </Card>
  <Card title="Channel routing" icon="route" href="/zh-TW/channels/channel-routing">
    將入站訊息路由至 agent。
  </Card>
  <Card title="Security" icon="shield" href="/zh-TW/gateway/security">
    威脅模型與強化。
  </Card>
  <Card title="Configuration" icon="sliders" href="/zh-TW/gateway/configuration">
    設定版面配置與優先順序。
  </Card>
  <Card title="Slash commands" icon="terminal" href="/zh-TW/tools/slash-commands">
    命令目錄與行為。
  </Card>
</CardGroup>
