Skip to content

Discord Integration

OpenClaw integrates with Discord via the official Discord Bot API. This allows you to create powerful Discord bots that can handle direct messages, server channels, slash commands, and rich interactions.

  • Discord account
  • Discord server (create one for testing)
  • Bot token from Discord Developer Portal
  1. Create a Discord bot:

  2. Enable required intents:

    • Message Content Intent
    • Server Members Intent (for allowlists)
    • Direct Messages Intent
  3. Configure OpenClaw (~/.openclaw/openclaw.json):

{
channels: {
discord: {
enabled: true,
token: "YOUR_BOT_TOKEN_HERE"
}
}
}
  1. Invite bot to server:

    • Generate OAuth2 URL in Developer Portal
    • Include bot permissions: Read Messages/View Channels, Send Messages, Embed Links
  2. Start the gateway:

Terminal window
openclaw gateway
{
channels: {
discord: {
// Bot configuration
enabled: true,
token: "YOUR_BOT_TOKEN_HERE",
// Gateway intents
intents: [
"GUILDS",
"GUILD_MESSAGES",
"DIRECT_MESSAGES",
"MESSAGE_CONTENT"
],
// Direct message policy
dm: {
policy: "pairing", // "pairing", "allowlist", "denylist", "open"
allowFrom: ["123456789012345678"], // User IDs
blockFrom: ["987654321098765432"],
groupEnabled: false, // Group DMs
groupChannels: [] // Specific group DM channels
},
// Server and channel permissions
allowedServers: ["123456789012345678"], // Server IDs
allowedChannels: ["123456789012345678"], // Channel IDs
blockedServers: [],
blockedChannels: [],
// Message settings
messages: {
maxMessageLength: 2000,
embeds: true,
reactions: true,
typingIndicator: true,
mentionEveryone: false
}
}
}
}
{
channels: {
discord: {
// Activity and presence
presence: {
status: "online", // "online", "idle", "dnd", "invisible"
activities: [
{
name: "OpenClaw Assistant",
type: "PLAYING" // "PLAYING", "STREAMING", "LISTENING", "WATCHING", "COMPETING"
}
]
},
// Slash commands
commands: {
enabled: true,
commands: {
"help": {
description: "Show available commands",
options: []
},
"status": {
description: "Check bot status",
options: []
},
"ask": {
description: "Ask OpenClaw a question",
options: [
{
name: "question",
description: "Your question for OpenClaw",
type: "STRING",
required: true
}
]
}
}
},
// Message handling
messageHandling: {
respondToBots: false,
respondToEdits: false,
deleteCommandMessages: false,
errorReplyType: "reply" // "reply", "dm", "none"
},
// Embed settings
embeds: {
color: 0x00ff00, // Green color
author: {
name: "OpenClaw",
icon_url: "https://example.com/avatar.png"
},
footer: {
text: "Powered by OpenClaw",
icon_url: "https://example.com/icon.png"
}
},
// Rate limiting
rateLimit: {
enabled: true,
maxMessages: 5,
windowMs: 5000,
skipSuccessfulRequests: false
}
}
}
}
  • Secure pairing: Pairing system for unknown users
  • Session management: Persistent conversation context
  • Rich formatting: Markdown and embed support
  • File sharing: Send and receive files
  • Channel-specific responses: Different behavior per channel
  • Mention-based activation: Respond only when mentioned
  • Role-based permissions: Control access by Discord roles
  • Server-specific settings: Custom configuration per server
  • Built-in commands: /help, /status, /ask
  • Custom commands: Define your own slash commands
  • Command options: Rich command interfaces with parameters
  • Auto-registration: Commands auto-register with Discord
  • Embeds: Rich message formatting with embeds
  • Reactions: Add reactions to messages
  • Buttons: Interactive button components
  • Select menus: Dropdown selection interfaces
Terminal window
# Set Discord bot token
openclaw config set channels.discord.token "YOUR_BOT_TOKEN_HERE"
# Enable specific server
openclaw config set channels.discord.allowedServers '["123456789012345678"]'
# Test Discord connection
openclaw channels test discord
# Send a direct message
openclaw message send --channel discord --target 123456789012345678 --message "Hello from OpenClaw!"
# Send to server channel
openclaw message send --channel discord --target 123456789012345678 --message "Hello everyone!" --server 987654321098765432

