Skip to content

Slack

Connect a Slack app over Socket Mode: one connection for every workspace, mentions and threads, files, reactions and approval buttons, with no public URL.

On this page

Slack connects over Socket Mode. One app-level token holds one connection for every workspace the app is installed in, with a bot token per workspace. No public URL is needed.

Set it up#

  1. Create an app at api.slack.com/apps and turn on Socket Mode. Create an app-level token (xapp-...) with the connections:write scope.
  2. Under Event Subscriptions, subscribe to the bot events app_mention and message.im, plus message.channels and message.groups so the bot can follow threads it was mentioned in. Add the OAuth scopes those events need, and chat:write.
  3. For files and reactions, add files:read, files:write and reactions:write. For approval buttons, turn on Interactivity.
  4. Install the app to your workspace and copy the bot token (xoxb-...).
  5. Run habakkuk setup and pick Slack app (it checks both tokens), or add the channel by hand:
yaml
channels:
  slack:
    type: slack
    app_token_env: SLACK_APP_TOKEN              # Socket Mode, one connection for every workspace
    bot_tokens_env: [SLACK_BOT_TOKEN, SLACK_BOT_TOKEN_2]   # one per workspace
    routes: {T0123456: ops}                     # a workspace or conversation can go to another agent

Several Slack apps#

One app installed in several workspaces needs one channel, with a bot token per workspace in bot_tokens_env. When each workspace has its own app (for example, an app you made in your workspace and another made in a client's), add one type: slack channel per app. Each has its own app token and its own Socket Mode connection, and they run side by side in one habakkuk serve. Both can go to the same agent:

yaml
channels:
  slack:
    type: slack
    agent: habakkuk
    app_token_env: SLACK_APP_TOKEN
    bot_tokens_env: [SLACK_BOT_TOKEN]
    allow_from: [U0123ABCD]
  slack-acme:
    type: slack
    agent: habakkuk                     # the same agent, or another
    app_token_env: ACME_SLACK_APP_TOKEN
    bot_tokens_env: [ACME_SLACK_BOT_TOKEN]
    allow_from: [U0999WXYZ]             # user ids from that workspace
    listen_channels: [C0777GHI]

Each channel keeps its own allow_from, pairing, routes and settings, and its conversations are its own. habakkuk setup edits the first Slack channel; add the second by hand, then put its tokens in .env.

Access#

allow_from takes Slack user ids (U0123ABCD). Anyone else who sends a direct message gets a pairing code. routes maps a workspace (team id) or a conversation to another agent, so one app can serve several teams with different agents.

Channels and threads#

In channels the bot answers mentions and replies in a thread under the mention. Once it has replied in a thread, later messages there count as addressed to it.

Direct messages are answered at the top level of the chat, even when you write inside a thread there.

Channels where no mention is needed#

listen_channels lists channels where every message from an allowed sender is for the bot, with no @mention:

yaml
channels:
  slack:
    type: slack
    app_token_env: SLACK_APP_TOKEN
    bot_tokens_env: [SLACK_BOT_TOKEN]
    allow_from: [U0123ABCD, U0456EFGH]
    listen_channels: [C0123ABC, C0456DEF]
  • Use channel ids, not names. In Slack, open the channel's name, then About: the id is at the bottom. With several workspaces, T0123/C0123ABC limits an entry to one workspace.
  • A top-level message starts a thread under it, and the bot answers there. A message inside a thread continues that thread, as with a mention.
  • Only senders in allow_from (or paired) are answered. Others are ignored without a pairing code, and so are other bots.
  • Invite the bot to each channel, and subscribe to message.channels (and message.groups for private channels) with the channels:history (and groups:history) scope.

What works#

Feature Support
In Text, files (needs files:read)
Out Text, files up to 100 MB (needs files:write)
Live progress One short line such as "Checking the web", edited as the work moves on (progress: plain, the default); detailed shows a line per tool step
Typing indicator Slack has none for bots. With progress: off, a turn that runs past 60 seconds posts one "still working" notice
Buttons Approve and Deny on approval requests. A press is acknowledged to Slack at once. A button on a request from before a restart answers the request asked again only when it is the same call; otherwise you are told it expired
Approval buttons Approve and Deny, with Interactivity turned on
Reactions With reactions: true (needs reactions:write)

Troubleshooting#

Symptom Cause and fix
slack download returned a web page: the app needs the files:read scope Add files:read, reinstall the app, and update the bot token.
... (the Slack app needs the files:write scope) Add files:write, reinstall the app, and update the bot token.
slack: no bot token for workspace T... The app is installed in a workspace whose bot token is not in bot_tokens_env. Add it.
The bot ignores follow-ups in a thread Subscribe to message.channels (and message.groups for private channels).
The bot never answers in channels Invite it to the channel, and mention it.