Skip to main content
The Discord adapter connects NanoClaw to a bot you create in the Discord Developer Portal. It’s built on the Chat SDK bridge (@chat-adapter/discord 4.26.0, pinned — the /add-discord skill may pin a slightly newer adapter version) and connects over Discord’s Gateway — a WebSocket NanoClaw opens outbound, with events forwarded to a local loopback server. No public URL, webhook, or open port needed; works behind NAT and on a laptop. The bot works in server text channels, threads, and DMs.

Prerequisites

  • A Discord account, and a server you can add the bot to (the wizard walks you through creating both the app and a server if needed)
  • A working NanoClaw install (quickstart)
  • A bot from the Developer Portal with Message Content Intent enabled (under BotPrivileged Gateway Intents) — without it the bot connects but can’t read message text
  • The bot token from the Bot tab. That’s the only thing you paste — the wizard derives the application ID and public key from the token via Discord’s API.

Install

Discord is offered in the first-run setup wizard, or add it later by running /add-discord in Claude Code. The wizard flow:
1

Create the bot (if you don't have one)

The wizard opens the Developer Portal: click New Application, then in the Bot tab click Reset Token, copy the token, and enable Message Content Intent.
2

Paste the token

The wizard format-validates it, calls /users/@me to confirm Discord accepts it and resolve the bot’s username, then calls /oauth2/applications/@me to derive the application ID and public key. If a DISCORD_BOT_TOKEN already exists in .env, it offers to reuse it.
3

Confirm your identity

The wizard reads the app owner from the API and asks “Is @you your Discord account?”. If the app is team-owned (or you decline), it falls back to a manual user-ID prompt with Developer Mode instructions.
4

Invite the bot to a server

The bot can’t DM you until you share a server. The wizard generates and opens the OAuth invite URL (scope bot, permissions 100416: Send Messages, Read Message History, Add Reactions, Attach Files) — pick any server, a personal one is fine.
5

Adapter install

setup/add-discord.sh copies the adapter from the channels branch, installs the pinned package, builds, writes DISCORD_BOT_TOKEN, DISCORD_APPLICATION_ID, and DISCORD_PUBLIC_KEY to .env (synced to data/env/env), and restarts the service.
6

Name the agent and get the welcome DM

The wizard opens a DM channel with you via the API, asks for your operator role and an agent name (default Nano), wires the DM to your first agent group, and sends a welcome message.
To wire server channels or more DMs later, run /manage-channels. Server channels are identified as discord:<guildId>:<channelId> (enable Developer Mode in Discord, then right-click the server for the guild ID and the channel for the channel ID); DMs as discord:@me:<dmChannelId>.

Platform notes

  • Gateway connection with backoff — the bridge starts a Gateway listener in 24-hour cycles and forwards raw events (including button clicks) to a local HTTP server bound to 127.0.0.1. If the listener dies, it reconnects with exponential backoff (1s doubling per consecutive failure, capped at 1 hour); a run lasting over 5 minutes counts as healthy and resets the counter. The cap exists because an unrecoverable failure like a bad token would otherwise restart ~10×/sec and get the IP blocked by Discord’s Cloudflare layer.
  • Threads — the adapter sets supportsThreads: true, and on server channels the router gives every thread its own agent session automatically: even wirings set to shared behave as per-thread here. Only agent-shared (one session across all of an agent’s messaging groups) overrides this. In DMs the forcing doesn’t apply: shared wirings get a single session regardless of sub-threads, while an explicit per-thread wiring is honored — see the entity model.
  • Mentions and engagement — @mentioning the bot in an unwired channel is platform-confirmed and reaches the router as a mention; in mention-sticky wirings the bot then sticks to that thread (plain mention wirings respond per mention without subscribing). DMs are always treated as addressed to the bot.
  • Replies and attachments — replying to a message passes the quoted text and sender (display name or username) to the agent as context. Attachments are downloaded and passed to the agent as data, not just described.
  • Interactive questions — when an agent asks a multiple-choice question, it renders as an embed with buttons; your click arrives via the Gateway and the card updates in place to show the selection.
  • 2,000-character limit — Discord caps messages at 2,000 characters. The current adapter doesn’t enable the bridge’s automatic chunking, so longer replies can be truncated by the platform.
  • Typing indicator — the bot shows a typing indicator while the agent works.

Troubleshooting

  • “Discord didn’t accept that token”/users/@me rejected it. Tokens are only shown once in the Developer Portal; click Reset Token and copy the fresh one (the old one stops working). “Couldn’t reach Discord” instead means a network problem — check connectivity and retry setup.
  • Bot connects but never responds to textMessage Content Intent isn’t enabled. Developer Portal → your app → BotPrivileged Gateway Intents → enable it, then restart the service.
  • “Couldn’t open a DM channel with you” / no welcome message — the bot and your account don’t share a server yet. Open the invite URL, add the bot to any server you’re in, then retry with /manage-channels.
  • Gateway listener error, retrying repeating in logs — the listener is in its backoff loop (the log line includes consecutiveFailures and the next delayMs). Growing delays usually mean an unrecoverable cause like an invalid token — fix the credential rather than waiting out the retry.
For service-level checks (logs, restarts, wiring queries), see troubleshooting.
Last modified on June 10, 2026