Slack Integration
Otto operates as a full Slack bot, allowing your team to assign tasks, receive results, ask follow-up questions, upload files, schedule work, and set reminders -- all without leaving Slack.
Otto operates as a full Slack bot, allowing your team to assign tasks, receive results, ask follow-up questions, upload files, schedule work, and set reminders -- all without leaving Slack.
What Otto Can Do in Slack
- Receive tasks via @mentions or the
/ottoslash command - Reply in threads with progress updates and final results
- Send direct messages when it needs human input or wants to deliver results
- Upload files (documents, reports, spreadsheets) directly into Slack threads
- Schedule tasks to run at a future time
- Set reminders for yourself or teammates, including recurring reminders
- Auto-onboard when invited to a new channel, syncing members and learning context
- Track membership as users join or leave channels
Setup
Otto ships an App Manifest that pre-configures all scopes, events, slash commands, and interactivity in one step.
1. Create the Slack App from the Manifest
- Go to api.slack.com/apps and click Create New App → From an app manifest.
- Select your workspace.
- Paste the contents of
slack-manifest.yamlfrom the Otto repo root. - Review the configuration and click Create.
2. Set Your Backend URL
The manifest uses YOUR_OTTO_URL as a placeholder. After creating the app, replace it with your actual Otto backend URL in three places:
- Event Subscriptions → Request URL:
https://your-domain.com/slack/dm_response - Interactivity & Shortcuts → Request URL:
https://your-domain.com/slack/interactive - Slash Commands →
/ottoRequest URL:https://your-domain.com/slack/command
3. Install the App
Click Install to Workspace under OAuth & Permissions. After authorization, copy:
- The Bot User OAuth Token (starts with
xoxb-) from OAuth & Permissions - The Signing Secret from Basic Information
What the Manifest Configures
The manifest sets up everything Otto needs automatically. For reference, here is what it includes.
Bot Token Scopes (21 scopes)
Messaging & Actions:
| Scope | Purpose |
|---|---|
chat:write | Send messages and thread replies as @Otto |
chat:write.public | Send messages to channels Otto hasn't been invited to |
im:write | Start and send direct messages to users |
mpim:write | Start and send group direct messages |
channels:join | Join public channels in the workspace |
files:write | Upload, edit, and delete files (reports, documents, etc.) |
reactions:write | Add emoji reactions (used for status indicators like eyes, checkmark) |
commands | Register the /otto slash command |
Reading Messages & History:
| Scope | Purpose |
|---|---|
app_mentions:read | View messages that @mention Otto |
channels:history | Read message history in public channels Otto is in |
groups:history | Read message history in private channels Otto is in |
im:history | Read direct message history with Otto |
mpim:history | Read group direct message history |
Channel & User Info:
| Scope | Purpose |
|---|---|
channels:read | List public channels and their metadata |
groups:read | List private channels Otto has been invited to |
im:read | View basic info about direct message conversations |
mpim:read | View basic info about group direct message conversations |
files:read | Access files shared in channels and conversations |
users:read | Discover workspace members and map them to Otto users |
users:read.email | Map Slack users to Otto users by email address |
users.profile:read | View profile details (display name, avatar) for richer user context |
Event Subscriptions
| Event | Trigger |
|---|---|
app_mention | Someone @mentions Otto in a channel |
message.im | Someone sends Otto a DM |
member_joined_channel | Otto or a user joins a channel (triggers auto-onboarding) |
member_left_channel | A user leaves a channel Otto is in |
channel_deleted | A channel Otto was in is deleted |
Slash Command
/otto— Assign a task to Otto from any channel
Interactivity
Enabled for the "Stop Reminders" button and other interactive features.
Manual Setup (Without Manifest)
If you prefer to configure the Slack app manually instead of using the manifest, follow these steps.
1. Create a Slack App
- Go to api.slack.com/apps and click Create New App.
- Choose From scratch, give it a name (e.g., "Otto"), and select your workspace.
2. Configure Bot Token Scopes
Under OAuth & Permissions, add all the bot token scopes listed in the Bot Token Scopes section above.
3. Enable Events
Under Event Subscriptions, enable events and set the request URL to:
Subscribe to the bot events listed in the Event Subscriptions section above.
4. Create a Slash Command
Under Slash Commands, create a new command:
- Command:
/otto - Request URL:
https://your-domain.com/slack/command - Short Description: Assign a task to Otto
- Usage Hint:
[describe your task]
5. Enable Interactive Components
Under Interactivity & Shortcuts, enable interactivity and set the request URL to:
This enables the "Stop Reminders" button and other interactive features.
6. Install the App
Click Install to Workspace under OAuth & Permissions. After authorization, copy the Bot User OAuth Token (xoxb-) and Signing Secret (from Basic Information).
Configuration
Set the following environment variables in your Otto backend:
| Variable | Required | Description |
|---|---|---|
SLACK_MCP_XOXB_TOKEN | Yes | Bot User OAuth Token (xoxb-...). This is the primary token used for all Slack API calls. |
SLACK_SIGNING_SECRET | Yes | Signing secret from your Slack app's Basic Information page. Used to verify incoming requests are from Slack. |
SLACK_BOT_USER_ID | No | The bot's Slack user ID. Used to detect self-mentions and avoid loops. If not set, Otto attempts to detect it automatically. |
Example .env configuration:
There are also legacy token variables (SLACK_BOT_TOKEN, SLACK_MCP_XOXC_TOKEN, SLACK_MCP_XOXD_TOKEN) that appear in Docker Compose files. For new installations, only SLACK_MCP_XOXB_TOKEN and SLACK_SIGNING_SECRET are needed.
Usage Patterns
Mentioning Otto in a Channel
Type @Otto followed by your task in any channel where Otto has been invited:
Otto replies in a thread with progress updates and the final result.
Using the Slash Command
Use /otto from any channel:
Otto acknowledges the command immediately and posts results when finished.
Direct Messages
Send Otto a DM for private tasks:
Responding to Questions
When Otto needs clarification during a task, it sends a DM or thread reply with its question. Simply reply in the same thread or DM to continue.
File Uploads
Share a file in a DM or alongside an @mention. Otto downloads the file to your sandbox and creates a task to process it:
Scheduling and Reminders
Scheduled Tasks
Schedule a task to run at a future time:
Supported time expressions:
- Relative:
in X hours,in X minutes,in X days,in X weeks - Absolute:
at 3pm,on tomorrow
One-Time Reminders
Set a reminder for yourself or a teammate:
Reminders send up to 3 follow-up notifications at hourly intervals until stopped.
Recurring Reminders
Create repeating reminders:
Recurring reminders run on a cron schedule until manually stopped.
Stopping Reminders
Every reminder notification includes a Stop Reminders button in Slack. Clicking it cancels the reminder and notifies the person who created it.
Channel Auto-Onboarding
When you invite Otto to a new Slack channel:
- Otto syncs all channel members into its user database.
- An onboarding task runs automatically to learn about the channel's context (by reading recent message history).
- A project record is created so future tasks in that channel carry project-scoped context and memory.
This means Otto understands the context of each channel it participates in and can draw on that knowledge when working on tasks.
Request Verification
Otto verifies every incoming Slack request using HMAC SHA256 signature verification:
- Slack sends the request body, a timestamp, and a signature header (
X-Slack-Signature). - Otto computes its own signature using the
SLACK_SIGNING_SECRET. - The request is rejected if the signatures do not match or the timestamp is older than 5 minutes (replay attack protection).
If SLACK_SIGNING_SECRET is not configured, signature verification is skipped with a warning. This is not recommended for production.
Troubleshooting
Otto does not respond to @mentions
- Verify that
SLACK_MCP_XOXB_TOKENis set and valid. Check the health endpoint atGET /slack/health-- it reports whether the bot token is configured. - Confirm that the
app_mentionevent is subscribed under Event Subscriptions. - Make sure Otto's event request URL is reachable from Slack's servers.
Slash command returns an error
- The
/ottoslash command must point to your backend's/slack/commandendpoint. - Verify that
SLACK_SIGNING_SECRETmatches the value in your Slack app's Basic Information page. - Slack requires a response within 3 seconds. If your backend is slow to start, the command may time out.
Files are not being processed
- Ensure the
files:readscope is granted. - Check that storage quota has not been exceeded (
STORAGE_QUOTA_GBenvironment variable).
Members are not syncing
- The
users:readandusers:read.emailscopes are required for member discovery. - Run a manual sync from the Onboarding page in the web UI (Team & Behavior tab, "Sync from Slack" button).
Otto replies to its own messages
- Set
SLACK_BOT_USER_IDto the bot's Slack user ID so it can filter out its own messages.
Reminders are not firing
- The scheduler service runs as an ARQ cron job that checks for due tasks every minute. Confirm your ARQ worker is running.
- Verify that
REDIS_URLis set and Redis is reachable.