Documentation Index
Fetch the complete documentation index at: https://mintlify.com/zeroclaw-labs/zeroclaw/llms.txt
Use this file to discover all available pages before exploring further.
Slack Channel
The Slack channel enables ZeroClaw to communicate via Slack’s API with support for both Socket Mode (WebSocket) and polling modes, thread support, and user display name resolution.Overview
- Channel Name:
slack - Transport: Socket Mode (WebSocket) or REST API polling
- Authentication: Bot token (xoxb-) + optional App token (xapp-)
- Public Port Required: No
- Supports: Text messages, threads, channel discovery, display names
Configuration
Required Settings
Complete Configuration
Environment Variables
Authentication
Creating a Slack App
- Go to Slack API
- Click “Create New App” → “From scratch”
- Name your app and select workspace
- Navigate to “OAuth & Permissions”
- Add Bot Token Scopes:
channels:historychannels:readchat:writegroups:historygroups:readim:historyim:readim:writempim:historympim:readusers:read(for display names)
- Install app to workspace
- Copy “Bot User OAuth Token” (starts with
xoxb-)
Socket Mode Setup (Recommended)
For real-time WebSocket connections:- In your Slack app, go to “Socket Mode”
- Enable Socket Mode
- Generate App-Level Token:
- Name: “ZeroClaw Socket”
- Scopes:
connections:write
- Copy token (starts with
xapp-) - Add to config:
- Subscribe to Bot Events:
message.channelsmessage.groupsmessage.immessage.mpim
User Authorization
Slack uses user IDs (format:U123ABC456):
- Click user’s profile in Slack
- Click ”⋯ More” → “Copy member ID”
Features
Transport Modes
Socket Mode (WebSocket)
Enabled whenapp_token is configured:
- Real-time message delivery
- No polling overhead
- Instant acknowledgments
- Lower latency
- Opens WebSocket connection via
apps.connections.open - Receives events in real-time
- Sends acknowledgment for each envelope
- Auto-reconnects on disconnect
- Handles ping/pong for keepalive
Polling Mode
Used whenapp_token is not set:
Behavior:
- Polls
conversations.historyevery 3 seconds - Tracks last seen timestamp per channel
- Discovers new channels every 60 seconds (when
channel_idnot set) - Rate limit aware with exponential backoff
Channel Scope
Single Channel
Multiple Channels
All Accessible Channels
- Public channels (bot is member)
- Private channels (bot is invited)
- DMs
- Multi-person DMs
Display Name Resolution
The channel automatically resolves user IDs to display names:profile.display_nameprofile.display_name_normalizedprofile.real_name_normalizedprofile.real_nameuser.real_nameuser.name- Falls back to user ID if all fail
- Cached for 6 hours
- Reduces API calls
- Automatic expiration
Thread Support
Slack threads are fully supported: Incoming:thread_tsextracted from messages- Top-level messages use
tsas thread identifier - Replies include
thread_tsfrom original message
thread_ts, reply uses same thread.
Group Chat Control
Mention-Only Mode
- Explicitly mentioned:
<@BOT_USER_ID> hello - In DMs
- Sender is in
allowed_sender_ids
VIP Senders
Rate Limit Handling
Automatic handling forconversations.history rate limits:
Detection:
- HTTP 429 status
error: "rate_limited"in response
- Parse
Retry-Afterheader (seconds or decimal) - Exponential backoff:
retry_after * 2^attempt - Cap at 120 seconds
- Add jitter (0-500ms) derived from system time
- Max 3 retries before giving up
Implementation Details
Source Location
src/channels/slack.rs (1425 lines)
Key Components
SlackChannel Struct
Socket Mode Flow
- Call
apps.connections.open→ get WebSocket URL - Connect to WebSocket
- For each envelope:
- Parse
envelope_idandtype - Handle event (if
type = "events_api") - Send acknowledgment:
{"envelope_id": "..."}
- Parse
- Handle
disconnecttype → reconnect - On error or close → wait 3s and restart
Polling Mode Flow
- Get bot user ID via
auth.test - List accessible channels via
conversations.list(if wildcard) - For each channel:
- Track cursor timestamp (bootstrap to current time)
- Fetch
conversations.historywitholdest=cursor - Process messages (newest-first, reverse to oldest-first)
- Update cursor to newest message
ts - Skip subtypes (system messages)
- Sleep 3 seconds
- Repeat
API Endpoints Used
| Method | Purpose |
|---|---|
auth.test | Get bot user ID |
conversations.list | Discover channels |
conversations.history | Fetch messages (polling) |
chat.postMessage | Send messages |
users.info | Get user display name |
apps.connections.open | Get Socket Mode URL |
Channel ID Prefixes
C...- Public channelG...- Private channel (group)D...- Direct message
C or G.
Message Deduplication
Prevents processing same message twice: Polling Mode:- Tracks
last_tsper channel - Skips messages with
ts <= last_ts - Bootstrap cursor to current time on first poll
- Tracks
last_tsper channel - Skips messages with
ts <= last_ts - Persistent across WebSocket reconnects
Error Handling
Common Errors
Invalid Token:Error Sanitization
- Authorization headers
- Token values
- Internal details
Runtime Commands
Available in Slack:/new- Start new conversation/model- Show/switch current model/models- Show/switch provider
Best Practices
- Use Socket Mode: Better performance and lower latency
- Scope Channels: Use
channel_idif possible - User IDs: More stable than usernames
- Allowlist: Start specific, expand as needed
- Display Names: Cached automatically for 6 hours
- Mention Mode: Use in public channels to reduce noise
Troubleshooting
Bot Doesn’t Respond
Check Allowlist:Slack channel listening on #channel-nameSlack: ignoring message from unauthorized user:Slack poll error:
- Invite bot to channel:
/invite @YourBot - Verify bot appears in channel members
Socket Mode Not Working
App Token Missing:connections:write
Event Subscriptions:
Enable in Slack app settings:
message.channelsmessage.groupsmessage.immessage.mpim
Polling Mode Too Slow
Use Socket Mode: Addapp_token for real-time delivery
Reduce Channels:
Set specific channel_id instead of wildcard
Display Names Not Resolving
Missing Scope: Addusers:read to bot token scopes
Cache Expiration:
Display names cached for 6 hours, then refetched
Performance
Message Throughput
Socket Mode:- Real-time delivery (<100ms)
- No polling overhead
- 3-second poll interval
- Per-channel sequential processing
Optimization Tips
- Socket Mode: Use when available
- Channel Scope: Reduce with
channel_id - Display Name Cache: 6-hour TTL reduces API calls
- Rate Limit Backoff: Automatic, no tuning needed
Security
Token Protection
- Bot tokens: Never logged
- App tokens: Never logged
- Sanitized from error messages
User Verification
- Allowlist checked before processing
- Bot self-messages always ignored
- Channel scope enforced