docs(discord): troubleshoot silent fail-closed denials

Docs portion of PR #57067: 'bot connects but never replies' section
pointing at the gateway.log warning and the allowlist/policy knobs.

Co-authored-by: ooovenenoso <120500656+ooovenenoso@users.noreply.github.com>
This commit is contained in:
teknium1 2026-07-07 16:42:47 -07:00 committed by Teknium
parent 3e7ade418d
commit db9e3e4ef9

View file

@ -114,7 +114,7 @@ This is the most critical step in the entire setup. Without the correct intents
On the **Bot** page, scroll down to **Privileged Gateway Intents**. You'll see three toggles:
| Intent | Purpose | Required? |
|--------|---------|-----------|
|--------|---------|-----------|
| **Presence Intent** | See user online/offline status | Optional |
| **Server Members Intent** | Access the member list, resolve usernames | **Required** |
| **Message Content Intent** | Read the text content of messages | **Required** |
@ -170,7 +170,7 @@ This method requires **Public Bot** to be set to **ON** in Step 2. If you set Pu
You can construct the invite URL directly using this format:
```
https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot+applications.commands&permissions=309237763136
https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot+applications.commands&permissions=274878286912
```
Replace `YOUR_APP_ID` with the Application ID from Step 1.
@ -187,7 +187,6 @@ These are the minimum permissions your bot needs:
### Recommended Additional Permissions
- **Create Public Threads** - create threads
- **Send Messages in Threads** — respond in thread conversations
- **Add Reactions** — react to messages for acknowledgment
@ -196,7 +195,7 @@ These are the minimum permissions your bot needs:
| Level | Permissions Integer | What's Included |
|-------|-------------------|-----------------|
| Minimal | `117760` | View Channels, Send Messages, Read Message History, Attach Files |
| Recommended | `309237763136` | All of the above plus Embed Links, Send Messages in Threads, Add Reactions, Create Public Threads |
| Recommended | `274878286912` | All of the above plus Embed Links, Send Messages in Threads, Add Reactions |
## Step 6: Invite to Your Server
@ -272,8 +271,10 @@ Discord behavior is controlled through two files: **`~/.hermes/.env`** for crede
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `DISCORD_BOT_TOKEN` | **Yes** | — | Bot token from the [Discord Developer Portal](https://discord.com/developers/applications). |
| `DISCORD_ALLOWED_USERS` | **Yes** | — | Comma-separated Discord user IDs allowed to interact with the bot. Without this **or** `DISCORD_ALLOWED_ROLES`, the gateway denies all users. |
| `DISCORD_ALLOWED_USERS` | Conditional | — | Comma-separated Discord user IDs allowed to interact with the bot. Without this **or** `DISCORD_ALLOWED_ROLES`, the gateway denies all users unless `DISCORD_ALLOW_ALL_USERS=true`, `GATEWAY_ALLOW_ALL_USERS=true`, or `DISCORD_ALLOWED_CHANNELS` explicitly scopes guild access. |
| `DISCORD_ALLOWED_ROLES` | No | — | Comma-separated Discord role IDs. Any member with one of these roles is authorized — OR semantics with `DISCORD_ALLOWED_USERS`. Auto-enables the **Server Members Intent** on connect. Useful when moderation teams churn: new mods get access as soon as the role is granted, no config push needed. |
| `DISCORD_ALLOW_ALL_USERS` | No | `false` | Explicit opt-in to allow every Discord user who can reach the bot. This restores the pre-0.18 open behavior for Discord only; use only for trusted/private guilds or development. |
| `GATEWAY_ALLOW_ALL_USERS` | No | `false` | Global allow-all opt-in for every gateway platform. Prefer the platform-specific `DISCORD_ALLOW_ALL_USERS` unless you intentionally want all connected platforms open. |
| `DISCORD_HOME_CHANNEL` | No | — | Channel ID where the bot sends proactive messages (cron output, reminders, notifications). |
| `DISCORD_HOME_CHANNEL_NAME` | No | `"Home"` | Display name for the home channel in logs and status output. |
| `DISCORD_COMMAND_SYNC_POLICY` | No | `"safe"` | Controls native slash-command startup sync. `"safe"` diffs existing global commands and only updates what changed, recreating commands when Discord metadata changes cannot be applied via patch. `"bulk"` preserves the old `tree.sync()` behavior. `"off"` skips startup sync entirely. |
@ -574,26 +575,6 @@ gateway:
Use `/whoami` to see the active scope, your tier (admin / user / unrestricted), and which slash commands you can run.
### Restricting exec-approval buttons to admins
By default, any user allowed to talk to the bot — including users paired via `hermes pairing approve` — can click the **Approve / Deny** buttons on a dangerous-command prompt. This mirrors plain-chat admission and is the historical behavior. To restrict *approving dangerous commands* to admins only, set `require_admin_for_exec_approval` in the Discord platform's `extra` block:
```yaml
gateway:
platforms:
discord:
extra:
require_admin_for_exec_approval: true # default: false
allow_admin_from:
- "123456789012345678" # only these users may click Approve/Deny
```
**Behavior:**
- **Default off** — exec-approval buttons stay user-scope; any admitted user can approve. Existing installs are unaffected.
- **When on** — the clicker must pass the normal admission check **and** be listed in `allow_admin_from` (the same key the slash-command split uses). The lower-stakes component views (model picker, clarify, update prompt) stay user-scope.
- **Fails closed** — if the toggle is on but `allow_admin_from` is empty, *nobody* can approve and a warning is logged, so the misconfiguration is visible rather than silently locking you out.
## Interactive Model Picker
Send `/model` with no arguments in a Discord channel to open a dropdown-based model picker:
@ -757,9 +738,34 @@ Refreshing the directory (`/channels refresh` on platforms that expose it, or a
### Bot is online but not responding to messages
**Cause**: Message Content Intent is disabled.
**Cause**: Either Message Content Intent is disabled, or Discord auth is failing closed because no access policy is configured.
**Fix**: Go to [Developer Portal](https://discord.com/developers/applications) → your app → Bot → Privileged Gateway Intents → enable **Message Content Intent** → Save Changes. Restart the gateway.
**Fix**:
1. Go to [Developer Portal](https://discord.com/developers/applications) → your app → Bot → Privileged Gateway Intents → enable **Message Content Intent** → Save Changes.
2. Verify that at least one Discord access policy is configured:
```bash
# recommended: allow specific users
DISCORD_ALLOWED_USERS=284102345871466496
# or allow a trusted guild/dev bot to behave like pre-0.18 Discord
DISCORD_ALLOW_ALL_USERS=true
```
3. Restart the gateway:
```bash
hermes gateway restart
```
If the gateway log says Discord is connected and REST API checks work, but every inbound message is silent, look for this warning in `~/.hermes/logs/gateway.log`:
```text
No Discord access policy configured; inbound Discord messages will be denied by default.
```
Hermes 0.18 intentionally fails closed on externally reachable adapters. A Discord bot with no `DISCORD_ALLOWED_USERS`, no `DISCORD_ALLOWED_ROLES`, no `DISCORD_ALLOWED_CHANNELS`, and no explicit allow-all flag will connect successfully but deny inbound users before normal message handling.
### "Disallowed Intents" error on startup