# Discord Connect

> discord-connect — Connect and configure Hermes on Discord — bot setup, intents, OAuth2 scopes, permissions, and gateway configuration.

- **Type:** Skill
- **Install:** `agentstack add skill-atlasomnia-donna-starter-discord-connect`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [AtlasOmnia](https://agentstack.voostack.com/s/atlasomnia)
- **Installs:** 0
- **Category:** [Communication](https://agentstack.voostack.com/c/communication)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [AtlasOmnia](https://github.com/AtlasOmnia)
- **Source:** https://github.com/AtlasOmnia/donna-starter/tree/main/skills/productivity/discord-connect

## Install

```sh
agentstack add skill-atlasomnia-donna-starter-discord-connect
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 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 #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. `@ 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:  () 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 (`@ 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
  tools list --platform discord
  gateway status --full
 ```
5. Start foreground first for testing (` 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 ** 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

- — step-by-step setup flow with gotchas captured from sessions.
- — what to check when the bot is in the server but Hermes still discovers zero Discord channels.
- — inspect and switch Discord voice replies between cloud TTS and local Piper/KittenTTS/NeuTTS providers.
- — API checks and fixes for Code Grant, guild install, channel discovery, and ✅-only unauthorized responses.
- — API probes and portal flow for `integration requires code grant`, bot-not-installed, final hCaptcha, and post-install Hermes verification.
- — diagnose the common case where the token is valid and the bot connects, but Discord API reports `guild_count 0`, meaning the bot has not been installed into any server.
- — end-to-end Discord voice setup/debugging: `/voice join`, ffmpeg/Opus, voice doctor, wrong-channel joins, and log verification.
- — move a Discord bot token from the default profile to a specialized profile, avoid token-owner conflicts, and verify the new profile gateway.

## 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

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [AtlasOmnia](https://github.com/AtlasOmnia)
- **Source:** [AtlasOmnia/donna-starter](https://github.com/AtlasOmnia/donna-starter)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** yes
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-atlasomnia-donna-starter-discord-connect
- Seller: https://agentstack.voostack.com/s/atlasomnia
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
