Problem: Your Team Needs an AI Assistant That Actually Works in Slack
You want an AI that doesn't just chat but actually executes tasks, remembers context, and integrates with your team's Slack workspace without sending data to third-party servers.
You'll learn:
- How to install OpenClaw locally on your infrastructure
- Configure Slack integration with Socket Mode (no exposed webhooks)
- Set up security policies for DMs and channels
- Deploy for enterprise teams with multi-channel support
Time: 20 min | Level: Intermediate
Why This Matters
OpenClaw is different from typical Slack bots because it runs on your hardware and connects to messaging platforms as a personal AI assistant. Unlike cloud services, your conversation history and business data stay on your servers.
Common use cases:
- Answer repeated questions without manual responses
- Execute automated workflows triggered by Slack messages
- Search internal documentation and databases
- Schedule tasks and send proactive notifications
What makes it enterprise-ready:
- Self-hosted (no data leaves your infrastructure)
- Multi-channel support with granular permissions
- Pairing mode for secure DM access
- Works with Claude, GPT, or local LLMs
Prerequisites
Before starting, ensure you have:
- A machine running macOS, Linux, or Windows WSL2
- Node.js 18+ (installer handles this automatically)
- Slack workspace admin access
- An Anthropic API key (Claude) or OpenAI key
Hardware recommendations:
- Development: Any modern laptop
- Production: Mac Mini M2 (16GB), cloud VPS, or dedicated server
Solution
Step 1: Install OpenClaw
Run the one-liner installer:
/bin/bash -c "$(curl -fsSL https://openclaw.ai/install.sh)"
What this does: Installs Node.js dependencies, downloads OpenClaw, and launches the onboarding wizard.
When prompted:
- Select QuickStart mode
- Choose your model provider (Anthropic recommended)
- Authenticate via browser when prompted
- Select Claude Opus 4.5 or Sonnet 4.5 as your default model
- When asked to select a channel, choose Slack
Expected output: The wizard will prompt for your Slack tokens.
Step 2: Create Your Slack App
Open https://api.slack.com/apps in a browser.
Create the app:
- Click Create New App → From scratch
- Name it
OpenClaw(or your preferred name) - Select your workspace
Enable Socket Mode:
- Go to Settings → Socket Mode → Toggle ON
- Navigate to Basic Information → App-Level Tokens
- Click Generate Token and Scopes
- Add scope:
connections:write - Name it
OpenClaw Gateway Token - Copy the App Token (starts with
xapp-)
Configure Bot Token:
- Go to OAuth & Permissions
- Scroll to Scopes → Bot Token Scopes
- Add these required scopes:
chat:write
channels:history
channels:read
groups:history
groups:read
im:history
im:read
im:write
mpim:history
mpim:read
users:read
app_mentions:read
reactions:read
reactions:write
pins:read
pins:write
emoji:read
files:write
- Click Install to Workspace
- Authorize the app
- Copy the Bot User OAuth Token (starts with
xoxb-)
Subscribe to events:
- Go to Event Subscriptions → Toggle ON
- Add these bot events:
message.channels
message.groups
message.im
message.mpim
app_mention
reaction_added
reaction_removed
member_joined_channel
member_left_channel
channel_rename
pin_added
pin_removed
- Click Save Changes
Enable App Home:
- Go to App Home
- Check Allow users to send Slash commands and messages from the messages tab
Step 3: Configure OpenClaw with Tokens
Option A: Environment Variables (Recommended)
export SLACK_APP_TOKEN="xapp-1-YOUR-TOKEN"
export SLACK_BOT_TOKEN="xoxb-YOUR-TOKEN"
Add these to your .bashrc or .zshrc for persistence.
Option B: Config File
Edit ~/.openclaw/openclaw.json:
{
"channels": {
"slack": {
"enabled": true,
"appToken": "xapp-1-YOUR-TOKEN",
"botToken": "xoxb-YOUR-TOKEN"
}
}
}
Start the gateway:
openclaw gateway
Expected output:
✓ Slack channel connected
✓ Socket mode active
✓ Listening for messages...
Step 4: Test Your Integration
Invite the bot to a channel:
- Open any Slack channel
- Type
/invite @OpenClaw - The bot should appear in the member list
Send a test message:
@OpenClaw what's the weather in San Francisco?
Expected response: The bot replies with current weather information (requires web search enabled).
If it fails:
- No response: Check
openclaw logsfor connection errors - Permission denied: Verify bot scopes include
chat:write - Socket timeout: Confirm
appTokenis correct and Socket Mode is enabled
Step 5: Configure Security Policies
OpenClaw defaults to pairing mode for DMs, requiring users to get approval codes before chatting.
Allow specific users for DMs:
Edit your config:
{
"channels": {
"slack": {
"dm": {
"enabled": true,
"policy": "pairing",
"allowFrom": ["U123ABC", "U456DEF"]
}
}
}
}
Get user IDs:
openclaw channels slack --list-users
Or use the Slack API: https://api.slack.com/methods/users.list/test
Approve pairing requests:
When a new user DMs the bot, they receive a pairing code. Approve it:
openclaw pairing approve slack <code>
For open DM access (not recommended for enterprise):
{
"channels": {
"slack": {
"dm": {
"policy": "open",
"allowFrom": ["*"]
}
}
}
}
Step 6: Control Channel Access
Allowlist specific channels:
{
"channels": {
"slack": {
"groupPolicy": "allowlist",
"channels": {
"C01EXAMPLE": {
"allow": true,
"requireMention": true
},
"#engineering": {
"allow": true,
"requireMention": false,
"users": ["U123ABC"],
"systemPrompt": "Be concise and technical"
}
}
}
}
}
Policy options:
open: Bot responds in all channels it's invited toallowlist: Only responds in configured channelsdisabled: Ignores all channel messages
Per-channel settings:
requireMention: Bot only responds when @mentionedusers: Restrict to specific user IDssystemPrompt: Custom instructions for this channelskills: Limit available tool integrations
Get channel IDs:
Right-click any channel → View channel details → Copy the ID from the URL:
https://app.slack.com/client/T123/C01EXAMPLE
^^^^^^^^^^
Step 7: Configure Thread Behavior
Control how the bot replies in channels:
{
"channels": {
"slack": {
"replyToMode": "off",
"replyToModeByChatType": {
"direct": "all",
"group": "first",
"channel": "off"
}
}
}
}
Threading modes:
off: Always reply in main channel (default)first: First reply creates a thread, subsequent replies in main channelall: All replies go into threads
Why this matters: Thread mode all keeps channels clean but reduces visibility. Use first for a balance.
Step 8: Add Slash Commands (Optional)
Enable /openclaw commands:
- In Slack app settings, go to Slash Commands
- Click Create New Command
- Set:
- Command:
/openclaw - Request URL: Leave blank (Socket Mode handles this)
- Short Description: "Send a message to OpenClaw"
- Command:
- Save
Configure in OpenClaw:
{
"channels": {
"slack": {
"slashCommand": {
"enabled": true,
"name": "openclaw",
"ephemeral": true
}
}
}
}
Usage:
/openclaw summarize the last 10 messages in this channel
Note: Ephemeral mode makes responses visible only to the user who ran the command.
Advanced Configuration
Multi-Account Support
Run multiple Slack workspaces:
{
"channels": {
"slack": {
"accounts": {
"workspace1": {
"name": "Engineering Team",
"appToken": "xapp-1-TOKEN1",
"botToken": "xoxb-TOKEN1"
},
"workspace2": {
"name": "Marketing Team",
"appToken": "xapp-2-TOKEN2",
"botToken": "xoxb-TOKEN2"
}
}
}
}
}
User Token for Enhanced Permissions
Some operations work better with a user token (reading history, accessing private channels):
- In Slack app → OAuth & Permissions → User Token Scopes
- Add:
channels:history,groups:history,search:read - Reinstall the app
- Copy the User OAuth Token (
xoxp-)
{
"channels": {
"slack": {
"userToken": "xoxp-YOUR-USER-TOKEN",
"userTokenReadOnly": true
}
}
}
Security note: Keep userTokenReadOnly: true unless you need the assistant to send messages as the installing user.
HTTP Mode (Alternative to Socket Mode)
For server deployments with public HTTPS endpoints:
{
"channels": {
"slack": {
"mode": "http",
"botToken": "xoxb-TOKEN",
"signingSecret": "YOUR_SIGNING_SECRET",
"webhookPath": "/slack/events"
}
}
}
When to use HTTP mode:
- You have a public-facing server with SSL
- Your infrastructure requires webhook-based integrations
- You're deploying on Railway, Render, or similar platforms
Setup:
- Get Signing Secret from Slack app → Basic Information
- In Event Subscriptions, set Request URL to
https://your-domain.com/slack/events - In Interactivity & Shortcuts, use the same URL
Verification
Test Core Functionality
1. DM test:
Message the bot directly:
Hello, can you help me?
Expected: Bot responds (if pairing approved) or sends pairing code.
2. Channel test:
In an allowed channel:
@OpenClaw what's 2+2?
Expected: Bot responds with the answer.
3. Check logs:
openclaw logs --tail 50
Look for:
[Slack] Message received from U123ABC
[Agent] Processing request...
[Slack] Response sent
Common Issues
Bot doesn't respond in channels:
- Verify the bot is invited:
/invite @OpenClaw - Check
groupPolicyis notdisabled - If using allowlist, confirm channel ID is in
channels.slack.channels
DM pairing fails:
- Run
openclaw pairing listto see pending codes - Approve with
openclaw pairing approve slack <code> - Check
dm.enabled: truein config
Connection drops:
- Socket Mode requires stable network connection
- Check
openclaw doctorfor gateway health - Verify App Token has
connections:writescope
Production Deployment
Running as a Service
macOS (launchd):
Create ~/Library/LaunchAgents/ai.openclaw.gateway.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ai.openclaw.gateway</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/openclaw</string>
<string>gateway</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/openclaw.log</string>
<key>StandardErrorPath</key>
<string>/tmp/openclaw.error.log</string>
</dict>
</plist>
Load it:
launchctl load ~/Library/LaunchAgents/ai.openclaw.gateway.plist
Linux (systemd):
Create /etc/systemd/system/openclaw.service:
[Unit]
Description=OpenClaw Gateway
After=network.target
[Service]
Type=simple
User=openclaw
WorkingDirectory=/home/openclaw
Environment="SLACK_APP_TOKEN=xapp-TOKEN"
Environment="SLACK_BOT_TOKEN=xoxb-TOKEN"
ExecStart=/usr/local/bin/openclaw gateway
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable openclaw
sudo systemctl start openclaw
Monitoring
Check gateway health:
openclaw health
Expected output:
{
"status": "healthy",
"uptime": "2d 14h 32m",
"channels": {
"slack": "connected"
},
"memory": "342MB",
"sessions": 5
}
View real-time dashboard:
openclaw dashboard
Access via browser: http://localhost:18789
What You Learned
- OpenClaw runs locally and connects to Slack via Socket Mode
- Pairing mode secures DM access without exposing your infrastructure
- Channel allowlists and user restrictions provide granular control
- Threading modes balance visibility and channel cleanliness
- Production deployments require process management (systemd/launchd)
Security considerations:
- User tokens grant broad permissions—keep them read-only
- Pairing mode prevents unauthorized DM access
- Channel allowlists prevent bot spam in public channels
- Never commit tokens to version control
Limitations:
- Requires a constantly running server (Mac Mini, VPS, or cloud instance)
- Socket Mode has a 10-connection limit per app (sufficient for most teams)
- Initial setup requires Slack admin access
Quick Reference: Slack App Manifest
Copy this manifest when creating your Slack app to auto-configure scopes:
{
"display_information": {
"name": "OpenClaw",
"description": "AI assistant for enterprise automation"
},
"features": {
"bot_user": {
"display_name": "OpenClaw",
"always_online": false
},
"app_home": {
"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": [
"chat:write",
"channels:history",
"channels:read",
"groups:history",
"groups:read",
"im:history",
"im:read",
"im:write",
"mpim:history",
"mpim:read",
"users:read",
"app_mentions:read",
"reactions:read",
"reactions:write",
"pins:read",
"pins:write",
"emoji: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"
]
}
}
}