discord-connect — Connect and configure Hermes on Discord — bot setup, intents, OAuth2 scopes, permissions, and gateway configuration.
Scanned 9/11/2026
Install to Claude Code
npx -y skills add AtlasOmnia/hermes-custom-pack --skill discord-connect --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Discord Connect?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/atlasomnia-discord-connect)More formats (shields.io, HTML) on the badges page.
---
name: discord-connect
description: discord-connect — Connect and configure Hermes on Discord — bot setup, intents, OAuth2 scopes, permissions, and gateway configuration.
version: 1.0.0
license: MIT
platforms:
- macos
metadata:
hermes:
tags:
- discord
- gateway
- bot
- connection
- setup
---
# Discord Connection Guide
## Quick Setup Flow
1. **Create a bot application** — go to [Discord Developer Portal](https://discord.com/developers/applications), create a new application (or use an existing one).
2. **Generate a bot token** — under Bot → Reset Token, copy the token.
3. **Enable intents** — in Bot settings:
- **Message Content Intent** (required for reading messages)
- **Presence Intent** (optional, for online status)
4. **Generate OAuth2 invite URL** — use [OAuth2 URL Generator](https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot+applications.commands&permissions=3558496) and paste into browser.
5. **Invite to server** — pick your guild from the dropdown.
6. **Configure in Hermes** — `hermes gateway setup` or manually configure via config.yaml.
## Bot Permissions (Minimal)
For Hermes, you only need:
- **Send Messages** (0x2)
- **Read Message History** (0x100000)
- **View Channel** (0x400)
- **Use External Emojis** (0x1000000)
Nice to have: Embed Links, Add Reactions, Send Text-to-Speech, Manage Messages.
Shortcut: set permissions to **3558496** ("Moderator" preset).
## OAuth2 Scopes
- **`bot`** — essential, lets you invite it to servers
- **`applications.commands`** — enables slash commands (useful but not strictly required)
## Guild Install vs User Install
**Guild install** is the one that puts the bot into your servers. User install is for apps, not bots. When generating the OAuth2 link, make sure `guild` is in the scope (usually default).
## Gotchas
- **Private applications cannot have a default authorization link.** Generate manually via OAuth2 URL Generator.
- **Message Content Intent must be enabled** — without it, the bot reads messages as empty strings and appears silent.
- **Presence Intent** — optional but useful for seeing when the bot is online/offline.
- **Prefer the exact invite URL generated by Discord Developer Portal** over improvising OAuth / Code Grant explanations from memory. If the generated link fails, inspect the portal settings rather than guessing about URL semantics.
- **Always verify prior state before assuming.** Don't assume a server exists, permissions are set, or the bot is already invited — ask first.
- **Discord connected is not the same as Discord usable.** A successful gateway login only proves the token works. Separately verify that the bot is invited to a guild, can see a text channel, slash commands appear there, and Hermes discovered the channel.
- **After adding the bot to a new server, restart the Hermes gateway** so `channel_directory.json` rebuilds against current guild visibility.
- **If `send_message(action='list')` still shows no Discord targets, inspect `~/.hermes/channel_directory.json`.** If it contains `"discord": []` while the bot is present in the server, treat it as a guild/channel discovery or visibility problem, not an auth failure.
- **Being connected is not the same as being installed.** `Connected as <botname>#xxxx` only proves the token works. It does NOT mean the bot has been added to the user's server.
- **If the bot is in the server but silent, check channel-level permissions before deeper debugging.** Minimum useful perms: View Channel, Send Messages, Read Message History, Use Application Commands; Embed Links preferred.
- **Always verify prior state before assuming.** Don't assume a server exists, permissions are set, or the bot is already invited — ask first.
## Invite/First-Use Verification
## Invite/First-Use Verification
1. Confirm Hermes shows Discord as configured and the gateway logs show `Connected as ...`.
2. Confirm the user has actually authorized the bot into a server — token connectivity alone is insufficient. Bot API `GET /users/@me/guilds` should return at least one guild after install.
3. After authorization, restart the Hermes gateway once so it re-discovers guilds/channels.
4. In Discord, confirm the bot appears in the server member list.
5. In a normal text channel, verify channel permissions: **View Channel**, **Send Messages**, **Read Message History**, **Use Application Commands**.
6. Verify Hermes channel discovery: `send_message(action='list')` or `~/.hermes/channel_directory.json` should show a Discord channel.
7. Test outbound text first with `send_message` to the discovered channel.
8. Then test a real user mention, e.g. `@<botname> test`, especially when `require_mention: true` is enabled in Hermes config.
9. If the bot only reacts with ✅ and no response appears, check authorization (`DISCORD_ALLOWED_USERS`) before deeper Discord debugging.
10. If Hermes still does not expose Discord send targets, treat that as a discovery/visibility problem, not proof that Discord auth failed.
- **Always verify prior state before assuming.** Don't assume a server exists, permissions are set, or the bot is already invited — ask first.
## Common Failure Pattern: `integration requires code grant`
When the user reports Discord showing **`integration requires code grant`** during install:
1. **Stop changing URL encoding by hand.** Do not bounce between `+`, `%20`, or hand-edited scopes unless Discord's generator itself produced the link.
2. **Ask whether the bot has already been added.** If yes, stop troubleshooting the invite link and switch to channel/mention verification.
3. **Prefer the exact link generated by Discord Developer Portal** over a manually reconstructed one.
4. **Verify the setting directly if you have the bot token:** `GET /api/v10/oauth2/applications/@me` with bot auth returns `bot_require_code_grant`. If true, the owner must disable **Bot → Authorization Flow → Requires OAuth2 Code Grant** in the Developer Portal and save. Bot tokens cannot patch this endpoint (`Bots cannot use this endpoint`).
5. **After disabling Code Grant, re-open the invite URL** and complete the guild install. If Discord presents hCaptcha, stop and have the user solve it; then continue automation.
6. **Once the bot is added, verify Hermes-side behavior with a first @mention** because `require_mention: true` and user authorization are common follow-on blockers.
## Common Failure Pattern: Only ✅ reaction, no text response
A ✅ reaction can mean Hermes received the Discord message but the gateway later dropped it before agent execution. Check gateway logs for `Unauthorized user: <id> (<name>) on discord`.
Fix path:
1. Get the Discord sender ID from logs or recent channel messages.
2. Add the user to `DISCORD_ALLOWED_USERS` in the active Hermes env/config. If using `.env` at gateway startup, ensure the value is present there too.
3. Restart the gateway.
4. Test with a real mention (`@<botname> test`) and verify logs show no `Unauthorized user` warning.
This is separate from channel permissions: outbound `send_message` can work while inbound user messages are still denied by Hermes authorization.
7. **If Discord presents hCaptcha at final Authorize, stop and ask the user to complete it.** Do not attempt CAPTCHA solving. Continue verification afterward.
8. **Once the bot is added, verify Hermes-side behavior with a first @mention** because `require_mention: true` is a common default.
7. **When the user asks the agent to “handle all of it,” use a safe login handoff:** open the Developer Portal, let the user authenticate via QR/passkey/password themselves, then continue. Never type their password or bypass 2FA.
8. **Once the bot is added, verify Hermes-side behavior with a first @mention** because `require_mention: true` is a common default.
## Profile-specific Discord gateways
When a Hermes profile is created for a specialized Discord bot persona (for example `support-bot`, `spanish-tutor`, or another training coach):
1. Prefer a dedicated Discord bot token per long-running profile. Do not leave multiple active gateways sharing the same Discord bot token; it can cause routing, voice joins, slash-command discovery, and session ownership weirdness.
2. Keep the profile's Discord toolset minimal for the job. For training profiles, a good baseline is `file`, `skills`, `memory`, `session_search`, `clarify`, and optional `tts`.
3. Disable unrelated surfaces in that profile (`telegram`, `api_server`, etc.) unless explicitly needed, to avoid accidental extra endpoints or port conflicts.
4. Verify profile-specific Discord readiness with:
```bash
<profile> tools list --platform discord
<profile> gateway status --full
```
5. Start foreground first for testing (`<profile> gateway run`), then install/start the profile gateway only after the bot token and guild/channel permissions are clean.
## Hermes Configuration
**CRITICAL: Token must be in `DISCORD_BOT_TOKEN` env var (in `.env`), not just `config.yaml`.**
The Discord adapter reads the token from `DISCORD_BOT_TOKEN` environment variable. Setting it only in `config.yaml`'s `discord.token` is NOT sufficient — the plugin won't pick it up.
```bash
# Set the token (writes to .env)
hermes config set DISCORD_BOT_TOKEN YOUR_TOKEN_HERE
# Verify it's there
python3 -c "import os; print('DISCORD_BOT_TOKEN:', 'configured' if os.environ.get('DISCORD_BOT_TOKEN') else 'not set')"
# Restart gateway — the plugin may be stuck in paused state from previous failures
launchctl stop ai.hermes.gateway && launchctl start ai.hermes.gateway
```
**Troubleshooting:**
- If `hermes status` shows Discord as "not configured" but you set the token, check `.env` for `DISCORD_BOT_TOKEN`. The config.yaml path (`discord.token`) is NOT checked by the adapter.
- After setting the token, always restart the gateway. The plugin can get stuck in its paused state (after 10 consecutive failures) and won't retry on subsequent starts.
- Token format: raw bot token (not base64 encoded). Length ~72 chars, contains `.` separators.
## Discord idle typing / apparent LLM polling
If Discord shows **<botname> is typing** while the user believes Hermes is idle, do not assume repeated model calls. First separate true repeated LLM turns from Discord typing/progress transport:
1. Check `~/.hermes/logs/gateway.log` for repeated `inbound message:` + `response ready:` pairs. Those indicate actual turns. Memory monitor / cron ticker / platform websocket lines do not.
2. Inspect the Discord adapter typing lifecycle. A persistent `/channels/{channel_id}/typing` refresh loop can make the bot appear active even when no new prompt is being launched.
3. Prefer a durable one-shot typing-pulse fix over merely telling the user to `/reset`: Discord `send_typing()` should send one pulse and leave no background typing task; `stop_typing()` should remain as stale-task cleanup.
4. Verify with focused Discord typing tests, restart `ai.hermes.gateway`, then watch at least ~45 seconds of logs for idle behavior.
## Discord Voice Setup / Troubleshooting
For `/voice join` / `/voice channel` to speak in Discord voice channels on macOS:
1. Verify Hermes can join the voice channel first; logs should show `VoiceReceiver started`.
2. If voice replies fail with `discord.errors.ClientException: ffmpeg was not found`, install playback dependencies:
```bash
brew install ffmpeg opus
```
3. Verify from the Hermes venv:
```bash
command -v ffmpeg
~/.hermes/hermes-agent/venv/bin/python - <<'PY'
import discord, shutil
print('ffmpeg_path', shutil.which('ffmpeg'))
if not discord.opus.is_loaded():
discord.opus.load_opus('/opt/homebrew/lib/libopus.dylib')
print('opus_loaded', discord.opus.is_loaded())
PY
```
4. Restart gateway:
```bash
launchctl stop ai.hermes.gateway && launchctl start ai.hermes.gateway
```
5. Confirm the new startup logs no longer show `Opus codec not found — voice channel playback disabled`.
6. Test from Discord while the user is in a voice channel: `/voice join`, then send a normal text/voice prompt and listen for TTS playback.
## Troubleshooting
- **Bot appears silent** — check Message Content Intent is enabled in Bot → Privileged Gateway Intents.
- **Bot not responding to messages** — verify the bot token in config matches the one from the developer portal.
- **Invite succeeded but Hermes still shows no Discord targets** — verify slash commands appear in a normal text channel, then inspect `~/.hermes/channel_directory.json`. If `discord` is empty, restart the gateway and treat it as channel discovery / visibility rather than auth failure.
- **Discord voice joins but does not speak** — install `ffmpeg` and `opus`, then restart gateway. The smoking-gun log is `Auto voice reply failed: ffmpeg was not found`.
- **Gateway dies on logout** — enable linger: `sudo loginctl enable-linger $USER`.
## Reference Files
## See Also
- [hermes-agent](../../autonomous-ai-agents/hermes-agent/SKILL.md) — broader Hermes configuration reference
- [platforms docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) — all messaging platform setups
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!