@anvia/discord
@anvia/discord provides a production-oriented channel adapter backed by the Discord Gateway for inbound events and the Discord REST API for outbound messages.
Start with discord() unless you are replacing its transport.
Which utility should I use?
| Task | Utility |
|---|---|
| Normal application or agent | discord() |
| Dependency-inject a custom gateway | new DiscordChannel({ gateway }) |
Use the built-in raw discord.js transport directly | DiscordJsGateway |
| Implement a replacement transport | DiscordGateway interface |
| Normalize a validated gateway value | normalizeDiscordEvent() |
| Normalize messages, actions, or commands | normalizeDiscordMessage(), normalizeDiscordAction(), normalizeDiscordCommand() |
| Render command options as text | discordCommandOptionText() |
| Validate Discord IDs in application configuration | isDiscordSnowflake(), validateDiscordSnowflake() |
The low-level exports are extension points. A normal bot should not call a normalizer manually or construct DiscordJsGateway itself.
Configure the Discord application
- Create an application and bot in the Discord Developer Portal.
- Enable Message Content Intent when the bot must read ordinary guild messages. The adapter requests that privileged intent by default.
- Install the bot with
VIEW_CHANNEL,SEND_MESSAGES, andREAD_MESSAGE_HISTORY. - Add
SEND_MESSAGES_IN_THREADSfor thread replies,ATTACH_FILESfor outbound files, andADD_REACTIONSwhen usingchannel.react(). - Grant access only to the servers and channels the application should process.
Set messageContentIntent: false for a mention-only guild bot that does not have privileged intent approval. Discord still supplies message content in direct messages, messages sent by the bot, and messages that mention the bot. See Discord's Gateway intent documentation and permission reference for application setup details.
Create the adapter
import { discord } from '@anvia/discord'
const channel = discord({
token: process.env.DISCORD_BOT_TOKEN!,
messageContentIntent: true,
maximumAttachmentBytes: 25 * 1024 * 1024,
onError(error, context) {
console.error('discord', context.operation, error)
},
})messageContentIntent defaults to true and maximumAttachmentBytes defaults to 25 MiB. The byte limit caps each outbound file and the combined bytes buffered for one message. URL-backed outbound files are downloaded sequentially with redirects rejected; pass a custom fetch that allowlists trusted hosts when attachment URLs are not controlled by your application.
onError receives the error and a context object whose operation is 'gateway' for connection problems or 'handle' when an event handler threw; the failing gateway event is attached in the latter case. Observer failures never terminate delivery.
Agent integration
import { createChannelAgent } from '@anvia/channel-agent'
const service = createChannelAgent({ channel, agent })
await service.start()The channel-agent default filter handles direct messages plus guild messages that mention or reply to the bot (see Channel agent). Use service.stop(), not channel.stop(), when the service started the adapter.
Continue with
- Discord messaging — send, threads, attachments, edits, and reactions.
- Receive Discord events — Gateway input and normalization.
- Custom Discord gateway — own the connection and shut down cleanly.
- Releases — current version and package history.