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
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.
What we are building
A Discord bot that:
- Responds when mentioned or in DMs
- Maintains conversation context within threads
- Uses Claude or GPT-4 for responses
- Handles rate limits gracefully
- Can be deployed anywhere Node.js runs
The complete code is around 200 lines. Not a weekend project, but a solid afternoon.
Prerequisites
- Node.js 18+ installed on your machine
- A Discord account and a server where you have admin rights
- An Anthropic or OpenAI API key (or your existing subscription—more on this below)
- Basic JavaScript/TypeScript knowledge
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.
Creating a Discord application
Go to the Discord Developer Portal and click "New Application". Name it whatever you want.
Get your bot token
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.
Set permissions
Under Bot → Privileged Gateway Intents, enable:
- Message Content Intent (required to read message text)
- Server Members Intent (optional, for member-related features)
Generate invite link
Go to OAuth2 → URL Generator. Select:
- Scopes:
bot,applications.commands - Bot Permissions:
Send Messages,Read Message History,View Channels
Copy the generated URL and open it in your browser to add the bot to your server.
Project setup
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/Basic bot structure
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.
Start free trialUsing OpenAI instead
If 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;Conversation context management
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);Rate limiting
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;
}Error handling
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.
Deployment options
VPS (DigitalOcean, Hetzner)
Cheapest long-term. Run with PM2 for process management:
npm install -g pm2
pm2 start index.js --name discord-bot
pm2 startup
pm2 saveRailway
Connect your GitHub repo, set environment variables, deploy. Pricing based on usage, typically $5-10/month for a bot.
Fly.io
Similar to Railway, good free tier for small bots.
Home server
If you have a machine that is always on, run it there. Same PM2 setup as VPS.
The simpler path
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.
Related guides
- 50 AI Tools Directory - Discover more AI tools for automation and productivity
- Puppeteer + AI Browser Automation - Combine AI with browser automation for smarter bots
- Claude vs ChatGPT 2026 - Which LLM is better for your Discord bot?
Discord AI bot in 60 seconds
OpenClaw on Molted includes full Discord integration. No coding, no hosting headaches.
24-hour free trial · No credit card required · Cancel anytime