- 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
9.0 KiB
Discord Bot Setup Guide
Complete guide to creating a Discord bot and connecting it to Aetheel.
Table of Contents
- Overview
- Create a Discord Application
- Create the Bot
- Enable Privileged Intents
- Invite the Bot to Your Server
- Configure Aetheel
- Run and Test
- Troubleshooting
- 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
- Go to https://discord.com/developers/applications
- Click "New Application"
- Enter a name:
Aetheel(or any name you prefer) - Accept the Terms of Service
- Click "Create"
You'll be taken to your application's General Information page.
Step 2: Create the Bot
- Navigate to Bot in the left sidebar
- The bot user is created automatically with your application
- Click "Reset Token" to generate a new bot token
- ⚠️ Copy the token now! You won't be able to see it again.
- Save it somewhere safe — this is your
DISCORD_BOT_TOKEN
- Save it somewhere safe — this is your
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
- Navigate to OAuth2 → URL Generator in the left sidebar
- Under Scopes, check:
bot - 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 |
- Copy the Generated URL at the bottom
- Open the URL in your browser
- Select the server you want to add the bot to
- 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:
{
"env": {
"vars": {
"DISCORD_BOT_TOKEN": "your-discord-bot-token-here"
}
},
"discord": {
"enabled": true,
"bot_token": "${DISCORD_BOT_TOKEN}"
}
}
Option B: Export environment variable
export DISCORD_BOT_TOKEN="your-discord-bot-token-here"
Step 6: Run and Test
Install dependencies
uv sync
# or: pip install -r requirements.txt
This will install discord.py along with the other dependencies.
Run the bot
# 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
- Check the console — you should see:
Aetheel Discord Adapter Bot: @Aetheel (123456789) Guilds: My Server - In Discord, go to a channel where the bot is present
- Type
@Aetheel help— you should see the help response - Type
@Aetheel status— you should see the bot's status - 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:
- Check your
config.jsonhas the token inenv.vars - Make sure there are no extra spaces or quotes
- 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:
- Go to Developer Portal → your app → Bot
- Scroll to Privileged Gateway Intents
- Enable Message Content Intent
- 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:
- Go to Bot page in the Developer Portal
- Click "Reset Token" to generate a fresh one
- Copy the full token (it's a long string)
- 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:
- Go to Bot → Privileged Gateway Intents
- Enable Message Content Intent
- Save changes and restart
❌ Bot is offline in the member list
Problem: Aetheel isn't running, or the token is wrong.
Fix:
- Start Aetheel with
--discordflag - Check the console for connection errors
- Verify the token in
config.jsonmatches the one in the Developer Portal
❌ "Missing Permissions" when sending messages
Problem: The bot doesn't have Send Messages permission in that channel.
Fix:
- Check the channel's permission overrides for the bot role
- Re-invite the bot with the correct permissions (see Step 4)
- 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 |