Skip to main content
Version: Next

AI Context and Hooks

CommandKit's AI system provides powerful context management and built-in tools to enhance your AI-powered commands.

AI Context

The AiContext class provides comprehensive access to the AI execution environment:

Context Properties

import { AiCommand } from '@commandkit/ai';

export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
// AI-generated parameters based on your schema
const params = ctx.ai.params;

// Original Discord message that triggered the AI
const message = ctx.message;

// Discord client instance
const client = ctx.client;

// CommandKit instance
const commandkit = ctx.commandkit;

// Key-value store for temporary data
const store = ctx.store;
};

Using the Store

The context store allows you to persist data during command execution:

export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
// Store data
ctx.store.set('startTime', Date.now());
ctx.store.set('userPreferences', { theme: 'dark', lang: 'en' });

// Retrieve data
const startTime = ctx.store.get('startTime');
const preferences = ctx.store.get('userPreferences');

// Check if data exists
if (ctx.store.has('processedUsers')) {
// Handle already processed users
}

// Delete data
ctx.store.delete('temporaryData');
};

AI Hooks

CommandKit provides several hooks to interact with the AI system:

useAIContext()

Access the current AI context from anywhere in your code:

import { useAIContext } from '@commandkit/ai';

function someUtilityFunction() {
try {
const ctx = useAIContext();
console.log('Current AI parameters:', ctx.ai.params);
return ctx.message.author.id;
} catch (error) {
// Not in an AI context
return null;
}
}

useAI()

Get access to the AI plugin instance:

import { useAI } from '@commandkit/ai';

async function executeAICommand(message: Message) {
const aiPlugin = useAI();
await aiPlugin.executeAI(message);
}

Built-in AI Tools

CommandKit provides several built-in tools that the AI can use to gather information:

Available Tools

  1. getAvailableCommands - Lists all available commands
  2. getChannelById - Fetches channel information by ID
  3. getCurrentClientInfo - Gets information about the bot
  4. getGuildById - Fetches guild information by ID
  5. getUserById - Fetches user information by ID

Example Tool Usage

The AI can automatically use these tools. For example, if a user asks "What commands are available?", the AI will use the getAvailableCommands tool:

// This happens automatically when the AI needs command information
const commands = await getAvailableCommands.execute({}, {});
console.log(commands);
// Output: [
// { name: 'ping', description: 'Check bot latency', category: 'utility', supportsAI: false },
// { name: 'greet', description: 'Greet a user', category: 'social', supportsAI: true },
// // ... more commands
// ]

Creating Custom Tools

You can create custom tools for the AI to use:

src/tools/weather.ts
import { createTool } from '@commandkit/ai';
import { z } from 'zod';

export const getWeather = createTool({
name: 'getWeather',
description: 'Get current weather information for a location',
parameters: z.object({
location: z.string().describe('The city or location to get weather for'),
units: z.enum(['celsius', 'fahrenheit']).default('celsius'),
}),
async execute(ctx, params) {
const { location, units } = params;

// Fetch weather data from an API
const weatherData = await fetchWeatherAPI(location);

return {
location,
temperature: units === 'celsius' ? weatherData.tempC : weatherData.tempF,
condition: weatherData.condition,
humidity: weatherData.humidity,
windSpeed: weatherData.windSpeed,
};
},
});

Tool Parameters

Tools support comprehensive parameter validation:

export const calculateTax = createTool({
name: 'calculateTax',
description: 'Calculate tax amount for a given price and tax rate',
parameters: z.object({
price: z.number().positive().describe('The base price amount'),
taxRate: z
.number()
.min(0)
.max(1)
.describe('Tax rate as decimal (e.g., 0.08 for 8%)'),
currency: z.string().default('USD').describe('Currency code'),
}),
async execute(ctx, params) {
const { price, taxRate, currency } = params;
const taxAmount = price * taxRate;
const total = price + taxAmount;

return {
basePrice: price,
taxRate: taxRate * 100, // Convert to percentage
taxAmount,
total,
currency,
};
},
});

Advanced Context Usage

Accessing Discord Objects

The AI context provides access to all Discord.js objects:

export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
const { message, client } = ctx;

// Access guild information
if (message.inGuild()) {
const guild = message.guild;
const member = message.member;

console.log(`Guild: ${guild.name}`);
console.log(
`Member roles: ${member.roles.cache.map((r) => r.name).join(', ')}`,
);
}

// Access channel information
const channel = message.channel;
if (channel.isTextBased()) {
console.log(`Channel: ${channel.name || 'DM'}`);
}

// Access bot information
const botUser = client.user;
console.log(`Bot: ${botUser.username}#${botUser.discriminator}`);
};

Error Handling in Context

Implement robust error handling in your AI commands:

export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
try {
const { userId } = ctx.ai.params;

// Attempt to fetch user
const user = await ctx.client.users.fetch(userId).catch(() => null);

if (!user) {
await ctx.message.reply('❌ User not found.');
return;
}

// Process the user
await processUser(user);
} catch (error) {
// Log error with context
console.error('AI command error:', {
command: 'example',
userId: ctx.message.author.id,
guildId: ctx.message.guildId,
error: error.message,
});

await ctx.message.reply('❌ An unexpected error occurred.');
}
};

Context Lifecycle

Understanding the AI context lifecycle helps with proper resource management:

export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
// 1. Context is created when AI processes the message
console.log('AI context created');

// 2. Parameters are set based on AI model output
console.log('Parameters:', ctx.ai.params);

// 3. Your command executes
await performAction(ctx.ai.params);

// 4. Context is cleaned up automatically
// Note: Store data is automatically cleared after execution
};

Best Practices

  1. Resource Cleanup: The context store is automatically cleared, but clean up external resources manually
  2. Error Boundaries: Always wrap potentially failing operations in try-catch blocks
  3. Validation: Validate AI-generated parameters even with Zod schemas
  4. Logging: Use the context information for detailed logging
  5. Performance: Avoid storing large objects in the context store
export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
// Good: Validate critical parameters
const { amount } = ctx.ai.params;
if (amount <= 0 || amount > 1000000) {
await ctx.message.reply('❌ Invalid amount specified.');
return;
}

// Good: Log operations with context
console.log(
`Processing payment: ${amount} for user ${ctx.message.author.id}`,
);

// Good: Handle external API failures
try {
const result = await processPayment(amount);
await ctx.message.reply(`✅ Payment processed: ${result.transactionId}`);
} catch (error) {
console.error('Payment failed:', error);
await ctx.message.reply('❌ Payment processing failed. Please try again.');
}
};