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:
317
docs/project/discord-setup.md
Normal file
317
docs/project/discord-setup.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# Discord Bot Setup Guide
|
||||
|
||||
> Complete guide to creating a Discord bot and connecting it to Aetheel.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Overview](#overview)
|
||||
2. [Create a Discord Application](#step-1-create-a-discord-application)
|
||||
3. [Create the Bot](#step-2-create-the-bot)
|
||||
4. [Enable Privileged Intents](#step-3-enable-privileged-intents)
|
||||
5. [Invite the Bot to Your Server](#step-4-invite-the-bot-to-your-server)
|
||||
6. [Configure Aetheel](#step-5-configure-aetheel)
|
||||
7. [Run and Test](#step-6-run-and-test)
|
||||
8. [Troubleshooting](#troubleshooting)
|
||||
9. [Architecture Reference](#architecture-reference)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Aetheel connects to Discord using the **Gateway API** via `discord.py`, which means:
|
||||
- ✅ **No public URL needed** — works behind firewalls and NAT
|
||||
- ✅ **No webhook setup** — Discord pushes events via WebSocket
|
||||
- ✅ **Real-time** — instant message delivery
|
||||
- ✅ **DMs + @mentions** — responds in both
|
||||
|
||||
### What You'll Need
|
||||
|
||||
| Item | Description |
|
||||
|------|-------------|
|
||||
| **Discord Account** | With access to a server where you have Manage Server permissions |
|
||||
| **Bot Token** | From the Discord Developer Portal |
|
||||
| **Python 3.14+** | Runtime for the Aetheel service |
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create a Discord Application
|
||||
|
||||
1. Go to [https://discord.com/developers/applications](https://discord.com/developers/applications)
|
||||
2. Click **"New Application"**
|
||||
3. Enter a name: `Aetheel` (or any name you prefer)
|
||||
4. Accept the Terms of Service
|
||||
5. Click **"Create"**
|
||||
|
||||
You'll be taken to your application's **General Information** page.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Create the Bot
|
||||
|
||||
1. Navigate to **Bot** in the left sidebar
|
||||
2. The bot user is created automatically with your application
|
||||
3. Click **"Reset Token"** to generate a new bot token
|
||||
4. **⚠️ Copy the token now!** You won't be able to see it again.
|
||||
- Save it somewhere safe — this is your `DISCORD_BOT_TOKEN`
|
||||
|
||||
### Optional: Bot Settings
|
||||
|
||||
On the same Bot page, you can configure:
|
||||
|
||||
| Setting | Recommended | Why |
|
||||
|---------|-------------|-----|
|
||||
| **Public Bot** | OFF | Only you can invite it to servers |
|
||||
| **Requires OAuth2 Code Grant** | OFF | Simpler invite flow |
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Enable Privileged Intents
|
||||
|
||||
Still on the **Bot** page, scroll down to **Privileged Gateway Intents**.
|
||||
|
||||
Enable the following:
|
||||
|
||||
| Intent | Required | Purpose |
|
||||
|--------|----------|---------|
|
||||
| **Message Content Intent** | ✅ Yes | Read the text content of messages |
|
||||
| **Server Members Intent** | Optional | Resolve member display names |
|
||||
| **Presence Intent** | No | Not needed |
|
||||
|
||||
> **Important:** The Message Content Intent is required. Without it, the bot will receive empty message content for guild messages.
|
||||
|
||||
Click **"Save Changes"**.
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Invite the Bot to Your Server
|
||||
|
||||
1. Navigate to **OAuth2** → **URL Generator** in the left sidebar
|
||||
2. Under **Scopes**, check: `bot`
|
||||
3. Under **Bot Permissions**, check:
|
||||
|
||||
| Permission | Purpose |
|
||||
|------------|---------|
|
||||
| **Send Messages** | Reply to users |
|
||||
| **Read Message History** | Context for conversations |
|
||||
| **View Channels** | See channels the bot is in |
|
||||
|
||||
4. Copy the **Generated URL** at the bottom
|
||||
5. Open the URL in your browser
|
||||
6. Select the server you want to add the bot to
|
||||
7. Click **"Authorize"**
|
||||
|
||||
The bot should now appear in your server's member list (offline until you start Aetheel).
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Configure Aetheel
|
||||
|
||||
### Option A: Using config.json (recommended)
|
||||
|
||||
Edit `~/.aetheel/config.json` and add your token to the `env.vars` block:
|
||||
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"vars": {
|
||||
"DISCORD_BOT_TOKEN": "your-discord-bot-token-here"
|
||||
}
|
||||
},
|
||||
"discord": {
|
||||
"enabled": true,
|
||||
"bot_token": "${DISCORD_BOT_TOKEN}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option B: Export environment variable
|
||||
|
||||
```bash
|
||||
export DISCORD_BOT_TOKEN="your-discord-bot-token-here"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Run and Test
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
# or: pip install -r requirements.txt
|
||||
```
|
||||
|
||||
This will install `discord.py` along with the other dependencies.
|
||||
|
||||
### Run the bot
|
||||
|
||||
```bash
|
||||
# Discord only
|
||||
uv run python main.py --discord
|
||||
|
||||
# Discord + Slack together
|
||||
uv run python main.py --discord
|
||||
|
||||
# Discord with Claude Code runtime
|
||||
uv run python main.py --discord --claude
|
||||
|
||||
# Test mode (echo handler, no AI)
|
||||
uv run python main.py --discord --test
|
||||
|
||||
# Debug logging
|
||||
uv run python main.py --discord --log DEBUG
|
||||
```
|
||||
|
||||
### Verify it's working
|
||||
|
||||
1. Check the console — you should see:
|
||||
```
|
||||
Aetheel Discord Adapter
|
||||
Bot: @Aetheel (123456789)
|
||||
Guilds: My Server
|
||||
```
|
||||
2. In Discord, go to a channel where the bot is present
|
||||
3. Type `@Aetheel help` — you should see the help response
|
||||
4. Type `@Aetheel status` — you should see the bot's status
|
||||
5. Send a DM to the bot — it should respond directly
|
||||
|
||||
### How the bot responds
|
||||
|
||||
| Context | Trigger | Session Isolation |
|
||||
|---------|---------|-------------------|
|
||||
| **Guild channel** | @mention only | Per-channel |
|
||||
| **DM** | Any message | Per-DM channel |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### ❌ "Discord bot token is required"
|
||||
|
||||
**Problem:** `DISCORD_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
|
||||
3. Verify the token is from the Bot page, not the application client secret
|
||||
|
||||
### ❌ Bot comes online but doesn't respond to messages
|
||||
|
||||
**Problem:** Message Content Intent is not enabled.
|
||||
|
||||
**Fix:**
|
||||
1. Go to [Developer Portal](https://discord.com/developers/applications) → your app → **Bot**
|
||||
2. Scroll to **Privileged Gateway Intents**
|
||||
3. Enable **Message Content Intent**
|
||||
4. Save and restart Aetheel
|
||||
|
||||
### ❌ Bot doesn't respond in guild channels
|
||||
|
||||
**Problem:** You're not @mentioning the bot.
|
||||
|
||||
**Fix:**
|
||||
- In guild channels, the bot only responds to @mentions: `@Aetheel hello`
|
||||
- In DMs, the bot responds to any message — no @mention needed
|
||||
|
||||
### ❌ "Improper token has been passed"
|
||||
|
||||
**Problem:** The token is malformed or from the wrong place.
|
||||
|
||||
**Fix:**
|
||||
1. Go to **Bot** page in the Developer Portal
|
||||
2. Click **"Reset Token"** to generate a fresh one
|
||||
3. Copy the full token (it's a long string)
|
||||
4. Make sure you're using the Bot token, not the Client ID or Client Secret
|
||||
|
||||
### ❌ "discord.errors.PrivilegedIntentsRequired"
|
||||
|
||||
**Problem:** You're requesting intents that aren't enabled in the portal.
|
||||
|
||||
**Fix:**
|
||||
1. Go to **Bot** → **Privileged Gateway Intents**
|
||||
2. Enable **Message Content Intent**
|
||||
3. Save changes and restart
|
||||
|
||||
### ❌ Bot is offline in the member list
|
||||
|
||||
**Problem:** Aetheel isn't running, or the token is wrong.
|
||||
|
||||
**Fix:**
|
||||
1. Start Aetheel with `--discord` flag
|
||||
2. Check the console for connection errors
|
||||
3. Verify the token in `config.json` matches the one in the Developer Portal
|
||||
|
||||
### ❌ "Missing Permissions" when sending messages
|
||||
|
||||
**Problem:** The bot doesn't have Send Messages permission in that channel.
|
||||
|
||||
**Fix:**
|
||||
1. Check the channel's permission overrides for the bot role
|
||||
2. Re-invite the bot with the correct permissions (see Step 4)
|
||||
3. Or manually grant the bot's role Send Messages in Server Settings → Roles
|
||||
|
||||
---
|
||||
|
||||
## Architecture Reference
|
||||
|
||||
### How It Works
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ Your Discord │
|
||||
│ Server │
|
||||
│ │
|
||||
│ #general │
|
||||
│ #random │
|
||||
│ DMs │
|
||||
└──────┬───────────────┘
|
||||
│ WebSocket (Gateway API)
|
||||
│
|
||||
┌──────▼───────────────┐
|
||||
│ Aetheel Discord │
|
||||
│ Adapter │
|
||||
│ │
|
||||
│ • Token resolution │
|
||||
│ • @mention filter │
|
||||
│ • DM handling │
|
||||
│ • Message chunking │
|
||||
│ (2000 char limit) │
|
||||
│ • Async dispatch │
|
||||
│ via to_thread() │
|
||||
└──────┬───────────────┘
|
||||
│ Callback
|
||||
│
|
||||
┌──────▼───────────────┐
|
||||
│ Message Handler │
|
||||
│ │
|
||||
│ • Echo (test) │
|
||||
│ • AI (OpenCode / │
|
||||
│ Claude Code) │
|
||||
│ • Memory + Skills │
|
||||
│ • Action tags │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
### Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `adapters/discord_adapter.py` | Core Discord adapter (Gateway, send/receive) |
|
||||
| `adapters/base.py` | Abstract base class all adapters implement |
|
||||
| `main.py` | Entry point — `--discord` flag enables this adapter |
|
||||
| `~/.aetheel/config.json` | Your Discord token (in `env.vars` block) |
|
||||
|
||||
### Comparison with Other Adapters
|
||||
|
||||
| Feature | Slack | Telegram | Discord |
|
||||
|---------|-------|----------|---------|
|
||||
| **Library** | `slack_bolt` | `python-telegram-bot` | `discord.py` |
|
||||
| **Connection** | Socket Mode (WebSocket) | Long polling | Gateway (WebSocket) |
|
||||
| **Auth** | Bot Token + App Token | Single Bot Token | Single Bot Token |
|
||||
| **Trigger (channels)** | @mention | @mention | @mention |
|
||||
| **Trigger (DMs)** | Any message | Any message | Any message |
|
||||
| **Text Limit** | 4000 chars | 4096 chars | 2000 chars |
|
||||
| **Threading** | Native threads | Reply-to-message | N/A (per-channel) |
|
||||
| **Session Isolation** | Per-thread | Per-chat | Per-channel |
|
||||
Reference in New Issue
Block a user