Slack Bot Setup
Set up a Slack bot like @Optimus using the Neumar desktop app. Install the app on macOS, configure tokens in the Slack App dashboard, customize skills and capabilities, and apply security best practices.
This guide walks through setting up a real-time Slack bot — the same pattern used to run @Optimus — with the Neumar desktop app. Total setup time is around ten minutes once you have admin access to a Slack workspace. The flow is identical for any other agentic AI desktop app that supports Slack Socket Mode.
What You Will Build
A bot that:
- Replies in channels when @-mentioned, and in direct messages
- Has access to your configured MCP tools (Linear, GitHub, Notion, etc.)
- Runs from your Mac with no public HTTP endpoint required
- Stores tokens encrypted at rest on-device
Prerequisites
- macOS 12 or later
- Admin permission on the Slack workspace where the bot will live
- The Neumar desktop app installed from neumar.app/download
1. Install the Desktop App on macOS
Download the .dmg from neumar.app/download and drag the app into /Applications. On first launch macOS may prompt you to confirm an unsigned binary if you are using a development build — release builds are notarized and do not show the warning.
The app starts an embedded API sidecar bound to 127.0.0.1:2620. Nothing is exposed beyond the loopback interface. The first time you open the app you will be asked to choose a workspace directory (default ~/Documents/Neumar) — every file the bot reads or writes from disk is sandboxed inside that directory.
2. Create the Slack App and Configure Tokens
2.1 Create the App
Open api.slack.com/apps and click Create New App → From scratch. Give it a display name (Optimus, or whatever the bot should be called in Slack) and pick the target workspace.
2.2 Add Bot Token Scopes
In the app's left nav, open OAuth & Permissions and add Bot Token Scopes. The principle here is least privilege — only add what the bot will actually use. Common minimum set:
| Scope | Purpose |
|---|---|
app_mentions:read | Receive @bot mentions |
chat:write | Send messages |
chat:write.public | Post in channels the bot is not a member of (optional) |
channels:history, groups:history | Read messages in channels/private channels the bot is in |
im:read, im:write, im:history | Direct messages |
mpim:history | Group DMs |
users:read | Resolve user IDs to display names |
files:read, files:write | Receive and send attachments |
reactions:write | Acknowledge messages with emoji reactions |
assistant:write | Use the Slack AI Assistant pane |
If you plan to use the Slack MCP server preset for cross-workspace search and canvases, also add a User Token with search:read, users:read.email, canvases:read, and canvases:write. The user token acts as you, so be conservative about who has access to the desktop app afterward.
2.3 Enable Socket Mode
Open Socket Mode in the left nav and toggle it on. Socket Mode opens an outbound WebSocket from your machine to Slack — there is no public URL to expose, and no request signing to manage.
When prompted, create an App-Level Token with the connections:write scope. Copy the xapp-… value somewhere safe.
2.4 Subscribe to Events
Open Event Subscriptions, toggle Enable Events on. Because Socket Mode is on, no Request URL is needed.
Under Subscribe to bot events, add at least:
app_mention— bot reacts to@mentionsmessage.channels,message.groups,message.im,message.mpim— bot can see messages in channels and DMs it has been added to
If the bot should only respond when explicitly mentioned, drop the message.* events and rely on app_mention alone. This is a meaningful security hardening: the bot literally cannot read messages that do not tag it.
2.5 Install and Capture Tokens
Back on OAuth & Permissions, click Install to Workspace and approve the consent screen. After install you will see:
- Bot User OAuth Token — starts with
xoxb- - User OAuth Token — starts with
xoxp-(only if user scopes were added)
Copy both. You should now have three tokens: xapp- (app-level for Socket Mode), xoxb- (bot), and optionally xoxp- (user).
3. Connect Neumar to Slack
In the desktop app, open Settings → Connectors and expand the Slack card. Two connection paths are available:
- OAuth — easier for end users, but requires you to first paste the Slack App's Client ID and Client Secret and to register
http://127.0.0.1:5189/callbackas a redirect URL in your Slack App. - Manual token entry — paste the tokens you already have. Recommended for developer setups.
Manual Connect
- Paste the
xoxb-…value into Bot Token - Optionally paste
xoxp-…into User Token - Click Connect
Neumar calls Slack's auth.test to verify the token, then captures the team ID, bot user ID, and authed user. Tokens are encrypted at rest with AES-256-GCM in ~/.neumar/slack-config.enc.json.
Start the Gateway
Once connected, a Socket Mode subsection appears. Paste the xapp-… app-level token, click Save, then click Start on the gateway controls. The status pill turns green when the WebSocket is live. Click Test to round-trip a check.
Verify in Slack: invite the bot to a channel, mention it (@Optimus hello), and confirm a reply within a couple of seconds.
4. Customize Skills and Capabilities
Three layers control what the bot can do.
4.1 MCP Servers
Neumar discovers MCP servers from ~/.claude/settings.json (if you use Claude Code) and ~/.neumar/mcp.json. Open Settings → MCP to browse the one-click preset gallery:
| Preset | What It Adds |
|---|---|
| Linear | Issue management, ticket-to-PR pipeline |
| GitHub | PR creation, branch and review workflows |
| Slack (cross-workspace) | Search, history, canvases |
| Notion | Page and database access |
| Figma | Design context |
| Playwright | Browser automation |
Each preset is sandboxed: stdio servers run as child processes, OAuth servers (Notion, Figma) open a browser flow scoped to your account. Adding a server immediately expands the bot's toolset — no restart required.
4.2 Skills
Skills are declarative recipes — markdown files that the agent loads on demand based on a trigger description. Drop a .md file into your skills directory and the bot can invoke it whenever the user's intent matches.
Useful skills for an Optimus-style bot:
/standup— summarize your recent Slack activity for daily standups/triage— classify incoming bug reports into severity buckets/digest— end-of-day summary of activity in a channel/jira-link— auto-link Jira tickets mentioned in messages
4.3 System Prompt
Open Settings → Agent → System Prompt to define personality, tone, and — most importantly — guardrails. Three things every bot system prompt should include:
- Identity scope — "You are Optimus, an assistant for the Engineering team in workspace X. Refuse questions outside that scope."
- Action confirmation — "Before any destructive action (deleting issues, posting to broadcast channels, sending DMs to people you haven't talked to before), ask the user to confirm in-thread."
- Data exfiltration ban — "Do not include credentials, tokens, or content from private channels in any reply that may be cross-posted, and never render image URLs from untrusted sources."
5. Security Practices
A Slack bot with chat:write and channels:history is a capable read/write account inside your workspace. Treat it like a service account.
5.1 Token Hygiene
- Never commit tokens. Slack and GitGuardian both auto-revoke leaked
xoxb-tokens, but you will lose service while you re-issue. - Rotate periodically. Slack supports token rotation — set a 90-day reminder, or use
auth.revokeand reinstall when an employee leaves. - Store encrypted. Neumar uses AES-256-GCM at rest. If you roll your own, prefer macOS Keychain, 1Password CLI, or a managed secret store over plaintext
.envfiles.
5.2 Least Privilege on Scopes
Audit your Slack App's OAuth page periodically and drop scopes you do not actively use. Common over-grants: users:read.email on a bot that never reads emails, chat:write.public on a bot that only posts in invited channels, files:read on a bot that does not process attachments. Slack's optional scopes feature (March 2026) lets you mark capabilities as opt-in so the install consent screen reflects what is actually required.
5.3 Prefer Socket Mode Over Webhooks
Socket Mode has no public endpoint to attack — Slack initiates the WebSocket from their side and you authenticate with the xapp- token. With webhooks you must expose a URL, verify the x-slack-signature header on every request, defend against replay attacks, and worry about request smuggling. For local development and small deployments, Socket Mode is strictly safer.
5.4 Defending Against Prompt Injection
Slack AI itself was found vulnerable to indirect prompt injection in August 2024 — a poisoned message in a public channel tricked the AI into leaking content from private channels via a crafted link. Your bot is exposed to the same class of attack.
The pattern to watch for is the lethal trifecta: access to private data + exposure to untrusted input + ability to make external requests. If the bot has all three, an attacker can plant instructions in a public message and exfiltrate data through a clickable link or an image URL Slack auto-renders.
Concrete mitigations:
- URL allowlist for outbound rendering. When the agent generates a markdown image like
, refuse to send it unless the host is on an allowlist (*.slack.com,*.slack-edge.com, your CDN). Apply the same allowlist to inbound file downloads. - Split read and write contexts. Where possible, run two agent contexts — an untrusted reader that ingests Slack history and produces structured summaries, and a trusted actor that calls high-impact tools. They never share a context window.
- Approval for destructive actions. Posting to broadcast channels, sending DMs to new contacts, deleting messages, modifying canvases — all should require an in-thread confirmation before the bot proceeds.
5.5 Audit and Monitor
Log every message the bot reads, every tool it calls, and every message it sends, with the user ID and channel ID attached. Neumar writes this trail through its built-in audit log. If something goes wrong, the trail is what tells you which incoming message caused which outgoing action.
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
Gateway state stuck on starting | Wrong xapp- token, or connections:write scope missing | Re-issue the app-level token with connections:write |
| Bot does not reply to mentions | app_mention not subscribed, or bot not in channel | Re-check Event Subscriptions and /invite @bot in the channel |
auth.test fails on Connect | Token revoked, or pasted with whitespace | Re-install the app, copy the token cleanly |
| Bot replies but cannot read history | Missing channels:history / groups:history scope | Add the scope, re-install the app |
| Files do not upload | Missing files:write scope | Add the scope, re-install the app |
Next Steps
- Wire in MCP servers for richer toolsets
- Connect Linear to enable the autonomous ticket-to-PR pipeline
- Read the security best-practice base in Slack's docs before going to production