Slack Bots
Connect your Gravity Rail agents to Slack. Respond to @mentions, interact via DMs, and stream real-time AI responses directly in Slack channels and threads.
Managed Gravity Rail app (recommended)
- Open App Connections, add Slack, and keep Gravity Rail managed app selected.
- Choose an Agent, a Workflow, or both. With both selected, the Workflow runs and the Agent is its assistant identity.
- Click Create, choose the Slack workspace, and approve installation of the shared Gravity Rail app. Then approve the separate member connection so Agent and Manager tools can browse or post as you.
- Enable the Slack toolkit on an Agent, or select it in Manager. If a member asks to use Slack before connecting, the Chat presents the same consent flow with a Connect button.
The member grant ("post as me") and the installed app identity are separate. Use the member tools for delegated browsing/posting; use the explicit Post to Slack as App tool or inbound DMs/mentions when the resident Gravity Rail identity should speak. Both grants and their Slack workspace binding are local to this Gravity Rail workspace.
Bring your own Slack app
1. Create a Slack App
- Go to api.slack.com/apps
- Click Create New App > From an app manifest
- Select your workspace, paste the manifest below, and click Create
{
"display_information": { "name": "Your Bot Name" },
"features": {
"bot_user": { "display_name": "Your Bot Name", "always_online": false },
"app_home": {
"home_tab_enabled": false,
"messages_tab_enabled": true,
"messages_tab_read_only_enabled": false
},
"agent_view": { "agent_description": "AI agent", "suggested_prompts": [] }
},
"oauth_config": {
"scopes": {
"bot": [
"app_mentions:read",
"channels:history",
"channels:read",
"chat:write",
"chat:write.public",
"files:read",
"files:write",
"groups:history",
"groups:read",
"im:history",
"im:read",
"im:write",
"mpim:history",
"mpim:read",
"reactions:write",
"users:read",
"users:read.email"
]
}
},
"settings": {
"event_subscriptions": {
"bot_events": [
"app_mention",
"app_context_changed",
"app_home_opened",
"message.channels",
"message.groups",
"message.im",
"message.mpim"
]
},
"org_deploy_enabled": true,
"token_rotation_enabled": false
}
}
DMs require the messages tab. Without the
app_homeblock above (messages_tab_enabled: true,messages_tab_read_only_enabled: false), Slack disables the DM composer and users see "Slack couldn't send this message." If you created the app from an older manifest, enable it under App Home → Show Tabs → Messages Tab — no reinstall needed.
- Note your Signing Secret from Basic Information
- Note your Client ID and Client Secret from OAuth & Permissions
2. Add Bot in Gravity Rail
- Go to Settings > Slack
- Click Add Slack App
- Enter:
- App Name
- Workflow (select the Workflow that will handle inbound messages)
- Signing Secret
- Client ID
- Client Secret
- Save
3. Configure Slack App URLs
In your Slack app settings at api.slack.com:
-
Event Subscriptions > Enable Events > set Request URL to:
https://api.gravityrail.com/api/v2/w/{workspaceUuid}/app-connections/slack/events -
OAuth & Permissions > add both Redirect URLs:
https://api.gravityrail.com/api/v2/w/{workspaceUuid}/app-connections/slack/oauth/callback(bot)https://api.gravityrail.com/api/v2/w/{workspaceUuid}/app-connections/slack/oauth/user/callback(user)
Replace {workspaceUuid} with your workspace UUID. These URLs are also shown when you run gr slack-apps get.
4. Install to Slack
- Go to the Connect tab in your app configuration
- Click Install to Slack
- Authorize the requested permissions
Your bot is now live! Try @mentioning it in a channel.
Response Modes
| Mode | When Bot Responds |
|---|---|
| Mentions (default) | Only when @mentioned |
| Auto | AI decides based on context |
| Off | DMs and slash commands only |
Set in your app's Behavior tab.
Auto Mode
In Auto mode, the bot uses AI to decide when to respond. You can customize the decision criteria with the Respond When field.
Requirements for Auto mode:
- Subscribe to
message.channelsandmessage.groupsevents in Slack - Invite the bot to channels with
/invite @botname
Streaming Responses
Slack bots support real-time streaming with "Thinking..." indicators:
- Enable Slack's Agent messaging feature in your Slack app settings
- Grant the
chat:writescope - Reinstall the app if you added the scope after installation
When Reply in Threads is enabled, Slack supports status in channel threads and DMs. Gravity Rail uses the incoming message timestamp as the thread root for a new DM. The bot starts with a generic "Thinking..." status, then replaces it with bounded Agent-authored progress when a tool-taking step includes visible narration. Agent messaging is required for status in Slack's DM Agent experience; channel-thread status uses chat:write without that feature.
Account Linking
Link Slack users to Gravity Rail members for personalized responses.
Auto-Link: Matches users by verified email automatically.
Manual: Users can link their accounts through Settings > Slack > Connect.
Linked accounts get responses personalized with member data.
Required OAuth Scopes
All 17 scopes are needed for full functionality:
| Scope | Purpose |
|---|---|
app_mentions:read | Read @mentions |
channels:history | Read public channel messages |
channels:read | View public channel info |
chat:write | Send messages and update Agent status |
chat:write.public | Post to public channels without being invited |
files:read | Read files shared with the bot |
files:write | Upload files from Agent responses |
groups:history | Read private channel messages |
groups:read | View private channel info |
im:history | Read DM messages |
im:read | View DM info |
im:write | Start DMs |
mpim:history | Read group DM messages |
mpim:read | View group DM info |
reactions:write | Add message reactions |
users:read | View workspace users |
users:read.email | View user emails (for account linking) |
Settings Reference
General
| Setting | Description |
|---|---|
| App Name | Display name for this configuration |
| Workflow | Workflow that handles interactions |
| Signing Secret | From Slack Basic Information |
| Client ID | For OAuth flows |
| Client Secret | For OAuth flows |
Behavior
| Setting | Description |
|---|---|
| Respond Mode | mentions, auto, or off |
| Respond When | Custom AI prompt for auto mode decisions |
| Reply in Threads | Whether responses go in threads |
| Allow DMs | Enable direct message interactions |
| Read Channel History | Expose tools that list channels and read bounded history available to the Slack app |
| Post to Slack Channels | Expose tools that list channels and post to channels available to the Slack app; omitting a thread posts at the channel root |
The channel tools are available only on Workflows invoked from Slack. Gravity Rail does not maintain a second channel allow-list for these tools: Slack OAuth scopes, channel membership, and workspace policy determine which channels can be listed, read, or posted to.
Scopes are what these toggles spend. Listing needs channels:read (public) and
groups:read (private). Reading history needs channels:history / groups:history,
and Slack returns not_in_channel for any channel the bot has not joined — private
channels always require an invite. Posting needs chat:write, plus
chat:write.public to reach a public channel the bot was never invited to; private
channels still require an invite. Adding a scope to an app that is already
installed does nothing until the app is reinstalled — Slack issues the bot token
with the scopes granted at install time, and the existing token keeps its old set.
Advanced
| Setting | Description |
|---|---|
| Allowed Channels | Restrict bot to specific channel IDs |
| Socket Mode | Use WebSocket instead of HTTP (for firewalls) |
Tips
- Test in a private channel first before deploying widely
- Use threads to keep conversations organized
- Enable streaming for a better user experience
- One app, many workspaces - install the same app to multiple Slack workspaces
Common Issues
Bot not responding to messages
Check event subscriptions, verify the signing secret matches, and ensure the bot is invited to the channel
Thread messages not received in Auto mode
Subscribe to
message.channelsandmessage.groupsevents, then reinstall the app
Streaming not working
Enable Agent messaging in Slack, grant
chat:write, and reinstall if the scope was newly added
"Thinking..." indicator not showing
Enable Reply in Threads and verify
chat:write. For DMs, also enable Agent messaging; Gravity Rail supplies the incoming message timestamp as their thread root.
Outbound DMs (Agent-Initiated)
Agents can open a Slack DM with a member proactively — without waiting for the member to message first. This is useful for routines that need to reach out (appointment reminders, follow-ups, alerts).
Prerequisites
- The Slack app must be installed and the agent member configured (see Quick Start above).
- The target member must have their Slack account linked to their Gravity Rail account (see Account Linking above). The link stores the member's Slack user ID so the bot knows who to DM.
- The
im:writeOAuth scope must be granted (included in the manifest above).
EventRule Configuration
Create an EventRule with action chat:create and set channel to slack:
{
"action": "chat:create",
"channel": "slack",
"messageTemplate": "Hi {{member.first_name}}, this is your reminder…"
}
messageTemplate: The opening message sent to the member. Supports template variables. If omitted,message/initialUserMessageis used (legacy Slack field), then the workflow's initial task content.channel:slackroutes the outbound chat through the Slack DM channel instead of SMS or email.
The EventRule can be triggered by any inbound event (form submission, routine schedule, workflow transition, etc.).
Thread-Reuse Behavior
If an active DM thread already exists for the same Slack app, member, and workflow, the new message is posted into that existing thread — no new Chat is created. This keeps related messages together and avoids spamming the member with separate conversations.
A new DM channel is opened (via conversations.open) only when no live thread exists. The opening message's Slack timestamp is captured and the Chat + SlackThread record are created with the same machinery used for inbound messages, so member replies flow through the existing inbound event handler seamlessly.
Error Handling
If the outbound DM cannot be delivered (member not linked, app not installed, missing scopes), the EventRule fails with a typed error rather than silently reporting success. Check the assignment activity log for details.
Related
- Channels — Overview of all communication channels
- Discord Bots — Deploy AI bots in Discord
- Workflows — Build the conversation flows that power your bot