Once configured, users can interact with your bot:

User: /help
Bot: 🤖 **OpenClaw Commands**
/help - Show this help message
/status - Check bot status
/ask <question> - Ask OpenClaw a question
/code <code> - Execute code
User: /ask What's the weather like today?
Bot: 🌤️ I don't have access to real-time weather data, but I can help you create a weather checker! Would you like me to write a script using a weather API?
User: @OpenClaw Write a Python function to calculate factorial
Bot: 🐍 Here's a Python function to calculate factorial:
```python
def factorial(n):
"""Calculate factorial of a non-negative integer."""
if n < 0:
raise ValueError("Factorial is not defined for negative numbers")
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
# Test the function
for i in range(6):
print(f"{i}! = {factorial(i)}")

Output:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120

User: /status Bot: 📊 Bot Status

  • Status: 🟢 Online
  • Uptime: 2h 34m
  • Servers: 3
  • Channels: 12
  • Messages processed: 247
  • Active users: 45
## Slash Commands
### Registering Commands
Commands are automatically registered when the bot starts. You can also register them manually:
```bash
# Register all commands
openclaw discord commands register
# Register specific commands
openclaw discord commands register --command help
openclaw discord commands register --command status
# View registered commands
openclaw discord commands list

Create custom slash command handlers:

~/.openclaw/handlers/discord.js
module.exports = {
slashCommands: {
weather: async (interaction) => {
const location = interaction.options.getString('location');
// Fetch weather data
const weather = await getWeather(location);
const embed = {
title: `Weather in ${location}`,
description: `${weather.temp}°C, ${weather.description}`,
color: 0x3498db,
fields: [
{ name: 'Humidity', value: `${weather.humidity}%`, inline: true },
{ name: 'Wind Speed', value: `${weather.wind} km/h`, inline: true }
],
timestamp: new Date().toISOString()
};
await interaction.reply({ embeds: [embed] });
},
code: async (interaction) => {
const code = interaction.options.getString('code');
const language = interaction.options.getString('language') || 'python';
try {
const result = await executeCode(code, language);
const embed = {
title: 'Code Execution Result',
fields: [
{ name: 'Input', value: `\`\`\`${language}\n${code}\`\`\`` },
{ name: 'Output', value: `\`\`\`\n${result}\`\`\`` }
],
color: 0x00ff00
};
await interaction.reply({ embeds: [embed] });
} catch (error) {
await interaction.reply({
content: `❌ Error: ${error.message}`,
ephemeral: true
});
}
}
}
};

Add interactive buttons and select menus:

// Send message with buttons
await interaction.reply({
content: 'Choose an option:',
components: [
{
type: 'ACTION_ROW',
components: [
{
type: 'BUTTON',
customId: 'help',
label: 'Help',
style: 'PRIMARY'
},
{
type: 'BUTTON',
customId: 'status',
label: 'Status',
style: 'SECONDARY'
}
]
}
]
});
// Handle button interactions
module.exports = {
onInteraction: async (interaction) => {
if (interaction.isButton()) {
switch (interaction.customId) {
case 'help':
await interaction.update({ content: 'Here\'s help information...' });
break;
case 'status':
await interaction.update({ content: 'Bot status information...' });
break;
}
}
}
};

Enable voice channel features:

{
channels: {
discord: {
voice: {
enabled: true,
autoJoin: false,
joinChannels: ["123456789012345678"], // Voice channel IDs
autoDisconnect: true,
maxSilenceTime: 300000 // 5 minutes
}
}
}
}

Configure Discord webhooks:

