Welcome to the SuperDapp Agents SDK! This guide will help you get started with building AI agents for the SuperDapp platform.
You can use a positional argument for the project directory:
superdapp create my-awesome-agentsuperdapp configureOr manually create a .env file:
API_TOKEN=your_superdapp_api_token_here
API_BASE_URL=https://api.superdapp.aisuperdapp runBefore diving into callback queries, let's explore how to send simple messages to users. The SuperDapp Agents SDK provides several methods for sending different types of messages.
The most common way to send messages is using sendConnectionMessage:
// Send a simple text message
await agent.sendConnectionMessage(roomId, 'Hello! How can I help you today?');
// Send a message with markdown formatting
await agent.sendConnectionMessage(
roomId,
'**Welcome!** Here are your options:\n\n• Option 1\n• Option 2\n• Option 3'
);To respond to user messages, use the message command:
// Handle text messages from users
agent.addCommand('message', async ({ message, roomId }) => {
const userMessage = message.text?.toLowerCase();
if (userMessage?.includes('hello') || userMessage?.includes('hi')) {
await agent.sendConnectionMessage(
roomId,
'Hello! Welcome to our service. How can I assist you today?'
);
} else if (userMessage?.includes('help')) {
await agent.sendConnectionMessage(
roomId,
'Available commands:\n• /news - Get latest news\n• /price - Get crypto prices\n• /help - Show this help'
);
} else if (userMessage?.includes('news')) {
const news = await getLatestNews();
await agent.sendConnectionMessage(roomId, `📰 **Latest News**\n\n${news}`);
} else {
await agent.sendConnectionMessage(
roomId,
'I didn\'t understand that. Type "help" for available commands.'
);
}
});You can add delays between messages for better user experience:
// Send multiple messages with delays
await agent.sendConnectionMessage(roomId, 'Processing your request...');
// Simulate processing time
await new Promise((resolve) => setTimeout(resolve, 2000));
await agent.sendConnectionMessage(roomId, 'Here are your results:');
await agent.sendConnectionMessage(roomId, '✅ Task completed successfully!');Always handle errors gracefully when sending messages:
try {
await agent.sendConnectionMessage(roomId, 'Processing...');
const result = await someAsyncOperation();
await agent.sendConnectionMessage(roomId, `Result: ${result}`);
} catch (error) {
console.error('Error:', error);
await agent.sendConnectionMessage(
roomId,
'❌ Sorry, something went wrong. Please try again later.'
);
}When creating interactive buttons and handling callback queries, use the colon (:) separator in your callback_data when you need to map multiple commands with different values. This enables proper parsing and command routing.
// Define buttons with proper COMMAND:VALUE format
const buttons = [
{ text: '💰 BTC Price', callback_data: 'PRICE:BTC' },
{ text: '📰 Latest News', callback_data: 'GET_NEWS:' },
{ text: '📂 Topics', callback_data: 'GET_TOPICS:' },
{ text: '🔔 Subscribe', callback_data: 'SUBSCRIBE:' },
];
// Handle callback queries using message.callback_command
agent.addCommand('callback_query', async ({ message, roomId }) => {
console.log('Callback query received:', message);
// The callback_data is automatically parsed into:
// - message.callback_command: The command part (before the colon)
// - message.data: The value part (after the colon)
switch (message.callback_command) {
case 'PRICE':
const symbol = message.data || '';
const price = await getPrice(symbol);
await agent.sendConnectionMessage(
roomId,
`💰 **${symbol} Price:** ${price}`
);
break;
case 'GET_NEWS':
const news = await getLatestNews();
await agent.sendConnectionMessage(
roomId,
`📰 **Latest News**\n\n${news}`
);
break;
case 'GET_TOPICS':
const topics = await getAvailableTopics();
await agent.sendConnectionMessage(
roomId,
`📂 **Available topics:** ${topics.join(', ')}`
);
break;
default:
await agent.sendConnectionMessage(
roomId,
'❌ **Unknown option selected.**'
);
}
});// DON'T do this - no colon separator
const buttons = [
{ text: '💰 BTC Price', callback_data: 'PRICE_BTC' }, // ❌ Wrong
{ text: '📰 Latest News', callback_data: 'GET_NEWS' }, // ❌ Wrong
];
// DON'T use callbackData?.startsWith() - deprecated
agent.addCommand('callback_query', async ({ message, roomId }) => {
const callbackData = message.data;
if (callbackData?.startsWith('PRICE_')) {
// ❌ Deprecated
// ...
}
});- Multiple Commands with Values: When you have the same command type but different values (e.g.,
PRICE:BTC,PRICE:ETH) - Dynamic Content: When generating buttons from arrays or lists
- Command Parameters: When you need to pass data to your command handlers
- Automatic Parsing: The SDK automatically parses
COMMAND:VALUEformat intomessage.callback_commandandmessage.data - Cleaner Code: No need for string manipulation with
startsWith()orreplace()
// Multiple price buttons for different cryptocurrencies
callback_data: 'PRICE:BTC';
callback_data: 'PRICE:ETH';
callback_data: 'PRICE:ADA';
// Multiple topic buttons
callback_data: 'TOPIC:CRYPTO';
callback_data: 'TOPIC:BLOCKCHAIN';
callback_data: 'TOPIC:DEFI';
// Channel management
callback_data: 'JOIN_CHANNEL:my-channel';
callback_data: 'LEAVE_CHANNEL:12345';const topics = ['crypto', 'blockchain', 'defi'];
const options = topics.map((topic) => ({
text: topic,
callback_data: `TOPIC:${topic.toUpperCase()}`,
}));// Simple unique commands - no colon needed
callback_data: 'GET_NEWS';
callback_data: 'GET_TOPICS';
callback_data: 'SUBSCRIBE';
callback_data: 'CONFIRM_TOPICS';- Check out the CLI Documentation for detailed command usage
- Explore API Reference for more complex scenarios and complete documentation
- Learn about Deployment options
- Review the API Reference for complete SDK documentation