Install
openclaw skills install @gaolfun/slack-integrationSend messages, upload files, list channels, query users, manage scheduled messages, search messages, and set bot status in Slack using the Web API.
openclaw skills install @gaolfun/slack-integrationName: slack-integration
Description: Send messages, list channels, query users, upload files, and manage scheduled messages in Slack via the Web API. All in English.
Trigger Phrases: See Section 2.
Capabilities: See Section 3.
Prerequisites: See Section 4.
Output Format: See Section 6.
Caveats: See Section 9.
The following natural English phrases activate this skill. The user does not need to use the exact wording — any reasonable paraphrase of these intents will trigger it.
This skill is modular. Each capability maps to one or more Slack Web API methods. The skill performs only the capability requested; it never combines unrelated operations.
Slack API: POST https://slack.com/api/chat.postMessage
Auth: Bot Token (xoxb-...)
Scope required: chat:write
Send a plain-text message to a public channel, private channel, or DM. The target can be specified by channel name (#general), channel ID (C0123456789), or user ID (U0123456789) for DMs.
Required arguments:
channel — channel name, ID, or user IDtext — message text (max 40,000 characters)Optional arguments:
username — display name override for the boticon_emoji — emoji icon (e.g., :robot_face:)thread_ts — to reply in a thread, pass the parent message's tsSlack API: POST https://slack.com/api/chat.postMessage
Auth: Bot Token
Scope required: chat:write
Send a richly formatted message using Slack Block Kit (sections, dividers, buttons, images, etc.). Pass a JSON array of blocks as the blocks argument. The skill will validate the block structure before sending.
Required arguments:
channel — channel name, ID, or user IDblocks — JSON array of Block Kit objectsOptional arguments:
text — plain-text fallback (required by Slack if using blocks, used in notifications/previews)Slack API: GET https://slack.com/api/conversations.list
Auth: Bot Token
Scope required: channels:read (public), groups:read (private), im:read (DMs), mpim:read (MPIMs)
Retrieve a paginated list of all channels the bot has access to. Supports filtering by type (public_channel, private_channel, im, mpim).
Optional arguments:
types — comma-separated list: public_channel,private_channel,im,mpimlimit — results per page (default 200, max 1000)cursor — pagination cursor from a previous responseReturns: An array of channel objects with id, name, is_private, num_members, topic, purpose.
Slack API: GET https://slack.com/api/users.info
Auth: Bot Token
Scope required: users:read
Look up a Slack user by their user ID. Returns profile, status, timezone, and workspace info.
Required arguments:
user — Slack user ID (e.g., U0123456789)Alternative lookup by email:
GET https://slack.com/api/users.lookupByEmail?email=<email>users:readReturns: User object with id, name, real_name, profile (avatar, title, email, phone), status, tz.
Slack API: POST https://slack.com/api/files.uploadV2
Auth: Bot Token
Scope required: files:write
Upload a file to a Slack channel or DM. The file can be referenced by local path (the skill will read and upload it) or by URL.
Required arguments:
filename — name of the file to display in Slackchannel — target channel or user IDfile — local file path or HTTPS URLOptional arguments:
title — file titleinitial_comment — comment to include with the filefiletype — MIME type hint (e.g., pdf, png, json)Note: Files are uploaded in a single request with multipart/form-data. Maximum file size is 1 GB for paid workspaces, 256 MB for free.
Slack APIs:
POST https://slack.com/api/chat.scheduleMessage — createGET https://slack.com/api/chat.scheduledMessages.list — listDELETE https://slack.com/api/chat.deleteScheduledMessage — deleteAuth: Bot Token
Scopes required: chat:write (post), chat:write (list/delete)
Create a message to be delivered at a specified time. Delete or list pending scheduled messages.
Create required arguments:
channel — target channeltext — message textpost_at — Unix timestamp or ISO 8601 datetime string for delivery timeCreate optional arguments:
blocks — Block Kit JSON arraythread_ts — reply in threadList required arguments: none (returns all scheduled messages for the app)
List optional arguments:
channel — filter to a specific channellimit — max results (default 100)Delete required arguments:
channel — channel ID where the scheduled message will postscheduled_message_id — ID returned from scheduleMessageSlack API: GET https://slack.com/api/search.messages
Auth: Bot Token
Scope required: search:read
Search message history across all visible channels.
Required arguments:
query — search query string (supports Slack search operators like from:@user, in:#channel, has:file, on:2024-01-15)Optional arguments:
count — results per page (default 100, max 100)page — page numbersort — score (default) or timestampsort_dir — asc or descReturns: Matches with message text, channel, user, timestamp, and highlights.
Slack API: POST https://slack.com/api/users.profile.set
Auth: Bot Token
Scope required: users.profile:write
Set the bot user's custom status emoji and status text. Also used to set away/dnd status via users.setPresence.
Required arguments for status:
profile — JSON object with status_emoji and status_textRequired arguments for presence:
presence — auto (active) or away (away)You must create a Slack App with a Bot Token before using this skill.
| Capability | Required Scopes |
|---|---|
| Send plain message | chat:write |
| Send Block Kit message | chat:write |
| List channels | channels:read, groups:read, im:read, mpim:read |
| Get user info | users:read |
| Lookup by email | users:read |
| Upload file | files:write |
| Scheduled messages | chat:write |
| Search messages | search:read |
| Set status | users.profile:write, users:write |
xoxb-...)Add to your OpenClaw environment config (~/.openclaw/.env or as OpenClaw config vars):
SLACK_BOT_TOKEN=xoxb-your-bot-token-here
SLACK_SIGNING_SECRET=your-signing-secret-here # for webhook verification (optional)
For interactive blocks (buttons, modals, shortcuts):
/webhooks/slack/interactiveThese helper patterns should be used by the AI when executing any Slack API call.
# Always include the Authorization header with the Bot Token
curl -s -X POST 'https://slack.com/api/chat.postMessage' \
-H 'Authorization: Bearer xoxb-your-token' \
-H 'Content-Type: application/json; charset=utf-8' \
-d '{
"channel": "#general",
"text": "Hello from OpenClaw!"
}'
Every Slack API response includes an ok boolean field:
ok: true → success, proceedok: false → failure, check error fieldAlways validate before reporting to the user:
If response.ok == false:
→ Report error: "Failed to send message. Slack error: [error_code]. Suggestion: [fix]"
Slack rate limits most APIs at 1,000 calls per minute per workspace. For some endpoints (e.g., chat.postMessage), it's 1 per second per channel.
Best practice: When sending many messages in sequence, add a sleep 1 between calls per channel.
Bot Tokens do not expire unless manually revoked. No refresh logic needed.
✅ Message sent to #channel-name
📝 Text: "Hello team, the deployment is complete."
👤 Sent as: OpenClaw Bot
🕐 Timestamp: 2026-07-04 20:35:12 UTC
🔗 View in Slack: https://slack.com/archives/C0123456789/p1234567890
✅ Found 8 channels
#engineering (42 members, public) — "Engineering team discussions"
#general (128 members, public) — "Company-wide announcements"
#random (89 members, public) — "Non-work banter"
...
✅ User found: Sarah Chen
🆔 User ID: U0123456789
📧 Email: sarah.chen@company.com
💼 Title: Senior Software Engineer
🕐 Timezone: America/Los_Angeles
🟢 Status: active
❌ Failed to send message
Reason: "not_in_channel" — Bot is not a member of #channel-name
Fix: Add the bot to the channel first (/invite @OpenClaw Bot in Slack)
❌ Rate limited by Slack
Retry after: ~1 second
Suggestion: Space out message sends by at least 1 second per channel
User: "Send a message to #engineering saying the new build is ready for testing"
AI: "Sure, posting to #engineering now..."
Execute:
#engineeringchat.postMessage with text "The new build v2.4.1 is ready for testing. Please review here: https://ci.example.com/builds/241"AI: "✅ Message sent to #engineering 📝 The new build v2.4.1 is ready for testing. Please review here: https://ci.example.com/builds/241 🕐 Sent at 20:35 UTC"
User: "Who is alex.johnson@company.com on Slack?"
AI: "Looking up alex.johnson@company.com..."
Execute:
users.lookupByEmail?email=alex.johnson@company.comAI: "✅ Found it! 👤 Alex Johnson 🆔 U9876543210 📧 alex.johnson@company.com 💼 Product Manager 🏢 Operations 🕐 Timezone: America/New_York"
User: "Schedule a message in #releases for tomorrow at 9am reminding the team about the deploy"
AI: "Scheduling a message for tomorrow at 9:00 AM UTC..."
Execute:
chat.scheduleMessage with channel #releases, text, and post_at timestampAI: "✅ Scheduled message created 📢 Channel: #releases 📝 'Friendly reminder: the production deploy is scheduled for 2pm UTC today. Please ensure all PRs are reviewed and your feature flags are configured. — The OpenClaw Bot' ⏰ Scheduled for: 2026-07-05 09:00:00 UTC 🆔 Scheduled ID: Q1234567890 (save this if you need to cancel) 🔗 Will appear at: https://slack.com/archives/C0123456789"
Step 1: Create a Slack App
Step 2: Configure Bot Token Scopes
xoxb-Step 3: Enable Necessary App Features
For each feature you want to use, enable it in the app:
chat:write scopefiles:write scope, reinstall appsearch:read scope, reinstall appStep 4: Configure OpenClaw
Add to ~/.openclaw/.env:
SLACK_BOT_TOKEN=xoxb-1111111111111-2222222222222-ABCdefGHIjklMNOpqrSTUvwxYZ
SLACK_SIGNING_SECRET=4a7b9c2d8e1f3g6h5j0k2l4m6n8p9q
Then restart OpenClaw to load the new environment variables.
Step 5: Add the Bot to a Channel
/invite and select Add apps to this channelAlternatively, the bot can be invited programmatically via conversations.invite (requires channels:write scope).
Step 6: Test the Setup
Try: "List all channels in Slack" — you should get back a list of channels the bot has access to.
| Error Code | Meaning | Fix |
|---|---|---|
not_in_channel | Bot not added to target channel | Invite bot via /invite @AppName in Slack |
channel_not_found | Channel name/ID invalid | Use channel ID (C0123456789) not name |
users_not_found | Email lookup failed | Check email spelling; user may not be in workspace |
file_incorrect_permissions | File read failed | Ensure file path is accessible to OpenClaw process |
missing_scope | Token missing required scope | Reinstall app with needed scope in OAuth & Permissions |
token_revoked | Bot token was invalidated | Regenerate token in Slack App dashboard |
rate_limited | Too many API calls | Wait and retry with 1-second delay per channel |
| Endpoint | Limit |
|---|---|
chat.postMessage | 1/second per channel |
conversations.list | 1/minute per workspace |
users.list | 1/minute per workspace |
| Most other methods | ~1,000/minute per workspace |
Always implement a 1-second sleep between consecutive chat.postMessage calls to the same channel.
C0123456789) over channel name (#engineering)conversations.list outputxoxb-...) are permanent and non-expiring unless manually revoked<@U0123456789> for user mention, <#C0123456789> for channel link, <!channel> for @channel, <!here> for @hereparse.error in the responsetext fallback field when sending blocks (required for notifications)