Set up Slack

Slack uses two credentials because WOML connects through Socket Mode:

  • a bot token (xoxb-...) authorizes messages, channel lookup, and events; and
  • an app-level token (xapp-...) opens the Socket Mode connection.

This setup does not require a public callback URL.

Create and configure the Slack app

  1. Open Slack API apps and select Create New App.
  2. Choose From an app manifest, select the workspace, and use this manifest:
JSON
{
  "display_information": {
    "name": "WOML",
    "description": "Run and approve WOML workflows from Slack.",
    "background_color": "#16a34a"
  },
  "features": {
    "bot_user": {
      "display_name": "WOML",
      "always_online": false
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "chat:write",
        "chat:write.public",
        "app_mentions:read",
        "channels:read",
        "groups:read",
        "im:history"
      ]
    }
  },
  "settings": {
    "event_subscriptions": {
      "bot_events": ["app_mention", "message.im"]
    },
    "interactivity": { "is_enabled": true },
    "socket_mode_enabled": true,
    "token_rotation_enabled": false
  }
}
  1. Open Event Subscriptions and confirm Enable Events is on. The bot events must include app_mention and message.im.
  2. Open Interactivity & Shortcuts and confirm interactivity is enabled. Approval buttons depend on it.
  3. Open Socket Mode and confirm it is enabled.
  4. Open Basic Information → App-Level Tokens, create a token with the connections:write scope, and copy the resulting xapp-... token.
  5. Open OAuth & Permissions, install the app to the workspace, and copy the Bot User OAuth Token beginning with xoxb-.

If scopes or event subscriptions change later, reinstall the app to the workspace and replace the stored bot token when Slack issues a new one.

Add the bot to the channel

Create or open a test channel such as #woml-testing, then run this inside the channel:

Text
/invite @WOML

Private channels always require an explicit invite. Inviting the bot is also recommended for public channels.

Store the credentials

Run these commands from the project that will run the workflow:

Terminal
woml secrets set SLACK_BOT_TOKEN
woml secrets set SLACK_APP_TOKEN

Paste the xoxb-... value into the first prompt and the xapp-... value into the second. Do not place either token directly in a .woml file or commit it to source control.

Test a Slack trigger

Save this as slack-test.woml:

WOML
<woml>
  <workflow id="slack-test" name="Slack Test" version="1.0.0">
    <triggers>
      <slack
        id="messageReceived"
        events="app-mention,direct-message"
        channels="woml-testing"
        bot-token="{{secrets.SLACK_BOT_TOKEN}}"
        app-token="{{secrets.SLACK_APP_TOKEN}}"
      />
    </triggers>

    <steps>
      <step id="capture" name="Capture Slack message">
        <script>
          return {
            text: context.payload.text,
            senderId: context.payload.senderId,
            conversationId: context.payload.conversationId
          };
        </script>
      </step>
    </steps>
  </workflow>
</woml>

Validate and start it:

Terminal
woml check slack-test.woml
woml run slack-test.woml

Wait for Slack workspace ... is ready for triggers, then send @WOML hello in #woml-testing or send the bot a direct message. WOML should accept a Slack trigger, run capture, and print the normalized message data.

The trigger's channels attribute uses comma-separated names without #. Notification destinations use whitespace-separated aliases with #, for example:

WOML
<approval id="review" timeout="24h" on-timeout="reject">
  <notify>
    <slack
      channels="#woml-testing"
      bot-token="{{secrets.SLACK_BOT_TOKEN}}"
      app-token="{{secrets.SLACK_APP_TOKEN}}"
    />
  </notify>
  <when-approved />
  <when-rejected />
</approval>

Diagnose Slack setup failures

  • No events arrive: make sure Enable Events is on and the bot events include app_mention and message.im.
  • Authentication fails: verify that the bot token starts with xoxb-, the app token starts with xapp-, and the app token has connections:write.
  • Channel lookup reports missing_scope: add channels:read and groups:read, then reinstall the app. channels:history is not a replacement for channels:read.
  • A private channel is not found: invite @WOML to it or use its Slack conversation ID.
  • Messages send but buttons do nothing: enable Interactivity & Shortcuts.
  • An updated app still behaves like the old configuration: reinstall it to the workspace and update the stored token.