AI Configuration
CommandKit provides comprehensive AI configuration options to customize how your bot processes and responds to messages. You can configure AI models, message filters, system prompts, and processing hooks.
Configuration Overview
The configureAI
function accepts several configuration options:
selectAiModel
(required) - Function to choose which AI model to usemessageFilter
(optional) - Filter which messages trigger AI processingdisableBuiltInTools
(optional) - Disable built-in Discord toolsprepareSystemPrompt
(optional) - Custom system prompt generationpreparePrompt
(optional) - Custom user prompt preparation- Lifecycle hooks - Functions called during AI processing
Creating a Configuration File
Create a dedicated configuration file, typically src/ai.ts
, to set up your AI model and processing options:
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { configureAI } from '@commandkit/ai';
const google = createGoogleGenerativeAI({
apiKey: process.env.GOOGLE_API_KEY,
});
const model = google.languageModel('gemini-2.0-flash');
configureAI({
// Required: Select which AI model to use
selectAiModel: async (ctx, message) => {
return {
model,
maxSteps: 5, // Maximum number of tool calls
temperature: 0.7, // Response creativity (0-1)
maxTokens: 2000, // Maximum response length
};
},
// Optional: Filter which messages trigger AI processing
messageFilter: async (commandkit, message) => {
// Only respond when the bot is mentioned
return (
message.inGuild() && message.mentions.users.has(message.client.user.id)
);
},
// Optional: Customize the system prompt
prepareSystemPrompt: async (ctx, message) => {
return `You are ${message.client.user.username}, a helpful Discord bot.
Current server: ${message.guild?.name || 'DM'}
Keep responses under 2000 characters and be friendly!`;
},
});
Configuration Options
Model Selection (selectAiModel
)
The selectAiModel
function is called for each message and must return model configuration:
selectAiModel: async (ctx, message) => {
// Basic model selection
return {
model: google.languageModel('gemini-2.0-flash'),
};
// Advanced configuration
return {
model: google.languageModel('gemini-2.0-flash'),
maxSteps: 8, // Max tool calls per request
temperature: 0.6, // Response creativity
maxTokens: 1500, // Max response length
abortSignal: AbortSignal.timeout(30000), // 30s timeout
};
};
Message Filtering (messageFilter
)
Control which messages trigger AI processing:
messageFilter: async (commandkit, message) => {
// Only respond to mentions
return message.mentions.users.has(message.client.user.id);
// Advanced filtering
return (
!message.author.bot && // Ignore bots
message.inGuild() && // Only in servers
(message.mentions.users.has(message.client.user.id) || // Mentions
message.content.toLowerCase().includes('hey bot')) // Keywords
);
};
System Prompts (prepareSystemPrompt
)
Customize the AI's behavior and context:
prepareSystemPrompt: async (ctx, message) => {
const serverName = message.guild?.name || 'Direct Message';
const availableCommands = ctx.commandkit.commandHandler
.getCommandsArray()
.filter((cmd) => 'ai' in cmd.data)
.map((cmd) => cmd.data.command.name)
.join(', ');
return `You are ${message.client.user.username}, a helpful Discord bot.
**Context:**
- Server: ${serverName}
- Available AI commands: ${availableCommands}
- Current channel: ${message.channel.name || 'DM'}
**Guidelines:**
- Keep responses under 2000 characters
- Be helpful and friendly
- Use available commands when appropriate
- Ask for clarification if needed`;
};
Lifecycle Hooks
Configure functions that run during AI processing:
configureAI({
// ... other options
// Called when AI processing starts
onProcessingStart: async (ctx, message) => {
await message.channel.sendTyping();
console.log(`AI processing started for ${message.author.username}`);
},
// Called when AI processing finishes
onProcessingFinish: async (ctx, message) => {
console.log('AI processing completed');
},
// Called with the AI response
onResult: async (ctx, message, result) => {
if (result.text) {
await message.reply({
content: result.text.substring(0, 2000),
allowedMentions: { parse: [] },
});
}
},
// Called when an error occurs
onError: async (ctx, message, error) => {
console.error('AI error:', error.message);
await message.reply(
'Sorry, I encountered an error processing your request.',
);
},
});
Built-in Tools
CommandKit provides built-in tools that the AI can use:
getAvailableCommands
- List available bot commandsgetChannelById
- Get channel informationgetCurrentClientInfo
- Get bot informationgetGuildById
- Get server informationgetUserById
- Get user information
Disable built-in tools if needed:
configureAI({
disableBuiltInTools: true, // AI won't have access to built-in tools
// ... other options
});
Now import this configuration in your main application file:
import { Client } from 'discord.js';
import './ai'; // Import AI configuration
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});
export default client;
Multiple AI Providers
You can configure multiple AI providers and choose between them dynamically:
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { createOpenAI } from '@ai-sdk/openai';
import { configureAI } from '@commandkit/ai';
// Configure multiple providers
const google = createGoogleGenerativeAI({ apiKey: process.env.GOOGLE_API_KEY });
const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });
configureAI({
selectAiModel: async (ctx, message) => {
// Use different models for different channels or users
if (message.channelId === 'premium-channel-id') {
return {
model: openai('gpt-4'),
maxSteps: 10,
};
}
// Default to Google Gemini
return {
model: google.languageModel('gemini-2.0-flash'),
maxSteps: 5,
};
},
messageFilter: async (commandkit, message) => {
return message.mentions.users.has(message.client.user.id);
},
});
Environment-Based Configuration
Configure different settings for development and production:
import { configureAI } from '@commandkit/ai';
const isDevelopment = process.env.NODE_ENV === 'development';
configureAI({
selectAiModel: async (ctx, message) => ({
model: google.languageModel(
isDevelopment ? 'gemini-1.5-flash' : 'gemini-2.0-flash',
),
maxSteps: isDevelopment ? 3 : 8,
temperature: isDevelopment ? 0.8 : 0.6,
}),
onError: async (ctx, message, error) => {
if (isDevelopment) {
// Show detailed errors in development
await message.reply(`Debug Error: ${error.message}`);
console.error(error.stack);
} else {
// Generic error in production
await message.reply('An error occurred while processing your request.');
}
},
});