How to Make a Discord Bot with AI (Claude/GPT)
Build an intelligent Discord bot powered by Claude or GPT-4. Step-by-step tutorial with full code examples, rate limiting, and deployment options.
Molted Team
molted.cloud
Build an intelligent Discord bot powered by Claude or GPT-4. Step-by-step tutorial with full code examples, rate limiting, and deployment options.
Molted Team
molted.cloud
A Discord bot that actually understands context, answers questions intelligently, and maintains conversation history across messages. Not the keyword-matching bots of 2020, but a real AI that integrates with Claude or GPT-4. Building one from scratch teaches you API integration, rate limiting, and asynchronous programming. Or you can skip straight to using one.
A Discord bot that:
The complete code is around 200 lines. Not a weekend project, but a solid afternoon.
About that API key: You don't necessarily need a pay-as-you-go API key. If you already have a Claude Pro, ChatGPT Plus, or similar subscription, you can often use that instead. Tools like OpenClaw support subscription-based authentication, so you're not stuck paying $100+/month in API fees on top of your existing $20 subscription. Those Reddit horror stories about "$700/month API bills"? Completely avoidable.
Go to the Discord Developer Portal and click "New Application". Name it whatever you want.
In your application, go to Bot → Reset Token. Copy this token and save it securely. This is your bot's password; never commit it to git or share it publicly.
Under Bot → Privileged Gateway Intents, enable:
Go to OAuth2 → URL Generator. Select:
bot, applications.commandsSend Messages, Read Message History, View ChannelsCopy the generated URL and open it in your browser to add the bot to your server.
mkdir discord-ai-bot
cd discord-ai-bot
npm init -y
npm install discord.js @anthropic-ai/sdk dotenvCreate a .env file:
DISCORD_TOKEN=your-bot-token
ANTHROPIC_API_KEY=your-anthropic-keyCreate .gitignore:
.env
node_modules/Create index.js:
require('dotenv').config();
const { Client, GatewayIntentBits, Partials } = require('discord.js');
const Anthropic = require('@anthropic-ai/sdk');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.DirectMessages,
],
partials: [Partials.Channel],
});
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
// Store conversation history per channel
const conversations = new Map();
client.once('ready', () => {
console.log(`Logged in as ${client.user.tag}`);
});
client.on('messageCreate', async (message) => {
// Ignore bot messages
if (message.author.bot) return;
// Check if bot was mentioned or is a DM
const isMentioned = message.mentions.has(client.user);
const isDM = !message.guild;
if (!isMentioned && !isDM) return;
// Remove the mention from the message
const content = message.content
.replace(/<@!?\d+>/g, '')
.trim();
if (!content) return;
// Get or create conversation history
const channelId = message.channel.id;
if (!conversations.has(channelId)) {
conversations.set(channelId, []);
}
const history = conversations.get(channelId);
// Add user message to history
history.push({ role: 'user', content });
// Keep only last 10 messages for context
if (history.length > 20) {
history.splice(0, history.length - 20);
}
try {
// Show typing indicator
await message.channel.sendTyping();
// Call Claude
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
system: 'You are a helpful assistant in a Discord server. Keep responses concise and friendly.',
messages: history,
});
const reply = response.content[0].text;
// Add assistant response to history
history.push({ role: 'assistant', content: reply });
// Send response (split if too long)
if (reply.length > 2000) {
const chunks = reply.match(/.{1,2000}/g);
for (const chunk of chunks) {
await message.reply(chunk);
}
} else {
await message.reply(reply);
}
} catch (error) {
console.error('Error:', error);
await message.reply('Sorry, I encountered an error. Please try again.');
}
});
client.login(process.env.DISCORD_TOKEN);Run it:
node index.jsMention your bot in Discord and it should respond.
Skip the coding?
OpenClaw includes Discord integration out of the box. Zero code needed.
Coming soonIf you prefer GPT-4, install the OpenAI SDK:
npm install openaiReplace the Anthropic setup:
const OpenAI = require('openai');
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// In the message handler, replace the Claude call:
const response = await openai.chat.completions.create({
model: 'gpt-4o',
max_tokens: 1024,
messages: [
{ role: 'system', content: 'You are a helpful assistant in a Discord server.' },
...history,
],
});
const reply = response.choices[0].message.content;The basic implementation stores all history in memory. For production:
// Better context management with expiry
const conversations = new Map();
const CONTEXT_EXPIRY = 30 * 60 * 1000; // 30 minutes
const MAX_CONTEXT_LENGTH = 20;
function getConversation(channelId) {
const now = Date.now();
if (!conversations.has(channelId)) {
conversations.set(channelId, { messages: [], lastActivity: now });
}
const conv = conversations.get(channelId);
// Reset if stale
if (now - conv.lastActivity > CONTEXT_EXPIRY) {
conv.messages = [];
}
conv.lastActivity = now;
return conv.messages;
}
function addMessage(channelId, role, content) {
const messages = getConversation(channelId);
messages.push({ role, content });
// Trim to max length
while (messages.length > MAX_CONTEXT_LENGTH) {
messages.shift();
}
}
// Clean up old conversations periodically
setInterval(() => {
const now = Date.now();
for (const [id, conv] of conversations) {
if (now - conv.lastActivity > CONTEXT_EXPIRY) {
conversations.delete(id);
}
}
}, 60000);Both Discord and AI APIs have rate limits. Handle them gracefully:
const rateLimit = new Map();
const RATE_LIMIT_WINDOW = 60000; // 1 minute
const MAX_REQUESTS_PER_WINDOW = 10;
function isRateLimited(userId) {
const now = Date.now();
const userLimits = rateLimit.get(userId) || { count: 0, windowStart: now };
// Reset window if expired
if (now - userLimits.windowStart > RATE_LIMIT_WINDOW) {
userLimits.count = 0;
userLimits.windowStart = now;
}
if (userLimits.count >= MAX_REQUESTS_PER_WINDOW) {
return true;
}
userLimits.count++;
rateLimit.set(userId, userLimits);
return false;
}
// In message handler:
if (isRateLimited(message.author.id)) {
await message.reply('You are sending messages too quickly. Please wait a moment.');
return;
}Production bots need robust error handling:
async function callAI(messages, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages,
});
return response.content[0].text;
} catch (error) {
if (error.status === 429) {
// Rate limited, wait and retry
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
continue;
}
if (error.status >= 500) {
// Server error, retry
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}Let us handle the bot
Molted deploys OpenClaw with Discord ready. 24-hour free trial.
Cheapest long-term. Run with PM2 for process management:
npm install -g pm2
pm2 start index.js --name discord-bot
pm2 startup
pm2 saveConnect your GitHub repo, set environment variables, deploy. Pricing based on usage, typically $5-10/month for a bot.
Similar to Railway, good free tier for small bots.
If you have a machine that is always on, run it there. Same PM2 setup as VPS.
Building a Discord bot from scratch teaches valuable skills: API integration, async programming, error handling, deployment. It is worth doing once for the learning experience.
But if you want a working AI bot without the coding and maintenance, pre-built solutions exist. OpenClaw, for example, includes Discord integration that connects in minutes. You configure a bot token, enable the channel, and you have AI responses without writing code.
The tradeoff is customization versus convenience. A custom bot does exactly what you program. OpenClaw does what OpenClaw does, but it does it reliably without you managing servers or debugging at 2 AM.
For teams, the calculation usually favors managed solutions. Developer time spent maintaining a Discord bot is developer time not spent on your actual product. For personal projects and learning, building your own is rewarding.
OpenClaw on Molted includes full Discord integration. No coding, no hosting headaches.
24-hour free trial · no credit card · cancel anytime
Build an AI-powered Telegram bot using grammY framework. Step-by-step tutorial with Claude and GPT integration.
Articles warn about astronomical OpenClaw bills. They're missing the obvious fix: use your existing Claude or ChatGPT subscription instead of pay-as-you-go API.
Run ChatGPT or Claude on WhatsApp with Baileys. Complete self-hosted setup guide with code examples and deployment options.
STILL AWAKE?