{
channels: {
discord: {
webhooks: {
onMessage: {
url: "https://your-api.com/webhook/discord",
secret: "webhook-secret",
events: ["message", "interaction"]
},
onJoin: {
url: "https://your-api.com/webhook/join",
events: ["guildJoin", "guildMemberAdd"]
}
}
}
}
}
  • Environment variables: Store tokens in environment variables
  • File permissions: Restrict access to config files
  • Token rotation: Regularly rotate bot tokens
  • Access monitoring: Monitor token usage patterns
  • Server whitelisting: Only allow specific servers
  • Channel permissions: Restrict bot to specific channels
  • Role-based access: Use Discord roles for permissions
  • Audit logging: Log all bot actions
  • Input validation: Validate all user inputs
  • Content filtering: Filter inappropriate content
  • Rate limiting: Prevent spam and abuse
  • Command sanitization: Sanitize command inputs

Bot Not Responding

Terminal window
# Check bot token
openclaw config get channels.discord.token
# Test Discord connection
openclaw channels test discord
# Check gateway logs
openclaw gateway logs --filter discord
# Verify bot permissions in Discord server

Commands Not Working

Terminal window
# Check command registration
openclaw discord commands list
# Re-register commands
openclaw discord commands register --force
# Check intents configuration
openclaw config get channels.discord.intents

Permission Issues

Terminal window
# Check allowed servers
openclaw config get channels.discord.allowedServers
# Verify bot has required permissions
# In Discord: Server Settings → Roles → Bot Role → Permissions
# Test channel access
openclaw channels test discord --channel 123456789012345678

Rate Limiting

Terminal window
# Check rate limit status
openclaw channels status discord --rate-limit
# Adjust rate limits
openclaw config set channels.discord.rateLimit.maxMessages 10
# Monitor API usage
openclaw channels metrics discord

Enable detailed logging for Discord:

Terminal window
# Enable debug logging
openclaw config set logging.components.discord debug
# Restart with debug
openclaw gateway restart --debug
# View Discord logs
openclaw gateway logs --follow --filter discord
  1. Bot Design

    • Clear command structure
    • Helpful error messages
    • Consistent user experience
    • Accessibility considerations
  2. Performance

    • Implement proper caching
    • Use efficient data structures
    • Monitor API usage
    • Optimize database queries
  3. Security

    • Validate all inputs
    • Use HTTPS for webhooks
    • Implement rate limiting
    • Regular security audits
  4. User Experience

    • Use embeds for rich content
    • Implement typing indicators
    • Provide clear feedback
    • Handle errors gracefully
Terminal window
# Discord channel management
openclaw channels test discord
openclaw channels status discord [--detailed]
openclaw discord commands register [--force]
openclaw discord commands list
# Message operations
openclaw message send --channel discord --target 123456789012345678 --message "Hello"
openclaw message send --channel discord --target 123456789012345678 --file ./image.png
openclaw message broadcast --channel discord --server 987654321098765432 --message "Announcement"
# Configuration
openclaw config set channels.discord.token "your-token"
openclaw config set channels.discord.dm.policy "pairing"
openclaw config get channels.discord
interface DiscordConfig {
enabled: boolean;
token: string;
intents?: string[];
dm?: {
policy: "pairing" | "allowlist" | "denylist" | "open";
allowFrom?: string[];
blockFrom?: string[];
groupEnabled?: boolean;
groupChannels?: string[];
};
allowedServers?: string[];
allowedChannels?: string[];
blockedServers?: string[];
blockedChannels?: string[];
messages?: {
maxMessageLength?: number;
embeds?: boolean;
reactions?: boolean;
typingIndicator?: boolean;
mentionEveryone?: boolean;
};
presence?: {
status: "online" | "idle" | "dnd" | "invisible";
activities?: Array<{
name: string;
type: "PLAYING" | "STREAMING" | "LISTENING" | "WATCHING" | "COMPETING";
}>;
};
commands?: {
enabled: boolean;
commands?: { [command: string]: SlashCommand };
};
voice?: {
enabled: boolean;
autoJoin?: boolean;
joinChannels?: string[];
autoDisconnect?: boolean;
maxSilenceTime?: number;
};
rateLimit?: {
enabled: boolean;
maxMessages: number;
windowMs: number;
skipSuccessfulRequests?: boolean;
};
}

Your Discord bot is now ready! You can start building powerful Discord experiences with OpenClaw. 🎮