Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/disgoorg/disgo/llms.txt

Use this file to discover all available pages before exploring further.

Basic concepts

DisGo is built around a modular architecture that separates concerns into distinct components. Understanding these core concepts will help you build robust Discord bots.

Architecture overview

Client

The high-level interface that combines all components

Gateway

WebSocket connection for real-time events

REST

HTTP client for API requests

Events

Type-safe event handling system

The Client

The bot.Client is the central component of DisGo. It combines the Gateway, REST API, event system, cache, and optional features like sharding and voice into one cohesive interface.

Client structure

type Client struct {
    Token                 string
    ApplicationID         snowflake.ID
    Logger                *slog.Logger
    Rest                  rest.Rest
    EventManager          EventManager
    Gateway               gateway.Gateway
    ShardManager          sharding.ShardManager
    HTTPServer            httpserver.Server
    VoiceManager          voice.Manager
    Caches                cache.Caches
    MemberChunkingManager MemberChunkingManager
}
Each component serves a specific purpose and can be configured or replaced independently.

Creating a client

The most common way to create a client is using disgo.New() with configuration options:
client, err := disgo.New(token,
    // Configure Gateway
    bot.WithGatewayConfigOpts(
        gateway.WithIntents(gateway.IntentGuilds, gateway.IntentGuildMessages),
    ),
    // Add event listeners
    bot.WithEventListenerFunc(myEventHandler),
    // Configure logging
    bot.WithLogger(customLogger),
    // Configure cache
    bot.WithCacheConfigOpts(cache.WithCaches(cache.FlagsAll)),
)
DisGo uses the functional options pattern for configuration. Each With* function returns a configuration option that modifies the client.

Gateway connection

The Gateway is a WebSocket connection to Discord that allows your bot to receive real-time events. It’s responsible for:
  • Establishing and maintaining the WebSocket connection
  • Sending and receiving Gateway messages
  • Handling heartbeats and reconnection
  • Managing connection state

Gateway lifecycle

1

Connect

Open the Gateway connection with client.OpenGateway(ctx).
2

Identify

The Gateway sends an Identify payload with your token and intents.
3

Ready

Discord sends a Ready event with your bot’s information and initial state.
4

Events

Your bot receives events in real-time as they occur.
5

Heartbeat

The Gateway sends periodic heartbeats to keep the connection alive.

Gateway status

The Gateway progresses through several states:
const (
    StatusUnconnected     // Initial state
    StatusConnecting      // Establishing connection
    StatusWaitingForHello // Waiting for Hello opcode
    StatusIdentifying     // Sending Identify
    StatusWaitingForReady // Waiting for Ready event
    StatusReady           // Fully connected and ready
    StatusDisconnected    // Disconnected
)

Gateway intents

Intents tell Discord which events you want to receive. This reduces bandwidth and improves performance by filtering out unwanted events.
gateway.WithIntents(
    gateway.IntentGuilds,              // Guild lifecycle events
    gateway.IntentGuildMessages,        // Message events in guilds
    gateway.IntentGuildMessageReactions, // Reaction events
    gateway.IntentDirectMessages,       // DM events
    gateway.IntentMessageContent,       // Message content (privileged)
)
Privileged intents (MessageContent, GuildMembers, GuildPresences) must be enabled in the Discord Developer Portal and require approval for verified bots.

REST API

The REST client handles HTTP requests to Discord’s API. It provides methods for:
  • Creating, updating, and deleting resources
  • Fetching data from Discord
  • Managing rate limits automatically
  • Handling pagination
Access the REST client through client.Rest.

Making REST requests

// Send a message
message, err := client.Rest.CreateMessage(
    channelID,
    discord.NewMessageCreateBuilder().
        SetContent("Hello, Discord!").
        SetEmbeds(myEmbed).
        Build(),
)

// Get guild information
guild, err := client.Rest.GetGuild(guildID, true)

// Update a role
role, err := client.Rest.UpdateRole(
    guildID,
    roleID,
    discord.RoleUpdate{
        Name:  omit.New("New Role Name"),
        Color: omit.New(0xFF0000),
    },
)

Rate limiting

DisGo automatically handles Discord’s rate limits:
  • Per-route rate limits: Managed automatically per endpoint
  • Global rate limits: Respected across all requests
  • Retry-After: Automatically waits when rate limited
// Configure rate limiter behavior
bot.WithRestConfigOpts(
    rest.WithRateLimiter(customRateLimiter),
)
DisGo queues requests when rate limited, so you don’t need to handle rate limits in your code.

Event system

DisGo’s event system is type-safe and flexible. Events are dispatched when Gateway messages are received, allowing you to react to changes in Discord.

Event types

