feat: openclaw-style secrets (env.vars + \) and per-task model routing
- Replace python-dotenv with config.json env.vars block + \ substitution - Add models section for per-task model routing (heartbeat, subagent, default) - Heartbeat/subagent tasks can use different models/providers than main chat - Remove python-dotenv from dependencies - Update all docs to reflect new config approach - Reorganize docs into project/ and research/ subdirectories
This commit is contained in:
365
docs/project/slack-setup.md
Normal file
365
docs/project/slack-setup.md
Normal file
@@ -0,0 +1,365 @@
|
||||
# Slack Bot Setup Guide
|
||||
|
||||
> Complete guide to creating a Slack bot and connecting it to Aetheel.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Overview](#overview)
|
||||
2. [Create a Slack App](#step-1-create-a-slack-app)
|
||||
3. [Configure Bot Permissions](#step-2-configure-bot-permissions)
|
||||
4. [Enable Socket Mode](#step-3-enable-socket-mode)
|
||||
5. [Enable Event Subscriptions](#step-4-enable-event-subscriptions)
|
||||
6. [Install the App to Your Workspace](#step-5-install-the-app-to-your-workspace)
|
||||
7. [Get Your Tokens](#step-6-get-your-tokens)
|
||||
8. [Configure Aetheel](#step-7-configure-aetheel)
|
||||
9. [Run and Test](#step-8-run-and-test)
|
||||
10. [Troubleshooting](#troubleshooting)
|
||||
11. [Architecture Reference](#architecture-reference)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Aetheel connects to Slack using **Socket Mode**, which means:
|
||||
- ✅ **No public URL needed** — works behind firewalls and NAT
|
||||
- ✅ **No webhook setup** — Slack pushes events via WebSocket
|
||||
- ✅ **Real-time** — instant message delivery
|
||||
- ✅ **Secure** — encrypted WebSocket connection
|
||||
|
||||
This is the same approach used by [OpenClaw](https://github.com/openclaw/openclaw) (see `src/slack/monitor/provider.ts`), where they use `@slack/bolt` with `socketMode: true`.
|
||||
|
||||
### What You'll Need
|
||||
|
||||
| Item | Description |
|
||||
|------|-------------|
|
||||
| **Slack Workspace** | A Slack workspace where you have admin permissions |
|
||||
| **Bot Token** | `xoxb-...` — for API calls (sending messages, reading info) |
|
||||
| **App Token** | `xapp-...` — for Socket Mode connection |
|
||||
| **Python 3.10+** | Runtime for the Aetheel service |
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create a Slack App
|
||||
|
||||
1. Go to [https://api.slack.com/apps](https://api.slack.com/apps)
|
||||
2. Click **"Create New App"**
|
||||
3. Choose **"From scratch"**
|
||||
4. Fill in:
|
||||
- **App Name:** `Aetheel` (or any name you prefer)
|
||||
- **Workspace:** Select your workspace
|
||||
5. Click **"Create App"**
|
||||
|
||||
You'll be taken to your app's **Basic Information** page.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Configure Bot Permissions
|
||||
|
||||
Navigate to **OAuth & Permissions** in the left sidebar.
|
||||
|
||||
Scroll down to **Scopes** → **Bot Token Scopes** and add the following:
|
||||
|
||||
### Required Scopes
|
||||
|
||||
| Scope | Purpose |
|
||||
|-------|---------|
|
||||
| `app_mentions:read` | Receive @mentions in channels |
|
||||
| `channels:history` | Read messages in public channels |
|
||||
| `channels:read` | View basic channel info |
|
||||
| `chat:write` | Send messages |
|
||||
| `groups:history` | Read messages in private channels |
|
||||
| `groups:read` | View private channel info |
|
||||
| `im:history` | Read direct messages |
|
||||
| `im:read` | View DM info |
|
||||
| `im:write` | Open DM conversations |
|
||||
| `mpim:history` | Read group DMs |
|
||||
| `mpim:read` | View group DM info |
|
||||
| `users:read` | Look up user info (for display names) |
|
||||
|
||||
### Optional Scopes (for future features)
|
||||
|
||||
| Scope | Purpose |
|
||||
|-------|---------|
|
||||
| `files:read` | Read files shared in messages |
|
||||
| `files:write` | Upload files |
|
||||
| `reactions:read` | Read emoji reactions |
|
||||
| `reactions:write` | Add emoji reactions |
|
||||
|
||||
> **Tip:** You can always add more scopes later, but you'll need to reinstall the app.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Enable Socket Mode
|
||||
|
||||
1. Navigate to **Socket Mode** in the left sidebar
|
||||
2. Toggle **"Enable Socket Mode"** to **ON**
|
||||
3. You'll be prompted to create an **App-Level Token**:
|
||||
- **Token Name:** `aetheel-socket` (or any name)
|
||||
- **Scopes:** Add `connections:write`
|
||||
4. Click **"Generate"**
|
||||
5. **⚠️ Copy the `xapp-...` token now!** You won't be able to see it again.
|
||||
- Save it somewhere safe — you'll need it in Step 6.
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Enable Event Subscriptions
|
||||
|
||||
1. Navigate to **Event Subscriptions** in the left sidebar
|
||||
2. Toggle **"Enable Events"** to **ON**
|
||||
3. Under **Subscribe to bot events**, add:
|
||||
|
||||
| Event | Description |
|
||||
|-------|-------------|
|
||||
| `message.channels` | Messages in public channels the bot is in |
|
||||
| `message.groups` | Messages in private channels the bot is in |
|
||||
| `message.im` | Direct messages to the bot |
|
||||
| `message.mpim` | Group DMs that include the bot |
|
||||
| `app_mention` | When someone @mentions the bot |
|
||||
|
||||
4. Click **"Save Changes"**
|
||||
|
||||
> **Note:** With Socket Mode enabled, you do NOT need a Request URL.
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Install the App to Your Workspace
|
||||
|
||||
1. Navigate to **Install App** in the left sidebar
|
||||
2. Click **"Install to Workspace"**
|
||||
3. Review the permissions and click **"Allow"**
|
||||
4. You'll see the **Bot User OAuth Token** (`xoxb-...`) — copy it!
|
||||
|
||||
> After installation, invite the bot to any channels where you want it to respond:
|
||||
> - In Slack, go to the channel
|
||||
> - Type `/invite @Aetheel` (or your bot's name)
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Get Your Tokens
|
||||
|
||||
After completing the steps above, you should have two tokens:
|
||||
|
||||
| Token | Format | Where to Find |
|
||||
|-------|--------|---------------|
|
||||
| **Bot Token** | `xoxb-1234-5678-abc...` | **OAuth & Permissions** → Bot User OAuth Token |
|
||||
| **App Token** | `xapp-1-A0123-456...` | **Basic Information** → App-Level Tokens (or from Step 3) |
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Configure Aetheel
|
||||
|
||||
### Option A: Using config.json (recommended)
|
||||
|
||||
Edit `~/.aetheel/config.json` and add your tokens to the `env.vars` block:
|
||||
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"vars": {
|
||||
"SLACK_BOT_TOKEN": "xoxb-your-actual-bot-token",
|
||||
"SLACK_APP_TOKEN": "xapp-your-actual-app-token"
|
||||
}
|
||||
},
|
||||
"slack": {
|
||||
"enabled": true,
|
||||
"bot_token": "${SLACK_BOT_TOKEN}",
|
||||
"app_token": "${SLACK_APP_TOKEN}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option B: Export environment variables
|
||||
|
||||
```bash
|
||||
export SLACK_BOT_TOKEN="xoxb-your-actual-bot-token"
|
||||
export SLACK_APP_TOKEN="xapp-your-actual-app-token"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 8: Run and Test
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Run the bot
|
||||
|
||||
```bash
|
||||
# Start with smart handler (default)
|
||||
python main.py
|
||||
|
||||
# Start in test/echo mode
|
||||
python main.py --test
|
||||
|
||||
# Start with debug logging
|
||||
python main.py --log DEBUG
|
||||
```
|
||||
|
||||
### Test sending and receiving
|
||||
|
||||
```bash
|
||||
# Run the test suite — sends test messages to a channel
|
||||
python test_slack.py --channel C0123456789
|
||||
|
||||
# Or send a DM test
|
||||
python test_slack.py --dm U0123456789
|
||||
|
||||
# Send-only (no listening)
|
||||
python test_slack.py --channel C0123456789 --send-only
|
||||
```
|
||||
|
||||
### Verify it's working
|
||||
|
||||
1. **In Slack**, go to a channel where the bot is invited
|
||||
2. Type `@Aetheel help` — you should see the help response
|
||||
3. Type `@Aetheel status` — you should see the bot's status
|
||||
4. Send a DM to the bot — it should echo back with details
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### ❌ "Slack bot token is required"
|
||||
|
||||
**Problem:** `SLACK_BOT_TOKEN` is not set or empty.
|
||||
|
||||
**Fix:**
|
||||
1. Check your `config.json` has the token in `env.vars`
|
||||
2. Make sure there are no extra spaces or quotes around the token
|
||||
3. Verify the token starts with `xoxb-`
|
||||
|
||||
### ❌ "Slack app-level token is required for Socket Mode"
|
||||
|
||||
**Problem:** `SLACK_APP_TOKEN` is not set.
|
||||
|
||||
**Fix:**
|
||||
1. Go to your Slack app → **Basic Information** → **App-Level Tokens**
|
||||
2. If no token exists, generate one with `connections:write` scope
|
||||
3. Add it to `config.json` → `env.vars`
|
||||
|
||||
### ❌ "not_authed" or "invalid_auth"
|
||||
|
||||
**Problem:** The bot token is invalid or revoked.
|
||||
|
||||
**Fix:**
|
||||
1. Go to **OAuth & Permissions** → check the Bot User OAuth Token
|
||||
2. If it says "Not installed", reinstall the app
|
||||
3. If you recently changed scopes, you need to reinstall
|
||||
|
||||
### ❌ Bot doesn't respond in channels
|
||||
|
||||
**Problem:** The bot is not invited to the channel, or you're not @mentioning it.
|
||||
|
||||
**Fix:**
|
||||
1. In the Slack channel, type `/invite @Aetheel`
|
||||
2. Make sure you @mention the bot: `@Aetheel hello`
|
||||
3. For DMs, just message the bot directly — no @mention needed
|
||||
|
||||
### ❌ "channel_not_found" when sending
|
||||
|
||||
**Problem:** Using a channel name instead of ID, or bot isn't in the channel.
|
||||
|
||||
**Fix:**
|
||||
1. Use channel **ID** not name. Find it in Slack:
|
||||
- Right-click the channel name → "View channel details"
|
||||
- The ID is at the bottom (starts with `C`)
|
||||
2. Invite the bot to the channel first
|
||||
|
||||
### ❌ Socket Mode connection drops
|
||||
|
||||
**Problem:** The WebSocket connection is unstable.
|
||||
|
||||
**Fix:**
|
||||
1. Check your internet connection
|
||||
2. The SDK automatically reconnects — this is usually transient
|
||||
3. If persistent, check Slack's [status page](https://status.slack.com/)
|
||||
|
||||
### ❌ "missing_scope"
|
||||
|
||||
**Problem:** The bot token doesn't have the required OAuth scopes.
|
||||
|
||||
**Fix:**
|
||||
1. Go to **OAuth & Permissions** → **Bot Token Scopes**
|
||||
2. Add the missing scope mentioned in the error
|
||||
3. **Reinstall the app** (scope changes require reinstallation)
|
||||
|
||||
---
|
||||
|
||||
## Architecture Reference
|
||||
|
||||
### How It Works
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ Your Slack │
|
||||
│ Workspace │
|
||||
│ │
|
||||
│ #general │
|
||||
│ #random │
|
||||
│ DMs │
|
||||
└──────┬───────────────┘
|
||||
│ WebSocket (Socket Mode)
|
||||
│
|
||||
┌──────▼───────────────┐
|
||||
│ Aetheel Slack │
|
||||
│ Adapter │
|
||||
│ │
|
||||
│ • Token resolution │
|
||||
│ • Event handling │
|
||||
│ • Thread isolation │
|
||||
│ • Message chunking │
|
||||
│ • User/channel │
|
||||
│ name resolution │
|
||||
└──────┬───────────────┘
|
||||
│ Callback
|
||||
│
|
||||
┌──────▼───────────────┐
|
||||
│ Message Handler │
|
||||
│ │
|
||||
│ • Echo (test) │
|
||||
│ • Smart (commands) │
|
||||
│ • AI (future) │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
### Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `adapters/slack_adapter.py` | Core Slack adapter (Socket Mode, send/receive) |
|
||||
| `main.py` | Entry point with echo and smart handlers |
|
||||
| `test_slack.py` | Integration test suite |
|
||||
| `~/.aetheel/config.json` | Your Slack tokens (in `env.vars` block) |
|
||||
| `requirements.txt` | Python dependencies |
|
||||
|
||||
### Comparison with OpenClaw
|
||||
|
||||
| Feature | OpenClaw (TypeScript) | Aetheel (Python) |
|
||||
|---------|----------------------|------------------|
|
||||
| **Library** | `@slack/bolt` | `slack_bolt` (official Python SDK) |
|
||||
| **Mode** | Socket Mode (`socketMode: true`) | Socket Mode (`SocketModeHandler`) |
|
||||
| **Auth** | `auth.test()` for identity | `auth_test()` for identity |
|
||||
| **Sending** | `chat.postMessage` with chunking | `chat_postMessage` with chunking |
|
||||
| **Threading** | `thread_ts` for conversation isolation | `thread_ts` for conversation isolation |
|
||||
| **DM Handling** | `conversations.open` for user DMs | `conversations_open` for user DMs |
|
||||
| **Text Limit** | 4000 chars (chunked) | 4000 chars (chunked) |
|
||||
| **Config** | JSON5 config file | `config.json` with `env.vars` + `${VAR}` |
|
||||
| **Accounts** | Multi-account support | Single account (MVP) |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
Once the Slack adapter is working, you can:
|
||||
|
||||
1. **Connect AI** — Replace the echo handler with an AI-powered handler (Claude API)
|
||||
2. **Add Memory** — Integrate the memory system for conversation context
|
||||
3. **Add Heartbeat** — Set up proactive notifications via Slack
|
||||
4. **Add Skills** — Load skills from the `.claude/skills/` directory
|
||||
|
||||
See the main [OpenClaw Analysis](../openclaw-analysis.md) for the full architecture plan.
|
||||
Reference in New Issue
Block a user