Files
Aetheel/docs/project/discord-features.md
tanmay11k 82c2640481 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
2026-02-20 23:49:05 -05:00

327 lines
8.6 KiB
Markdown

# Discord Advanced Features
All Discord features are config-driven via `~/.aetheel/config.json` under the `discord` key. No code changes needed.
---
## Default Config
```json
{
"discord": {
"enabled": false,
"listen_channels": [],
"reply_to_mode": "first",
"history_enabled": true,
"history_limit": 20,
"channel_overrides": {},
"ack_reaction": "👀",
"typing_indicator": true,
"reaction_mode": "own",
"exec_approvals": false,
"exec_approval_tools": ["Bash", "Write", "Edit"],
"slash_commands": true,
"components_enabled": true
}
}
```
---
## Reply Threading
Controls whether the bot replies to the user's message using Discord's native reply feature (the quoted message above the response).
```json
"reply_to_mode": "first"
```
| Value | Behavior |
|-------|----------|
| `"off"` | Plain messages, no reply reference |
| `"first"` | First chunk of the response replies to the user's message |
| `"all"` | Every chunk replies to the user's message |
If the original message gets deleted before the bot responds, it falls back to a plain message automatically.
---
## Channel History Context
Injects recent channel messages into the AI's system prompt so it has conversational context beyond the current message.
```json
"history_enabled": true,
"history_limit": 20
```
- `history_enabled` — global toggle, default `true`
- `history_limit` — number of recent messages to fetch, default `20`
- History is only fetched for guild channels, not DMs (DMs already have session continuity)
- Messages are formatted as `[username]: content` and injected under a "Recent Channel History" section in the system prompt
- The bot's own messages appear as `[assistant]`
### Per-Channel Overrides
You can enable, disable, or change the limit per channel:
```json
"channel_overrides": {
"1234567890": {
"history_enabled": true,
"history_limit": 50
},
"9876543210": {
"history_enabled": false
}
}
```
Keys are Discord channel IDs (strings). Any field you omit falls back to the global default.
Use cases:
- Disable history in a high-traffic channel to save context window
- Increase the limit in a project channel where long context matters
- Disable entirely for a channel where privacy is a concern
---
## Ack Reactions
Adds a reaction emoji to the user's message while the bot is processing, then removes it when the response is sent. Gives immediate visual feedback that the bot received the message.
```json
"ack_reaction": "👀"
```
- Set to any valid emoji: `"👀"`, `"⏳"`, `"🤔"`, etc.
- Set to `""` (empty string) to disable
- The reaction is removed automatically after the response is sent
- If the bot lacks Add Reactions permission in a channel, it silently skips
---
## Typing Indicator
Shows the "Aetheel is typing..." indicator in the channel while the AI processes the message.
```json
"typing_indicator": true
```
- `true` — typing indicator shown during processing (default)
- `false` — no typing indicator
The indicator stays active for the entire duration of the AI call. Combined with ack reactions, users get two layers of feedback: the reaction appears instantly, and the typing indicator persists until the response arrives.
---
## Reaction Handling
Controls whether the bot processes emoji reactions as messages to the AI.
```json
"reaction_mode": "own"
```
| Value | Behavior |
|-------|----------|
| `"off"` | Reactions are ignored entirely |
| `"own"` | Only reactions on the bot's own messages are processed |
| `"all"` | Reactions on any message in the channel are processed |
When a reaction is processed, it's sent to the AI as:
```
[Reaction: 👍 on message: <original message text>]
```
The AI can then respond contextually — for example, a 👎 on a suggestion could prompt the bot to offer alternatives.
Bot reactions and reactions from other bots are always ignored.
---
## Slash Commands
Registers native Discord slash commands that appear in the `/` menu.
```json
"slash_commands": true
```
### Available Commands
| Command | Description |
|---------|-------------|
| `/ask <message>` | Ask Aetheel a question. Shows "thinking..." while processing. |
| `/status` | Check bot status (same as typing `status` in chat) |
| `/help` | Show help (same as typing `help` in chat) |
Commands are synced with Discord on bot startup. First sync can take up to an hour to propagate globally — guild-level commands appear faster.
Set to `false` to disable slash command registration entirely.
### Bot Permissions
For slash commands to work, the bot must be invited with the `applications.commands` OAuth2 scope in addition to `bot`. If you originally invited without it, re-invite using:
OAuth2 → URL Generator → Scopes: `bot`, `applications.commands`
---
## Interactive Components
Enables the bot to send messages with buttons and select menus.
```json
"components_enabled": true
```
Components are used internally by:
- Exec approval prompts (approve/deny buttons)
- Any future interactive features
The adapter exposes `send_components_message()` for programmatic use:
```python
adapter.send_components_message(
channel_id="123456789",
text="Choose an option:",
buttons=[
{"label": "Option A", "style": "primary", "custom_id": "opt_a"},
{"label": "Option B", "style": "secondary", "custom_id": "opt_b"},
{"label": "Delete", "style": "danger", "custom_id": "delete"},
],
select_options=[
{"label": "Python", "value": "python", "description": "Snake language"},
{"label": "TypeScript", "value": "ts", "description": "JS but typed"},
],
callback=my_callback_fn,
)
```
Button styles: `primary` (blurple), `secondary` (gray), `success` (green), `danger` (red).
Set to `false` to disable — approval prompts and interactive messages fall back to plain text.
---
## Exec Approvals
Adds a human-in-the-loop confirmation step for dangerous AI tool use. When the AI tries to use a gated tool, a button prompt appears in the channel asking the user to approve or deny.
```json
"exec_approvals": false,
"exec_approval_tools": ["Bash", "Write", "Edit"]
```
- `exec_approvals` — master toggle, default `false`
- `exec_approval_tools` — list of tool names that require approval
### How It Works
1. AI decides to use a gated tool (e.g. `Bash`)
2. Bot sends an embed with approve/deny buttons:
```
⚠️ Exec Approval Required
Tool: Bash
Action: <description of what the AI wants to do>
[✅ Approve] [❌ Deny]
```
3. Only the user who sent the original message can click the buttons
4. If approved, the tool executes normally
5. If denied or timed out (2 minutes), the action is blocked
### Customizing Gated Tools
Add or remove tools from the approval list:
```json
"exec_approval_tools": ["Bash", "Write", "Edit", "WebFetch"]
```
Tools not in this list are auto-approved. Set the list to `[]` to approve everything (while keeping the feature enabled for future use).
---
## Listen Channels
Channels where the bot responds to all messages without requiring an @mention.
```json
"listen_channels": ["1234567890", "9876543210"]
```
In all other guild channels, the bot only responds when @mentioned. DMs always respond to all messages regardless of this setting.
You can also set this via environment variable:
```bash
DISCORD_LISTEN_CHANNELS=1234567890,9876543210
```
---
## Required Bot Permissions
For all features to work, invite the bot with these permissions:
| Permission | Required For |
|------------|-------------|
| Send Messages | Responding to users |
| Read Message History | History context injection |
| View Channels | Seeing channels |
| Add Reactions | Ack reactions |
| Use External Emojis | Custom ack reaction emojis |
| Embed Links | Exec approval prompts |
OAuth2 scopes: `bot`, `applications.commands`
Privileged intents (in Developer Portal → Bot):
- Message Content Intent (required)
- Server Members Intent (recommended)
---
## Example Configs
### Minimal (just the basics)
```json
{
"discord": {
"enabled": true
}
}
```
Uses all defaults: reply threading on first message, history on, ack 👀, typing on, reactions on own messages, slash commands on.
### Privacy-focused
```json
{
"discord": {
"enabled": true,
"history_enabled": false,
"ack_reaction": "",
"reaction_mode": "off",
"slash_commands": false
}
}
```
### Full control with approvals
```json
{
"discord": {
"enabled": true,
"reply_to_mode": "all",
"history_limit": 50,
"ack_reaction": "⏳",
"exec_approvals": true,
"exec_approval_tools": ["Bash", "Write", "Edit", "WebFetch"],
"channel_overrides": {
"123456789": { "history_limit": 100 },
"987654321": { "history_enabled": false }
}
}
}
```