Skip to content

Discord

The Discord adapter connects an agent to a Discord bot. It handles message sending and receiving, history, reactions, slash commands, and attachments.

The adapter starts automatically when config/channels/discord.toml exists. The file is not created by init; create it to enable the integration.

Configuration

toml
token = "MTxxxxxxxxxxxxxxxxxxxxxxxx.xxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ownerId = "123456789012345678"

# REST request timeout in ms (default 60000)
timeout = 30000

# Seconds the gateway may stay silent before the runtime reconnects (default 600)
gatewaySilenceTimeout = 600

# Restrict who can interact in guild channels
access = { mode = "allowlist", users = ["123456789012345678"] }

# Restrict who can DM the agent
directMessages = { mode = "owner", users = [] }

# Grant non-owner users permission to run specific slash commands
[[trustedUsers]]
ids = ["987654321098765432"]
allowedCommands = ["stop", "summarize", "model query"]
FieldRequiredDefaultDescription
tokenYesBot token from the Discord Developer Portal.
ownerIdYesDiscord user ID of the bot operator (numeric snowflake).
timeoutNo60000REST request timeout in milliseconds.
gatewaySilenceTimeoutNo600Seconds the gateway may stay silent before the runtime reconnects; minimum 60.
accessNodisabledGuild channel access restriction.
directMessagesNoownerDirect-message access mode.
trustedUsersNo[]Users allowed to run specific commands.

Access modes

access controls who can interact with the agent in guild channels.

ModeBehavior
disabledAnyone can interact (default).
allowlistOnly users in users can interact, plus the owner.
denylistEveryone can interact except users in users.

The ownerId user always bypasses access control regardless of mode.

Direct message modes

directMessages controls who can DM the agent.

ModeBehavior
ownerOnly the owner can DM (default).
publicAnyone can DM.
allowlistOnly users in users can DM, plus the owner.
denylistEveryone can DM except users in users.

Trusted users

trustedUsers grants specific users permission to run specific slash commands without being the owner.

FieldRequiredDescription
idsYesArray of Discord user IDs (numeric snowflakes) that share this permission set.
allowedCommandsYesArray of slash command names as used internally, e.g. stop, summarize, model query.

Subcommands use the form "<command> <subcommand>". The owner is always allowed to run every command and subcommand. Message commands and the error-reaction cleanup remain owner-only.

Slash commands

Slash commands and subcommands are restricted to the owner and to trusted users whose allowedCommands includes the command path.

CommandSubcommandsDescription
/clearReset conversation history for the channel; super keeps a history barrier.
/closeClose an open file in the current session.
/inviteGet an invite link for the bot.
/modeloverride, clear, clear-all, querySwitch the provider or model for this session.
/repairRepair corrupted Discord media attachments.
/stopGracefully stop the current generation.
/summarizeSummarize a described portion of the conversation.
/unsummarizeRemove the most recent summary.

/model override stores a provider and model on the current session. /model clear removes both values instead of storing the current global default, so subsequent turns follow the agent's current global provider and model when engine.toml is reloaded.

Unauthorized users receive an ephemeral "You are not authorized to use this command." response.

Message commands

The owner can use the message Apps menu on bot messages.

CommandBehavior
Delete MessageDelete the message from Discord and remove it from session history.
Reroll ResponseDelete the message and everything after it, then regenerate a response.

Owner error-reaction cleanup

The owner can react with ✨ to a bot error message to delete it. This works only on messages starting with ⚠️ Engine error, :warning: Engine error, ⚠️ Discord error, or :warning: Discord error. Reactions from other users or on other messages are ignored.

Required intents

Enable the following gateway intents for the bot in the Discord Developer Portal:

  • GUILD_MESSAGES
  • DIRECT_MESSAGES
  • MESSAGE_CONTENT
  • GUILD_MESSAGE_REACTIONS
  • DIRECT_MESSAGE_REACTIONS
  • GUILD_MEMBERS

Message processing

Guild messages are processed when the bot is mentioned or when the message replies to a bot message. Direct messages are processed according to the configured DM mode.

Each turn reads the recent channel history and crawls reply chains for full thread context. Long responses are split at sensible boundaries to stay under Discord's 2000-character limit; splits keep code fences open across chunks.

Message edits update the stored history in place, and message deletions remove the deleted message from internal history on the next turn.

Supported content

Images are downloaded and converted to WebP before being sent to the model. Stickers are fetched and converted to WebP; Lottie stickers are skipped. Videos are sent only when the selected model supports video and the attachment is within the size cap. File and text attachments are described with metadata; only images and videos are fetched and sent to the model.

Gateway liveness

Discord answers every heartbeat, so a healthy connection always produces traffic even when no one is talking to the bot. The runtime records that traffic and treats prolonged silence as a dead connection, which is what a half-open TCP socket looks like from userspace: the socket still reports itself as open, but no payload will ever arrive again.

When the gateway has been silent for gatewaySilenceTimeout seconds the runtime aborts the connection so the client reconnects. A blocked read cannot be interrupted by cancellation, but aborting the socket releases it immediately. If payloads still do not resume within two minutes the runtime replaces its gateway client entirely, because a fatal error can stop the client without affecting the rest of the runtime.

Each recovery step is logged at warning or error level. Without this watchdog the failure is invisible: sessions, heartbeats, and REST sends keep working while the bot looks offline in every channel.

Restart requirement

Changes to channels/discord.toml require a full runtime restart.

Are you an agent? Prefer this page's raw Markdown document: follow its text/markdown alternate link, use its .md URL, or add ?md=1 to the page URL.