- scripts/learner-*.sh → scripts/dev-*.sh - docs/learner-*.md → docs/dev-*.md - tests/test-learner-env.sh → tests/test-dev-env.sh - Update all internal references 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.6 KiB
5.6 KiB
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, mode640 - Dev users added to
devsgroup on creation .bashrcsources the env file on login
Scripts
/usr/local/bin/dev-add.sh <username> '<ssh-pubkey>'
/usr/local/bin/dev-remove.sh <username> [--archive]
Dev Workflow
1. Get Access
Send SSH pubkey to admin. Admin runs:
ssh root@ops-jrz1 'dev-add.sh alice "ssh-ed25519 AAAA..."'
2. Connect
ssh alice@<server-ip>
Tokens are available immediately:
echo $SLACK_BOT_TOKEN # xoxb-...
echo $SLACK_APP_TOKEN # xapp-...
3. Write a Bot
# ~/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
pip install slack-bolt
python bot.py
Bot responds to "hello" and "dice" in Slack.
slack-bolt Basics
Event Handlers
# 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):
@app.command("/mycommand")
def handle_command(ack, respond, command):
ack() # Must acknowledge within 3 seconds
respond(f"You said: {command['text']}")
Sending Messages
# 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
- Shared tokens - All devs use same bot identity
- Token exposure - If leaked, affects everyone
- Rate limits - Shared across all bots
- Process sprawl - N devs = N processes to manage
- 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:
- systemd user services - Each dev manages their own
- supervisor - Central process manager
- tmux/screen - Manual but simple
- Container per dev - Isolation but complex
Starter Template
Create ~/slack-bot-template/ with:
bot.py- Hello worldrequirements.txt- slack-bolt pinnedMakefile- run, install targetsREADME.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