# Direct Slack Bot Development for Devs Design doc for the "direct to Slack" dev path, bypassing Matrix/maubot. ## Overview Devs write Python bots using `slack-bolt` that connect directly to Slack via Socket Mode. No Matrix, no bridge, no maubot. ``` ┌─────────────────────────────────────────┐ │ VPS (ops-jrz1) │ │ │ │ alice's bot.py ──┐ │ │ bob's bot.py ────┼── Socket Mode ─────────► Slack API │ carol's bot.py ──┘ (WebSocket) │ │ │ └─────────────────────────────────────────┘ ``` ## Current Setup ### Credentials Shared Slack App tokens stored in `/etc/slack-dev.env`: | Variable | Purpose | |----------|---------| | `SLACK_BOT_TOKEN` | Bot identity (xoxb-...) | | `SLACK_APP_TOKEN` | Socket Mode connection (xapp-...) | These come from the existing mautrix-slack bridge login (Chochacho workspace, vlad's account). ### Access Control - File owned by `root:devs`, mode `640` - Dev users added to `devs` group on creation - `.bashrc` sources the env file on login ### Scripts ``` /usr/local/bin/dev-add.sh '' /usr/local/bin/dev-remove.sh [--archive] ``` ## Dev Workflow ### 1. Get Access Send SSH pubkey to admin. Admin runs: ```bash ssh root@ops-jrz1 'dev-add.sh alice "ssh-ed25519 AAAA..."' ``` ### 2. Connect ```bash ssh alice@ ``` Tokens are available immediately: ```bash echo $SLACK_BOT_TOKEN # xoxb-... echo $SLACK_APP_TOKEN # xapp-... ``` ### 3. Write a Bot ```python # ~/bot.py from slack_bolt import App from slack_bolt.adapter.socket_mode import SocketModeHandler import os app = App(token=os.environ["SLACK_BOT_TOKEN"]) @app.message("hello") def hello(message, say): say(f"Hey <@{message['user']}>!") @app.message("dice") def dice(message, say): import random say(f"🎲 You rolled a {random.randint(1, 6)}!") if __name__ == "__main__": print("Bot starting...") SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start() ``` ### 4. Run It ```bash pip install slack-bolt python bot.py ``` Bot responds to "hello" and "dice" in Slack. ## slack-bolt Basics ### Event Handlers ```python # Match exact text @app.message("hello") def handle_hello(message, say): say("Hello!") # Match regex @app.message(re.compile(r"^roll (\d+)d(\d+)")) def handle_roll(message, say, context): # context["matches"] contains regex groups pass # Match any message @app.event("message") def handle_all(event, say): pass # React to app mentions (@bot) @app.event("app_mention") def handle_mention(event, say): say("You mentioned me!") ``` ### Slash Commands Requires additional Slack App config (not set up yet): ```python @app.command("/mycommand") def handle_command(ack, respond, command): ack() # Must acknowledge within 3 seconds respond(f"You said: {command['text']}") ``` ### Sending Messages ```python # Reply in thread say("Reply!", thread_ts=message["ts"]) # Send to specific channel app.client.chat_postMessage(channel="C1234567", text="Hello") # Rich formatting (blocks) say(blocks=[ {"type": "section", "text": {"type": "mrkdwn", "text": "*Bold* and _italic_"}} ]) ``` ## Tradeoffs ### vs Maubot/Matrix Path | Aspect | Direct Slack | Maubot/Matrix | |--------|--------------|---------------| | **Setup complexity** | Lower - just Python | Higher - Matrix + bridge + maubot | | **Feedback loop** | Fast - direct to Slack | Slower - goes through bridge | | **Mental model** | Simple - just Slack | Complex - Matrix concepts | | **Documentation** | Excellent (Bolt is popular) | Sparse (maubot is niche) | | **Process management** | Manual (you run it) | Managed (maubot lifecycle) | | **Bot identity** | Shared (all bots = same user) | Per-instance configurable | | **Crash recovery** | Manual restart | Auto-managed | | **Production path** | Direct - same code works | Need to rewrite for Slack-only | ### Risks 1. **Shared tokens** - All devs use same bot identity 2. **Token exposure** - If leaked, affects everyone 3. **Rate limits** - Shared across all bots 4. **Process sprawl** - N devs = N processes to manage 5. **No guardrails** - Bad code can spam/crash easily ### Mitigations - Dedicated test channel in Slack - Supervisor/systemd for process management (not yet set up) - Tokens in env vars, not code - Can rotate tokens if leaked (re-login bridge) ## Future Improvements ### Process Management Options: 1. **systemd user services** - Each dev manages their own 2. **supervisor** - Central process manager 3. **tmux/screen** - Manual but simple 4. **Container per dev** - Isolation but complex ### Starter Template Create `~/slack-bot-template/` with: - `bot.py` - Hello world - `requirements.txt` - slack-bolt pinned - `Makefile` - run, install targets - `README.md` - Quick start ### Per-Dev Bot Identity Create separate Slack App per dev: - More setup friction - Full isolation - Each bot has own name/avatar ### Test Channel Create `#dev-sandbox` in Slack: - All dev bots invited - Safe place to spam - Doesn't pollute real channels ## References - [Bolt for Python - Getting Started](https://slack.dev/bolt-python/tutorial/getting-started) - [Slack API - Socket Mode](https://api.slack.com/apis/connections/socket) - [Slack API - Events](https://api.slack.com/events) - [slack-bolt GitHub](https://github.com/slackapi/bolt-python)