AI Tools Review
Moltbot Slack Setup: Complete Enterprise Guide

Insights

Moltbot Slack Setup: Complete Enterprise Guide

AI Tools Review Editorial TeamJan 29, 2026

    Slack is the operating system for modern work, and Moltbot brings truly agentic AI directly into your team's channels. Whether you're automating devops tasks, summarising threads, or managing projects, the Slack integration offers deep visibility and control.

    This guide covers everything from a simple Socket Mode setup for local testing to a production-grade HTTP Events API deployment for enterprise use.

    A note on naming

    This project has been through three names in under a year: it shipped as Clawdbot in November 2025, became Moltbot in January 2026, and was renamed again to OpenClaw later the same month. The Slack connector is the same code throughout, but current releases ship an openclaw CLI binary and publish their documentation under the OpenClaw name, so the diagnostic commands later in this guide use that prefix. If you are running an older build, the equivalent moltbot commands behave identically. See Moltbot vs Clawdbot for the full history.

    Socket Mode vs. HTTP Mode

    Socket Mode (Default) is easiest: it works behind firewalls without a public IP. Use this for personal bots or local testing.
    HTTP Mode is faster and stateless: use this for server deployments where your Moltbot instance has a public HTTPS endpoint.

    Quick Setup (Socket Mode)

    Step 1: Create App

    Go to api.slack.com/apps and create a new app "From Scratch".

    Name it "Moltbot" and select your workspace.

    Step 2: Enable Socket Mode

    • Navigate to Socket Mode in the sidebar and toggle it ON.
    • Go to Basic Information → App-Level Tokens.
    • Click "Generate Token and Scopes", add connections:write, and generate.
    • Copy the App Token (starts with xapp-...).

    Step 3: Bot Token & Scopes

    • Go to OAuth & Permissions.
    • Add the required Bot Token Scopes (see manifest below).
    • Click "Install to Workspace" at the top.
    • Copy the Bot User OAuth Token (starts with xoxb-...).

    Step 4: Configure Moltbot

    Add the tokens to your configuration:

    {
      "channels": {
        "slack": {
          "enabled": true,
          "appToken": "xapp-...",
          "botToken": "xoxb-..."
        }
      }
    }

    Alternatively, set SLACK_APP_TOKEN and SLACK_BOT_TOKEN env vars.

    App Manifest & Scopes

    The fastest way to configure your Slack app is to use the App Manifest (JSON). This ensures you have exactly the right permissions and event subscriptions.

    How to use: In the Slack API dashboard, go to App Manifest, select "JSON", and paste the code below.

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

    What Each Scope Actually Does

    Pasting a manifest is quick, but it also means you approve a list of permissions without reading it — and a security reviewer will eventually ask you to justify every line. Here is what the important ones buy you, and which you can safely drop.

    • chat:write — the one non-negotiable scope. Without it the bot can read everything and say nothing.
    • app_mentions:read — delivers the app_mention event. If you only ever want the bot to respond when explicitly summoned, this plus chat:write is very nearly a complete install.
    • channels:history / groups:history — read message history in public and private channels respectively. These are what let the bot answer "summarise the last hour" rather than only reacting to the single message that triggered it. They are also the scopes your security team will scrutinise hardest, because together they grant broad read access.
    • im:history, im:read, im:write — direct messages. Drop all three if you intend the bot to be channel-only; it materially reduces the blast radius of a leaked token.
    • mpim:* — group DMs, which Slack treats as a separate surface from both channels and one-to-one DMs. Forgetting these is the usual reason a bot works in a DM and is silent in a three-person group chat.
    • users:read — resolves user IDs to display names. Skip it and transcripts fill with raw U0123ABCD identifiers, which degrades the model's answers as well as your logs.
    • reactions:read / reactions:write — needed for emoji-triggered workflows and for the acknowledgement reaction the bot adds while it is thinking. That little eyes emoji is the cheapest UX win in the whole integration; without it, users repeat themselves because nothing appears to be happening.
    • files:read / files:write — required if you want the bot to read uploaded PDFs and images or return generated artefacts. Omit them and file-heavy prompts fail silently rather than loudly.
    • commands — only needed if you register slash commands.

    Scope changes require a reinstall

    Adding a scope to an installed Slack app does not take effect until you reinstall the app to the workspace, and reinstalling issues a new bot token. Plan for this: if you add files:read three weeks after go-live and forget to update SLACK_BOT_TOKEN, the gateway will fail with invalid_auth and stop reconnecting. Start with the scopes you know you need, then treat each later addition as a small deployment rather than a settings tweak.

    User Tokens (Optional)

    Moltbot can optionally use a User Token (xoxp-...) to perform actions "as you" or to access data that bots can't see (like detailed search results or member profiles).

    Token Privacy & Read-Only Mode

    By default, the user token is Read-Only. Moltbot prefers the Bot Token for all write actions (sending messages, pinning) unless explicitly configured otherwise.

    {
      "channels": {
        "slack": {
          "enabled": true,
          "appToken": "xapp-...",
          "botToken": "xoxb-...",
          "userToken": "xoxp-...",
          "userTokenReadOnly": false // Set true to allow writing as user
        }
      }
    }

    HTTP Mode (Events API)

    For production deployments where you have a public HTTPS endpoint, HTTP Mode is more robust than Socket Mode.

    Setup Steps

    1. Disable Socket Mode in your Slack App settings.
    2. Copy the Signing Secret from "Basic Information".
    3. Configure Moltbot with the correct mode and webhook path:
      {
        "channels": {
          "slack": {
            "enabled": true,
            "mode": "http",
            "botToken": "xoxb-...",
            "signingSecret": "your-signing-secret",
            "webhookPath": "/slack/events"
          }
        }
      }
    4. In Slack Event Subscriptions, set Request URL to: https://your-bot.com/slack/events.
    5. Use the same URL for Interactivity & Shortcuts and Slash Commands.

    A few implementation details are worth knowing before you put this behind a load balancer. The HTTP handler installs a 1MB request body limit and a 30-second timeout, which is generous for Slack's payloads but will cut off a reverse proxy that buffers badly. The public URL must terminate TLS itself and forward to the gateway's configured path; Slack will not follow redirects during URL verification, so an HTTP-to-HTTPS redirect at the edge shows up as a failed challenge rather than a warning. And if you run more than one Slack account against a single gateway, each account needs its own webhookPath — reusing one produces repeated webhook path ... already registered errors at startup and only the first account receives events.

    There is also a third transport worth knowing about: relay mode, intended for managed deployments where the operator terminates Slack's connection centrally. It is convenient, but note the limitation before you plan around it — relay mode is not supported for Enterprise Grid accounts.

    Access Control: DM and Channel Policies

    This is the part most setup guides skip and most real deployments get wrong. A Slack bot that has been invited to a channel is, by default, a bot that can be talked to by everyone in that channel — including people who do not realise they are addressing an autonomous agent with tool access. The connector exposes two independent policy layers, and you should set both deliberately.

    Direct message policy

    channels.slack.dmPolicy accepts four values, in rough order of strictness:

    • disabled — the bot ignores DMs entirely. Correct for a bot that exists to serve one team channel.
    • pairing — a new sender must be approved before their messages are processed. Inspect the queue with openclaw pairing list slack. This is the sensible default for anything shared across a workspace.
    • allowlist — only the identities you enumerate get through. The schema requires at least one entry, so an empty allowlist is a configuration error rather than a silent lockout.
    • open — anyone can DM the bot. Note the gotcha: setting open is not sufficient on its own, because the policy still requires channels.slack.allowFrom to be ["*"]. Set one without the other and you get a bot that looks configured and answers nobody.

    Group DMs are a separate switch again. Enable channels.slack.dm.groupEnabled and list the relevant MPIMs in channels.slack.dm.groupChannels, or your bot will answer one-to-one messages perfectly and ignore the four-person huddle where the actual work is happening.

    Channel policy and mention gating

    On the channel side, groupPolicy governs which conversations the bot will engage with at all, and the per-channel allowlist under channels.slack.channels narrows it further. One rule causes more wasted debugging than any other: allowlist entries must be channel IDs, not channel names. Use C12345678, or on Enterprise Grid the workspace-qualified form team:<team-id>:channel:<channel-id>. Typing #general will parse fine and match nothing.

    requireMention is the other lever, and for any busy channel you almost certainly want it on. Without it the bot sees every message and has to decide for itself whether it was being addressed, which is both expensive and socially awkward. With it, the bot stays quiet until someone writes @Moltbot. You can also tune what happens to the messages it sees but was not addressed by, via messages.groupChat.unmentionedInbound: setting it to room_event means unmentioned traffic becomes ambient context the model can draw on, but the bot must explicitly invoke the message tool to say anything back.

    Threading & Direct Messages

    Moltbot supports sophisticated threading strategies to keep your channels clean.

    ModeBehavior
    offReply in the main channel (default). Only threads if the trigger was already in a thread.
    firstFirst reply starts a thread; subsequent replies stay in the main channel. Good balance of context and visibility.
    allEvery reply goes into a thread. Keeps the main channel very clean.

    Per-Channel-Type Strategy

    You can configure different behaviours for DMs vs Channels. For example, always thread in DMs but keep channels flat:

    {
      "channels": {
        "slack": {
          "replyToMode": "off",        // Default for public channels
          "replyToModeByChatType": {
            "direct": "all",           // Thread every DM response
            "group": "first"           // Thread first response in group DMs
          }
        }
      }
    }

    Sessions, History Scope and Context Bleed

    Threading is not only a cosmetic choice; it determines what the model can see. The connector derives a session key from the conversation, roughly agent:<agentId>:slack:user:<userId> for a DM, agent:<agentId>:slack:channel:<channelId> for a channel, with a thread:<threadTs> component appended inside a thread. Each distinct key is a distinct conversation as far as the agent is concerned.

    Two settings control how much context crosses those boundaries. thread.historyScope set to thread isolates a thread to its own messages, which keeps a long-running support thread clean; set to channel, the thread can see the surrounding channel history, which is better when threads are used as brief asides within an ongoing discussion. thread.inheritParent goes further and copies the parent channel transcript into a newly created thread, so the bot does not lose the plot the moment someone replies in a thread to a conversation it had been following.

    The trade-off is cost and leakage. Wider scope means more tokens per turn and a real chance that something said in one part of a busy channel surfaces in an unrelated reply. For a general-purpose assistant in a noisy channel, thread-scoped history with inheritParent enabled is usually the right compromise: enough context to answer the question, not enough to wander.

    Slash Commands, Streaming & Rich Output

    Once messaging works, the difference between a toy and something a team will actually use is output quality. Three areas matter.

    Two different slash command modes

    There are two mutually confusable options and picking the wrong one accounts for a good share of "my commands do nothing" reports. Native command mode (channels.slack.commands.native: true) registers a set of first-class Slack commands. Single slash command mode (channels.slack.slashCommand.enabled: true) exposes one catch-all command, such as the /clawd in the manifest above, which forwards whatever you type. Crucially, Slack does not create or remove commands on your behalf: whichever mode you choose, you must register the commands in the Slack app dashboard yourself. Setting native commands to auto does not enable them — use true.

    In HTTP mode every registered command must carry your gateway URL; in Socket Mode the command URLs are ignored entirely, which is why a configuration that works locally can break the moment you move to a server. Commands run in an isolated session but carry metadata pointing back at the conversation they were invoked from, so a command can act on the surrounding thread without inheriting its whole transcript.

    Streaming and chunking

    Where Slack's native streaming is available, the connector posts an empty message and then streams chunks into it, finishing with a completion signal, so users watch the answer arrive rather than staring at a typing indicator for forty seconds. Where it is not, it falls back to editing a preview message, and long replies are split once they exceed textChunkLimit. Long-form output is the usual trigger for edge cases here: a 4,000-word answer that arrives as eleven consecutive messages is technically correct and practically unreadable, so it is worth tuning the chunk limit and, better, prompting the agent to summarise in Slack and attach the long version as a file.

    Reactions as an interface

    Reaction notifications have four modes — off, own (only reactions on the bot's own messages), all, and allowlist. The own mode is the quiet win: it lets you build approve-and-reject flows where a human ticks a message to authorise the next step, without the bot waking up every time someone adds a party popper elsewhere in the channel.

    Enterprise Grid Deployments

    On Enterprise Grid, a single installation can receive messages from every workspace the org-wide install covers. An Org Admin or Owner approves and installs the app at the organisation level and then selects which workspaces the installation applies to; you copy the bot token from the org installation as normal. You do not need to declare that you are in Grid mode — the connector calls Slack's auth.test and detects whether the token belongs to a workspace or an enterprise installation.

    The one thing you must change is how you write identifiers. Bare channel and user IDs are ambiguous across workspaces, so enterprise destinations use the qualified forms team:<team-id>:channel:<channel-id> and team:<team-id>:user:<user-id>. Workspace IDs begin with T and can be read out of the Slack web app URL. This qualification is mandatory for policy keys, and proactive or detached calls that supply a bare ID fail closed rather than guessing — which is the correct behaviour, and also the reason a Grid rollout tends to surface a batch of configuration errors on day one that a single-workspace pilot never showed.

    Grid limitations to plan around

    • Relay mode is unsupported. Choose Socket Mode (app-level token with connections:write) or HTTP Request URLs with a public HTTPS endpoint.
    • Channel-ID-change events are unavailable, so allowlists keyed to a channel that gets converted or migrated will need manual correction.
    • App Home is unavailable, which removes a convenient place to surface status and settings to end users.

    Troubleshooting: Symptoms and Fixes

    Almost every Slack integration failure presents as one of five symptoms. Work through them in this order; the diagnostic commands are openclaw channels status --probe, openclaw logs --follow and openclaw doctor.

    1. The bot is silent in channels

    • Has the bot actually been invited to the channel? Scopes grant capability, not membership.
    • Check groupPolicy, then the channel allowlist — and confirm you used channel IDs, not names.
    • Check requireMention. If it is on and nobody is mentioning the bot, everything is working as designed.
    • Check the per-channel users allowlist, which can silently exclude the person testing.
    • If logs show assistant text but no outbound message, look at messages.groupChat.visibleReplies. It defaults to automatic; if it has been set to message_tool, the model has to explicitly call the send action and sometimes will not.

    2. Direct messages are ignored

    • Confirm channels.slack.dm.enabled is on and check dmPolicy (older configs use the legacy channels.slack.dm.policy key).
    • Run openclaw pairing list slack to see whether the sender is stuck awaiting approval.
    • Remember the open policy still needs allowFrom: ["*"].
    • For group DMs, check dm.groupEnabled and that the MPIM is listed in dm.groupChannels.
    • A drop message_changed line in verbose logs means an event arrived without human sender metadata — typically an assistant-thread event rather than a real user message.

    3. Socket Mode will not connect

    • Confirm Socket Mode is toggled on in the Slack app itself, not just in your config.
    • Confirm the app-level token carries connections:write.
    • Confirm the bot token and app token belong to the same Slack app in the same workspace. A slack token mismatch log line means they do not — usually the result of copying one token from an env var and the other from a config file.
    • If openclaw channels status --probe --json reports configured_unavailable, the runtime can see that a secret reference exists but cannot resolve its value. That is a secrets-management problem, not a Slack problem.

    4. HTTP mode receives nothing

    • The signing secret must match, and channels.slack.webhookPath (default /slack/events) must exactly match the request URL configured in Slack.
    • Set the Request URL in all three places you use: Event Subscriptions, Interactivity & Shortcuts, and each slash command.
    • A signingSecretStatus: "configured_unavailable" reading again points at unresolved secrets.
    • Duplicate webhook path ... already registered errors mean two accounts are fighting over one path.

    5. Authentication errors that stop everything

    Four Slack errors are treated as non-recoverable and abort the connection monitor rather than retrying: invalid_auth, account_inactive, token_revoked and not_authed. That design is deliberate — retrying a revoked token forever only gets you rate-limited — but it means a token rotation that you forgot to deploy looks like a total outage rather than a degraded service. Everything else reconnects using exponential backoff with jitter, so a transient Slack incident resolves itself without intervention.

    Production Hardening Checklist

    Before you let a workspace loose on this, work through the following. None of it is exotic; all of it is the difference between a pilot and a service.

    • Keep tokens out of config files. Use SLACK_BOT_TOKEN and SLACK_APP_TOKEN, or a secret reference your runtime can resolve. Note that the environment-variable fallback applies only to the default account, so multi-account deployments need explicit secret references.
    • Rotate on exposure, not on schedule alone. An xoxb token is a workspace credential; if it appears in a log, a screenshot or a support ticket, regenerate it the same day.
    • Start with requireMention on and dmPolicy: pairing. Loosen deliberately once you know who is using it and for what.
    • Set spend and rate expectations before launch. An agent in a busy channel with history scopes enabled reads far more tokens per reply than the same agent in a DM.
    • Decide on bot-to-bot behaviour explicitly. Leaving allowBots off is the safe default; two agents that can hear each other in the same channel will eventually discover a reply loop, and it will happen at the weekend.
    • Run openclaw doctor as part of deployment, not only when something breaks. Most misconfigurations it catches are cheap to fix before users notice and expensive to diagnose afterwards.
    • Document which transport you chose and why. Socket Mode and HTTP mode fail in different ways, and the person on call at 3am will not be the person who set it up.

    If Slack is not the only surface you need, the same connector model covers other platforms — our Discord setup guide walks through the equivalent configuration there, and the grammY engineering case explains why the messaging layer is built the way it is.

    Next Steps

    Once your Slack bot is running, try these advanced configurations:

    • Set Group Policies to restrict which channels the bot can join.
    • Configure Slash Commands for custom tool triggers.
    • Enable Reaction Notifications to trigger skills via emoji.

    Frequently Asked Questions

    How do I deploy to an Enterprise Grid?
    For Enterprise Grid, install the app to the Org level and then add it to specific workspaces. You may need to use Admin scopes or multiple bot tokens if you are segmenting data strictly.
    Can Moltbot trigger on other bots' messages?
    By default, no. You can enable this by setting allowBots: true in the channel config, but be careful, this can create infinite reply loops if two bots start talking to each other.
    How secure are the tokens?
    Treat xoxb and xoxp tokens like passwords. If leaked, an attacker can access your workspace. We recommend using environment variables (SLACK_BOT_TOKEN) rather than hardcoding them in config files.

    Explore more AI tool comparisons

    In-depth reviews, benchmarks and guides to help you choose the right AI tools.

    Browse all reviews
    AI Tools Review Editorial Team

    AI Tools Review Editorial Team Expert verified

    Our editorial team consists of veteran AI researchers, software engineers, and industry analysts. We spend hundreds of hours benchmarking frontier models natively to provide you with objective, actionable intelligence on agentic AI capabilities and cybersecurity landscapes.