Reference docs fixes: - cli-commands.md: remove non-existent --provider alibaba, add hermes profile/completion/plugins/mcp to top-level table, add --profile/-p global flag, add --source chat option - slash-commands.md: add /yolo and /commands, fix /q alias conflict (resolves to /queue not /quit), add missing aliases (/bg, /set-home, /reload_mcp, /gateway) - toolsets-reference.md: fix hermes-api-server (not same as hermes-cli, omits clarify/send_message/text_to_speech) - profile-commands.md: fix show name required not optional, --clone-from not --from, add --remove/--name to alias, fix alias path, fix export/ import arg types, remove non-existent fish completion - tools-reference.md: add EXA_API_KEY to web tools requires_env - mcp-config-reference.md: add auth key for OAuth, tool name sanitization - environment-variables.md: add EXA_API_KEY, update provider values - plugins.md: remove non-existent ctx.register_command(), add ctx.inject_message() Feature docs additions: - security.md: add /yolo mode, approval modes (manual/smart/off), configurable timeout, expanded dangerous patterns table - cron.md: add wrap_response config, [SILENT] suppression - mcp.md: add dynamic tool discovery, MCP sampling support - cli.md: add Ctrl+Z suspend, busy_input_mode, tool_preview_length - docker.md: add skills/credential file mounting Messaging platform docs: - telegram.md: add webhook mode, DoH fallback IPs - slack.md: add multi-workspace OAuth support - discord.md: add DISCORD_IGNORE_NO_MENTION - matrix.md: add MSC3245 native voice messages - feishu.md: expand from 129 to 365 lines (encrypt key, verification token, group policy, card actions, media, rate limiting, markdown, troubleshooting) - wecom.md: expand from 86 to 264 lines (per-group allowlists, media, AES decryption, stream replies, reconnection, troubleshooting) Configuration docs: - quickstart.md: add DeepSeek, Copilot, Copilot ACP providers - configuration.md: add DeepSeek provider, Exa web backend, terminal env_passthrough/images, browser.command_timeout, compression params, discord config, security/tirith config, timezone, auxiliary models 21 files changed, ~1000 lines added
12 KiB
sidebar_position, title, description
| sidebar_position | title | description |
|---|---|---|
| 4 | Slack | Set up Hermes Agent as a Slack bot using Socket Mode |
Slack Setup
Connect Hermes Agent to Slack as a bot using Socket Mode. Socket Mode uses WebSockets instead of public HTTP endpoints, so your Hermes instance doesn't need to be publicly accessible — it works behind firewalls, on your laptop, or on a private server.
:::warning Classic Slack Apps Deprecated Classic Slack apps (using RTM API) were fully deprecated in March 2025. Hermes uses the modern Bolt SDK with Socket Mode. If you have an old classic app, you must create a new one following the steps below. :::
Overview
| Component | Value |
|---|---|
| Library | slack-bolt / slack_sdk for Python (Socket Mode) |
| Connection | WebSocket — no public URL required |
| Auth tokens needed | Bot Token (xoxb-) + App-Level Token (xapp-) |
| User identification | Slack Member IDs (e.g., U01ABC2DEF3) |
Step 1: Create a Slack App
- Go to https://api.slack.com/apps
- Click Create New App
- Choose From scratch
- Enter an app name (e.g., "Hermes Agent") and select your workspace
- Click Create App
You'll land on the app's Basic Information page.
Step 2: Configure Bot Token Scopes
Navigate to Features → OAuth & Permissions in the sidebar. Scroll to Scopes → Bot Token Scopes and add the following:
| Scope | Purpose |
|---|---|
chat:write |
Send messages as the bot |
app_mentions:read |
Detect when @mentioned in channels |
channels:history |
Read messages in public channels the bot is in |
channels:read |
List and get info about public channels |
groups:history |
Read messages in private channels the bot is invited to |
im:history |
Read direct message history |
im:read |
View basic DM info |
im:write |
Open and manage DMs |
users:read |
Look up user information |
files:write |
Upload files (images, audio, documents) |
:::caution Missing scopes = missing features
Without channels:history and groups:history, the bot will not receive messages in channels —
it will only work in DMs. These are the most commonly missed scopes.
:::
Optional scopes:
| Scope | Purpose |
|---|---|
groups:read |
List and get info about private channels |
Step 3: Enable Socket Mode
Socket Mode lets the bot connect via WebSocket instead of requiring a public URL.
- In the sidebar, go to Settings → Socket Mode
- Toggle Enable Socket Mode to ON
- You'll be prompted to create an App-Level Token:
- Name it something like
hermes-socket(the name doesn't matter) - Add the
connections:writescope - Click Generate
- Name it something like
- Copy the token — it starts with
xapp-. This is yourSLACK_APP_TOKEN
:::tip You can always find or regenerate app-level tokens under Settings → Basic Information → App-Level Tokens. :::
Step 4: Subscribe to Events
This step is critical — it controls what messages the bot can see.
- In the sidebar, go to Features → Event Subscriptions
- Toggle Enable Events to ON
- Expand Subscribe to bot events and add:
| Event | Required? | Purpose |
|---|---|---|
message.im |
Yes | Bot receives direct messages |
message.channels |
Yes | Bot receives messages in public channels it's added to |
message.groups |
Recommended | Bot receives messages in private channels it's invited to |
app_mention |
Yes | Prevents Bolt SDK errors when bot is @mentioned |
- Click Save Changes at the bottom of the page
:::danger Missing event subscriptions is the #1 setup issue
If the bot works in DMs but not in channels, you almost certainly forgot to add
message.channels (for public channels) and/or message.groups (for private channels).
Without these events, Slack simply never delivers channel messages to the bot.
:::
Step 5: Enable the Messages Tab
This step enables direct messages to the bot. Without it, users see "Sending messages to this app has been turned off" when trying to DM the bot.
- In the sidebar, go to Features → App Home
- Scroll to Show Tabs
- Toggle Messages Tab to ON
- Check "Allow users to send Slash commands and messages from the messages tab"
:::danger Without this step, DMs are completely blocked Even with all the correct scopes and event subscriptions, Slack will not allow users to send direct messages to the bot unless the Messages Tab is enabled. This is a Slack platform requirement, not a Hermes configuration issue. :::
Step 6: Install App to Workspace
- In the sidebar, go to Settings → Install App
- Click Install to Workspace
- Review the permissions and click Allow
- After authorization, you'll see a Bot User OAuth Token starting with
xoxb- - Copy this token — this is your
SLACK_BOT_TOKEN
:::tip If you change scopes or event subscriptions later, you must reinstall the app for the changes to take effect. The Install App page will show a banner prompting you to do so. :::
Step 7: Find User IDs for the Allowlist
Hermes uses Slack Member IDs (not usernames or display names) for the allowlist.
To find a Member ID:
- In Slack, click on the user's name or avatar
- Click View full profile
- Click the ⋮ (more) button
- Select Copy member ID
Member IDs look like U01ABC2DEF3. You need your own Member ID at minimum.
Step 8: Configure Hermes
Add the following to your ~/.hermes/.env file:
# Required
SLACK_BOT_TOKEN=xoxb-your-bot-token-here
SLACK_APP_TOKEN=xapp-your-app-token-here
SLACK_ALLOWED_USERS=U01ABC2DEF3 # Comma-separated Member IDs
# Optional
SLACK_HOME_CHANNEL=C01234567890 # Default channel for cron/scheduled messages
SLACK_HOME_CHANNEL_NAME=general # Human-readable name for the home channel (optional)
Or run the interactive setup:
hermes gateway setup # Select Slack when prompted
Then start the gateway:
hermes gateway # Foreground
hermes gateway install # Install as a user service
sudo hermes gateway install --system # Linux only: boot-time system service
Step 9: Invite the Bot to Channels
After starting the gateway, you need to invite the bot to any channel where you want it to respond:
/invite @Hermes Agent
The bot will not automatically join channels. You must invite it to each channel individually.
How the Bot Responds
Understanding how Hermes behaves in different contexts:
| Context | Behavior |
|---|---|
| DMs | Bot responds to every message — no @mention needed |
| Channels | Bot only responds when @mentioned (e.g., @Hermes Agent what time is it?). In channels, Hermes replies in a thread attached to that message. |
| Threads | If you @mention Hermes inside an existing thread, it replies in that same thread. |
:::tip In channels, always @mention the bot. Simply typing a message without mentioning it will be ignored. This is intentional — it prevents the bot from responding to every message in busy channels. :::
Home Channel
Set SLACK_HOME_CHANNEL to a channel ID where Hermes will deliver scheduled messages,
cron job results, and other proactive notifications. To find a channel ID:
- Right-click the channel name in Slack
- Click View channel details
- Scroll to the bottom — the Channel ID is shown there
SLACK_HOME_CHANNEL=C01234567890
Make sure the bot has been invited to the channel (/invite @Hermes Agent).
Multi-Workspace Support
Hermes can connect to multiple Slack workspaces simultaneously using a single gateway instance. Each workspace is authenticated independently with its own bot user ID.
Configuration
Provide multiple bot tokens as a comma-separated list in SLACK_BOT_TOKEN:
# Multiple bot tokens — one per workspace
SLACK_BOT_TOKEN=xoxb-workspace1-token,xoxb-workspace2-token,xoxb-workspace3-token
# A single app-level token is still used for Socket Mode
SLACK_APP_TOKEN=xapp-your-app-token
Or in ~/.hermes/config.yaml:
platforms:
slack:
token: "xoxb-workspace1-token,xoxb-workspace2-token"
OAuth Token File
In addition to tokens in the environment or config, Hermes also loads tokens from an OAuth token file at:
~/.hermes/platforms/slack/slack_tokens.json
This file is a JSON object mapping team IDs to token entries:
{
"T01ABC2DEF3": {
"token": "xoxb-workspace-token-here",
"team_name": "My Workspace"
}
}
Tokens from this file are merged with any tokens specified via SLACK_BOT_TOKEN. Duplicate tokens are automatically deduplicated.
How it works
- The first token in the list is the primary token, used for the Socket Mode connection (AsyncApp).
- Each token is authenticated via
auth.teston startup. The gateway maps eachteam_idto its ownWebClientandbot_user_id. - When a message arrives, Hermes uses the correct workspace-specific client to respond.
- The primary
bot_user_id(from the first token) is used for backward compatibility with features that expect a single bot identity.
Voice Messages
Hermes supports voice on Slack:
- Incoming: Voice/audio messages are automatically transcribed using the configured STT provider: local
faster-whisper, Groq Whisper (GROQ_API_KEY), or OpenAI Whisper (VOICE_TOOLS_OPENAI_KEY) - Outgoing: TTS responses are sent as audio file attachments
Troubleshooting
| Problem | Solution |
|---|---|
| Bot doesn't respond to DMs | Verify message.im is in your event subscriptions and the app is reinstalled |
| Bot works in DMs but not in channels | Most common issue. Add message.channels and message.groups to event subscriptions, reinstall the app, and invite the bot to the channel with /invite @Hermes Agent |
| Bot doesn't respond to @mentions in channels | 1) Check message.channels event is subscribed. 2) Bot must be invited to the channel. 3) Ensure channels:history scope is added. 4) Reinstall the app after scope/event changes |
| Bot ignores messages in private channels | Add both the message.groups event subscription and groups:history scope, then reinstall the app and /invite the bot |
| "Sending messages to this app has been turned off" in DMs | Enable the Messages Tab in App Home settings (see Step 5) |
| "not_authed" or "invalid_auth" errors | Regenerate your Bot Token and App Token, update .env |
| Bot responds but can't post in a channel | Invite the bot to the channel with /invite @Hermes Agent |
| "missing_scope" error | Add the required scope in OAuth & Permissions, then reinstall the app |
| Socket disconnects frequently | Check your network; Bolt auto-reconnects but unstable connections cause lag |
| Changed scopes/events but nothing changed | You must reinstall the app to your workspace after any scope or event subscription change |
Quick Checklist
If the bot isn't working in channels, verify all of the following:
- ✅
message.channelsevent is subscribed (for public channels) - ✅
message.groupsevent is subscribed (for private channels) - ✅
app_mentionevent is subscribed - ✅
channels:historyscope is added (for public channels) - ✅
groups:historyscope is added (for private channels) - ✅ App was reinstalled after adding scopes/events
- ✅ Bot was invited to the channel (
/invite @Hermes Agent) - ✅ You are @mentioning the bot in your message
Security
:::warning
Always set SLACK_ALLOWED_USERS with the Member IDs of authorized users. Without this setting,
the gateway will deny all messages by default as a safety measure. Never share your bot tokens —
treat them like passwords.
:::
- Tokens should be stored in
~/.hermes/.env(file permissions600) - Rotate tokens periodically via the Slack app settings
- Audit who has access to your Hermes config directory
- Socket Mode means no public endpoint is exposed — one less attack surface