Skip to main content

Slack

The Slack connector pins your gateway to https://slack.com/api and exposes the conversation methods an agent actually needs: list channels, read a channel's history, list users, and search. Posting, deleting and archiving are there too, switched off until you decide otherwise. It suits an agent that summarises a channel, finds the thread where a decision was made, or drafts a standup post for you to approve.

What you need

A bot token (xoxb-…) from a Slack app you install into your workspace.

  1. Create the app at api.slack.com/appsCreate New AppFrom scratch. Name it and pick the workspace.
  2. Open OAuth & Permissions and add these Bot Token Scopes under Scopes:
ScopeNeeded for
channels:readconversations.list (public channels)
groups:read, im:read, mpim:readconversations.list when you pass private channels, DMs or group DMs in types
channels:historyconversations.history
users:readusers.list
chat:writechat.postMessage and chat.delete
channels:manageconversations.archive

search.messages is the exception: it needs search:read, which Slack only issues as a user token scope. Add it under User Token Scopes rather than Bot Token Scopes, and see the caution below.

Add only the scopes for the capabilities you intend to enable. A scope you never grant is a capability that fails closed even if someone switches it on.

  1. Click Install to Workspace and authorise. Slack returns you to OAuth & Permissions, where the Bot User OAuth Token starting xoxb- is shown. Copy it.
  2. Invite the bot to any channel it should read, with /invite @your-app. A bot token only sees channels the bot is a member of.
search.messages will not work with a bot token

Slack's search.messages requires search:read and accepts user tokens only — a bot token is rejected with not_allowed_token_type. The capability ships enabled, so on a bot-token connection expect it to fail on every call until you switch it off. To use search, install the app with search:read under User Token Scopes and paste the User OAuth Token (xoxp-…) as the credential instead.

That is a real trade. A user token acts as you: it reads every channel and DM you can see, not just the channels a bot was invited to, and chat.delete on a user token can remove anyone's message rather than only the bot's. Prefer the bot token unless you specifically need search.

Add the connection

Open Access → Connections → Add connection, choose Slack from the catalog, and paste the xoxb-… token into the credential field (or the xoxp-… user token, if you took that route for search). It is sealed on your gateway and never displayed again.

An agent still cannot use it until a grant allows it.

What the agent can do

ActionWhat it doesOn by default
conversations.listList conversations, filtered by types and limitYes
conversations.historyRead a channel's message historyYes
users.listList workspace usersYes
search.messagesSearch messages by queryYes — but see the note above
chat.postMessagePost a message to a channelNo — approval required
chat.deleteDelete a messageNo — approval required
conversations.archiveArchive a channelNo — approval required

The three writes land switched off, and each carries a standing approval requirement on top. Enabling chat.postMessage does not let an agent post: every message stops and waits for a human on a paired device first. That matters most for chat.delete, which with a bot token can only remove the bot's own messages, but with a user token removes anyone's.

Good to know

  • Rate limits are per method, per workspace. Slack tiers its Web API roughly 1+, 20+, 50+ and 100+ requests per minute; conversations.list sits in the 20-per-minute tier and conversations.history in the 50-per-minute one. chat.postMessage is special-cased to about one message per second per channel. Exceeding any of them returns 429 with a Retry-After header. Since May 2025 Slack throttles conversations.history to roughly one request per minute for newly created apps that are commercially distributed and not Marketplace-approved — a single-workspace internal app like the one above is not affected, but a distributed one will crawl.
  • The bot only sees what it has joined. conversations.list will show public channels, but conversations.history returns nothing for a channel the bot was never invited to. That is a useful containment boundary: invite it to the two channels you meant, not the whole workspace.
  • Private channels and DMs need extra scopes. Passing types=private_channel,im,mpim to conversations.list without groups:read, im:read and mpim:read returns an error rather than a partial list.
  • OAuth works too, but only with token rotation on. Gateway 1.1.0 and later runs the whole authorisation code flow against the same Slack app, sealing the tokens on your gateway and refreshing them there; you start it through the gateway's REST API (POST /v1/connections/:id/oauth/start), because the console has no "Add to Slack" button yet. Whether it completes depends on the app: with token rotation enabled Slack returns a refresh token alongside an xoxe.… access token that expires after twelve hours, which is what the gateway needs; without it the xoxb-… token comes back on its own, the gateway refuses to seal a credential it cannot refresh, and the callback stops with that error. The exchange seals the bot token — Slack returns the user token nested separately and the gateway does not read it — so search.messages still needs an xoxp-… pasted by hand. Installing the app already hands you a xoxb-… that does not expire, so pasting that stays the simpler route.
  • Contact details are redacted on the way back. The connector strips email and phone from responses before the agent sees them, which mostly bites on users.list — profiles come back without contact details. Message text and display names are untouched.