Common events include:
EventDescription
MessageCreateNew message sent
MessageUpdateMessage edited
MessageDeleteMessage deleted
GuildCreateGuild became available
GuildMemberAddMember joined guild
GuildMemberRemoveMember left guild
InteractionCreateInteraction received
ReadyBot connected and ready

Listening for events

There are several patterns for handling events:
// Simple function listener
bot.WithEventListenerFunc(func(event *events.MessageCreate) {
    if event.Message.Content == "!hello" {
        client.Rest.CreateMessage(
            event.ChannelID,
            discord.NewMessageCreateBuilder().
                SetContent("Hello!").
                Build(),
        )
    }
})

Event data

All events implement the Event interface:
type Event interface {
    Client() *bot.Client        // Access to the client
    SequenceNumber() int        // Gateway sequence number
}
Each event type provides specific data:
func handleMessage(event *events.MessageCreate) {
    // Access message data
    content := event.Message.Content
    author := event.Message.Author
    channelID := event.ChannelID
    
    // Access client
    client := event.Client()
    
    // Send response
    client.Rest.CreateMessage(channelID, ...)
}

Cache system

DisGo includes a built-in cache to store Discord entities locally, reducing API calls and improving performance.

Cached entities

The cache can store:
  • Guilds and their properties
  • Channels
  • Members
  • Roles
  • Messages
  • Users
  • Voice states
  • Presences

Configuring caches

client, err := disgo.New(token,
    bot.WithCacheConfigOpts(
        // Cache everything
        cache.WithCaches(cache.FlagsAll),
        
        // Or select specific caches
        cache.WithCaches(
            cache.FlagGuilds |
            cache.FlagChannels |
            cache.FlagMembers,
        ),
    ),
)

Using the cache

// Get from cache
if guild, ok := client.Caches.Guild(guildID); ok {
    fmt.Println("Guild name:", guild.Name)
}

// Get all guilds
guilds := client.Caches.Guilds()

// Get channel
if channel, ok := client.Caches.Channel(channelID); ok {
    fmt.Println("Channel name:", channel.Name())
}
The cache is automatically updated by Gateway events. You rarely need to manually populate it.

Custom cache implementations

You can provide your own cache implementation:
type MyCache struct {
    // Your custom cache logic
}

func (c *MyCache) Guild(id snowflake.ID) (discord.Guild, bool) {
    // Custom implementation
}

bot.WithCache(cache.NewWithCaches(myCustomCache))

Sharding

When your bot is in many guilds (typically 2,500+), you need sharding to split the Gateway connection across multiple shards.

Why shard?

  • Discord requires sharding for large bots
  • Distributes load across connections
  • Improves reliability and scalability
  • Each shard handles a subset of guilds

Using the ShardManager

client, err := disgo.New(token,
    // Use ShardManager instead of Gateway
    bot.WithShardManagerConfigOpts(
        // Auto-detect shard count from Discord
        sharding.WithAutoSharding(),
        
        // Or specify manually
        sharding.WithShardCount(4),
        sharding.WithShardIDs(0, 1, 2, 3),
        
        // Configure gateway options for all shards
        sharding.WithGatewayConfigOpts(
            gateway.WithIntents(gateway.IntentGuilds),
        ),
    ),
)

// Open all shards
if err := client.OpenShardManager(ctx); err != nil {
    panic(err)
}

Accessing specific shards

// Get shard for a guild
shard, err := client.Shard(guildID)

// Get shard by ID
shard := client.ShardManager.Shard(0)

// Iterate all shards
for _, shard := range client.ShardManager.Shards() {
    fmt.Printf("Shard %d status: %s\n", shard.ShardID(), shard.Status())
}
Discord automatically assigns guilds to shards. You don’t need to manage shard assignment yourself.

HTTP Interactions

For high-traffic bots, you can handle interactions via HTTP instead of the Gateway:
client, err := disgo.New(token,
    bot.WithHTTPServerConfigOpts(
        httpserver.WithURL("https://yourbot.com/interactions"),
        httpserver.WithPublicKey("your_public_key"),
    ),
)

// Start HTTP server
if err := client.HTTPServer.Start(); err != nil {
    panic(err)
}
HTTP interactions:
  • Reduce Gateway load
  • Scale horizontally more easily
  • Required for interaction-only bots

Logging

DisGo uses Go’s standard log/slog package for structured logging:
import "log/slog"

// Create custom logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
    Level: slog.LevelDebug,
}))

client, err := disgo.New(token,
    bot.WithLogger(logger),
)
Log levels:
  • Debug: Detailed diagnostic information
  • Info: General informational messages
  • Warn: Warning messages
  • Error: Error messages

Next steps

Now that you understand DisGo’s core concepts, explore more advanced topics:

Slash commands

Build modern application commands

Message components

Create interactive buttons and menus

Voice connections

Connect to voice channels

Examples

Browse working examples

Build docs developers (and LLMs) love