Telegram AI Bot: Complete Setup with grammY
Build an AI-powered Telegram bot using grammY framework. Step-by-step tutorial with Claude and GPT integration.
Molted Team
Molted.cloud
Telegram bots are the easiest to set up among all messaging platforms. No OAuth flows, no app review, no QR codes. You get a token from BotFather, write some code, and you are live. This guide shows how to build an AI-powered Telegram bot using grammY, the modern TypeScript framework.
Why Telegram for AI bots?
- Instant setup - Get a bot token in 30 seconds from BotFather
- No approval process - Unlike WhatsApp Business API
- Rich features - Inline keyboards, file sharing, groups, channels
- Great API - Well-documented, reliable, fast
- Privacy options - Secret chats, self-destructing messages
Create your bot with BotFather
- Open Telegram and search for
@BotFather - Send
/newbot - Choose a name (display name) and username (must end in "bot")
- Copy the token BotFather gives you
That is it. You now have a bot token like 123456789:ABCdefGHIjklMNOpqrsTUVwxyz.
Project setup with grammY
grammY is the most popular Telegram bot framework for TypeScript/JavaScript. It is fast, type-safe, and well-maintained.
mkdir telegram-ai-bot
cd telegram-ai-bot
npm init -y
npm install grammy @anthropic-ai/sdk dotenvCreate .env:
BOT_TOKEN=your-telegram-bot-token
ANTHROPIC_API_KEY=your-anthropic-keyBasic AI bot
require('dotenv').config();
const { Bot } = require('grammy');
const Anthropic = require('@anthropic-ai/sdk');
const bot = new Bot(process.env.BOT_TOKEN);
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
// Store conversations per chat
const conversations = new Map();
bot.command('start', (ctx) => {
ctx.reply('Hello! I am an AI assistant. Send me any message and I will respond.');
});
bot.command('clear', (ctx) => {
conversations.delete(ctx.chat.id);
ctx.reply('Conversation cleared. Starting fresh.');
});
bot.on('message:text', async (ctx) => {
const chatId = ctx.chat.id;
const text = ctx.message.text;
// Skip commands
if (text.startsWith('/')) return;
// Get or create conversation
if (!conversations.has(chatId)) {
conversations.set(chatId, []);
}
const history = conversations.get(chatId);
// Add user message
history.push({ role: 'user', content: text });
// Trim history
if (history.length > 20) {
history.splice(0, history.length - 20);
}
try {
// Show typing
await ctx.api.sendChatAction(chatId, 'typing');
// Call Claude
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
system: 'You are a helpful Telegram bot. Keep responses concise.',
messages: history,
});
const reply = response.content[0].text;
history.push({ role: 'assistant', content: reply });
await ctx.reply(reply);
} catch (error) {
console.error('Error:', error);
await ctx.reply('Sorry, something went wrong. Try again.');
}
});
bot.start();
console.log('Bot is running...');Run it
node index.jsOpen Telegram, find your bot, and start chatting. Every message gets an AI response.
Want groups and advanced features?
OpenClaw handles Telegram groups, inline queries, and more. Zero code.
Start free trialHandle images with vision
const { InputFile } = require('grammy');
bot.on('message:photo', async (ctx) => {
const chatId = ctx.chat.id;
const photo = ctx.message.photo;
// Get highest resolution
const fileId = photo[photo.length - 1].file_id;
const file = await ctx.api.getFile(fileId);
// Download file
const url = `https://api.telegram.org/file/bot${process.env.BOT_TOKEN}/${file.file_path}`;
const response = await fetch(url);
const buffer = await response.arrayBuffer();
const base64 = Buffer.from(buffer).toString('base64');
await ctx.api.sendChatAction(chatId, 'typing');
const aiResponse = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/jpeg',
data: base64,
},
},
{
type: 'text',
text: ctx.message.caption || 'What is in this image?',
},
],
}],
});
await ctx.reply(aiResponse.content[0].text);
});Group chat support
Telegram bots can work in groups. Configure privacy mode with BotFather:
/setprivacy → DisableWith privacy disabled, your bot sees all messages. To only respond when mentioned:
bot.on('message:text', async (ctx) => {
const text = ctx.message.text;
const botUsername = ctx.me.username;
// In groups, only respond if mentioned
if (ctx.chat.type !== 'private') {
if (!text.includes(`@${botUsername}`)) {
return;
}
}
// Remove mention from text
const cleanText = text.replace(`@${botUsername}`, '').trim();
// ... rest of handler
});Inline keyboards for actions
const { InlineKeyboard } = require('grammy');
bot.command('help', async (ctx) => {
const keyboard = new InlineKeyboard()
.text('Clear history', 'clear')
.text('Settings', 'settings')
.row()
.url('Documentation', 'https://molted.cloud/docs');
await ctx.reply('What would you like to do?', {
reply_markup: keyboard,
});
});
bot.callbackQuery('clear', async (ctx) => {
conversations.delete(ctx.chat.id);
await ctx.answerCallbackQuery('Conversation cleared!');
await ctx.reply('Starting fresh. Send me a message.');
});
bot.callbackQuery('settings', async (ctx) => {
await ctx.answerCallbackQuery();
await ctx.reply('Settings: (coming soon)');
});Webhook deployment (production)
For production, use webhooks instead of polling:
const { webhookCallback } = require('grammy');
const express = require('express');
const app = express();
app.use(express.json());
// Set webhook
const WEBHOOK_URL = 'https://your-domain.com/webhook';
bot.api.setWebhook(WEBHOOK_URL);
// Handle webhook
app.post('/webhook', webhookCallback(bot, 'express'));
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});Production-ready Telegram bot
Molted deploys OpenClaw with Telegram configured. Just paste your bot token.
Rate limiting and error handling
const rateLimit = new Map();
bot.use(async (ctx, next) => {
const userId = ctx.from?.id;
if (!userId) return next();
const now = Date.now();
const userLimit = rateLimit.get(userId) || { count: 0, reset: now + 60000 };
if (now > userLimit.reset) {
userLimit.count = 0;
userLimit.reset = now + 60000;
}
if (userLimit.count >= 20) {
await ctx.reply('Too many messages. Please wait a minute.');
return;
}
userLimit.count++;
rateLimit.set(userId, userLimit);
return next();
});
// Global error handler
bot.catch((err) => {
console.error('Bot error:', err);
});Deploy with OpenClaw
OpenClaw supports Telegram out of the box with grammY under the hood. Setup is:
- Create bot with BotFather, get token
- In OpenClaw config, paste the token
- Enable Telegram channel
- Done
You get group support, inline keyboards, image handling, and conversation persistence without writing code.
Related guides
- Discord Bot with AI - Build for Discord servers
- ChatGPT on WhatsApp - WhatsApp integration with Baileys
- Slack AI Chatbot - Enterprise Slack integration
Telegram AI bot in 2 minutes
OpenClaw on Molted. Paste your bot token, start chatting. 24-hour free trial.
24-hour free trial · No credit card required · Cancel anytime