Een Discord AI-bot is een bot die berichten op je server beantwoordt met vloeiende, door AI aangedreven antwoorden. In deze gids bouwen we een volledig werkende bot die binnenkomende berichten opvangt met discord.js, ze naar de Claude API van Anthropic stuurt en het antwoord terugplaatst in het kanaal. Anders dan klassieke, op commando's gebaseerde bots is het doel hier een assistent die in natuurlijke taal converseert en de context onthoudt.
Wat heb je nodig voor een Discord AI-bot?
Bereid voor je begint een paar essentiële zaken voor:
- Node.js 18+ — discord.js v14 en de officiële Anthropic-SDK vereisen een moderne Node-versie.
- Een Discord-applicatie en bot-token — maak een applicatie aan in het
Discord Developer Portal, zet die om in een bot en kopieer de token. - Een Anthropic API-sleutel — verkregen via
console.anthropic.comen opgeslagen in een.env-bestand. - De Message Content Intent — je moet deze geprivilegieerde intent in het Developer Portal inschakelen zodat de bot de berichtinhoud kan lezen.
Zet de token of API-sleutel nooit hard in je broncode; bewaar beide als omgevingsvariabelen. Als de sleutel lekt, komt de misbruikrekening bij jou terecht.
Het project en de afhankelijkheden opzetten
Initialiseer het project in een lege map en installeer de benodigde pakketten:
mkdir discord-ai-bot && cd discord-ai-bot
npm init -y
npm install discord.js @anthropic-ai/sdk dotenv
Voeg "type": "module" toe aan je package.json zodat je de ES-modulesyntaxis (import) kunt gebruiken. Maak vervolgens een .env-bestand in de hoofdmap:
DISCORD_TOKEN=jouw_discord_bot_token
ANTHROPIC_API_KEY=jouw_anthropic_sleutel
De SDK leest de omgevingsvariabele ANTHROPIC_API_KEY automatisch uit, dus je hoeft de sleutel niet handmatig mee te geven bij het aanmaken van de client.
Praten met de Claude API: de basiscode
Het echte werk gebeurt in Claude's Messages API: je kiest een model en levert een messages-array (rol en inhoud) aan, en je krijgt een bericht terug dat uit inhoudsblokken bestaat. De onderstaande index.js vraagt het aan Claude zodra de bot wordt gepingd (mention) en schrijft het antwoord terug:
import 'dotenv/config';
import { Client, GatewayIntentBits, Events } from 'discord.js';
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic(); // sleutel wordt uit de omgeving gelezen
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});
const SYSTEM_PROMPT =
'Je bent een behulpzame Discord-communityassistent. Houd antwoorden kort en duidelijk.';
client.once(Events.ClientReady, (c) => {
console.log(`Ingelogd als ${c.user.tag}`);
});
client.on(Events.MessageCreate, async (message) => {
if (message.author.bot) return;
if (!message.mentions.has(client.user)) return;
const prompt = message.content.replace(/<@!?\d+>/g, '').trim();
if (!prompt) return;
await message.channel.sendTyping();
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: SYSTEM_PROMPT,
messages: [{ role: 'user', content: prompt }],
});
const reply = response.content
.filter((block) => block.type === 'text')
.map((block) => block.text)
.join('');
await message.reply(reply.slice(0, 2000));
});
client.login(process.env.DISCORD_TOKEN);
Een paar details om op te letten: Claude's antwoord zit in response.content als een array van blokken; om de tekst te krijgen, filteren we de blokken van het type text en voegen we ze samen. We knippen het antwoord af omdat de berichtlimiet van Discord 2000 tekens is. Het veld system is de systeemprompt die de persoonlijkheid en taal van de bot bepaalt.
Gespreksgeheugen en contextbeheer
De bot hierboven behandelt elk bericht vanaf nul; hij onthoudt het vorige gesprek niet. Voor een echt gesprek bewaar je de recente berichten per kanaal en stuur je de geschiedenis bij elk verzoek mee terug. De Claude API is stateless: jij draagt de context.
const history = new Map();
// binnen MessageCreate:
const channelId = message.channelId;
const messages = history.get(channelId) ?? [];
messages.push({ role: 'user', content: prompt });
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: SYSTEM_PROMPT,
messages,
});
const reply = response.content
.filter((block) => block.type === 'text')
.map((block) => block.text)
.join('');
messages.push({ role: 'assistant', content: reply });
// Beperk de context tot de laatste 10 berichten (token- en kostenbeheersing)
history.set(channelId, messages.slice(-10));
Een belangrijke regel hier: berichten wisselen af tussen de rollen user en assistant, en het eerste bericht moet altijd user zijn. Als je de geschiedenis onbeperkt laat groeien, stijgen de tokenkosten en vul je het contextvenster; afkappen tot de laatste N berichten is dus een goede gewoonte. Voor langdurige persistentie sla je deze array op in een database (bijvoorbeeld SQLite).
Tips voor kosten, snelheid en veiligheid
- Foutafhandeling: omhul de API-aanroep met een
try/catch; stuur bij een netwerkfout of een rate limit een vriendelijk bericht naar de gebruiker en log de fout. - Cooldown: voeg een eenvoudige wachttijd per gebruiker toe om zowel spam als onnodige API-kosten te blokkeren.
- Modelkeuze: voor grote, snelheidsgevoelige workloads is de Sonnet-familie een evenwichtige keuze; overweeg Opus voor complexere taken en Haiku voor eenvoudige, snelle antwoorden.
- max_tokens: stel een redelijke bovengrens in om antwoorden kort te houden — een lang antwoord is duur en kan de limiet van Discord overschrijden.
- Systeemprompt: definieer de rol, grenzen en toon van de bot duidelijk in het veld
system; dit is de effectiefste manier om het gedrag van het model te sturen.
Voeg deze onderdelen samen en je hebt een solide assistent die in natuurlijke taal praat, de context onthoudt en de kosten onder controle houdt.
Veelgestelde vragen
Mijn bot kan geen berichten lezen — waarom?
Hoogstwaarschijnlijk staat de Message Content Intent uit. Schakel deze geprivilegieerde intent in bij de botinstellingen in het Developer Portal en zorg dat je de intent GatewayIntentBits.MessageContent in je code hebt toegevoegd.
Welk Claude-model moet ik gebruiken?
Voor chatbots biedt een actueel model zoals claude-sonnet-4-6 een goede balans tussen snelheid en kwaliteit. Je kunt naar behoefte overstappen op een krachtiger of sneller model; wijzig gewoon de model-ID in het veld model van het verzoek.
Hoe houd ik mijn API-sleutel veilig?
Bewaar de sleutel in een .env-bestand, voeg het toe aan .gitignore en push het nooit naar je repo. Als de sleutel per ongeluk lekt, trek hem dan onmiddellijk in via de console en maak een nieuwe aan.
Wil je een door AI aangedreven bot voor je Discord-community? Of het nu om een opbouw vanaf nul gaat of om het toevoegen van Claude aan je bestaande bot, laten we het samen plannen. Neem contact met me op en laten we je project tot leven brengen.