Back to Blog
TutorialFebruary 2, 202612 min

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.

telegrambotgrammyclaudeai chatbot

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

  1. Open Telegram and search for @BotFather
  2. Send /newbot
  3. Choose a name (display name) and username (must end in "bot")
  4. 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 dotenv

Create .env:

BOT_TOKEN=your-telegram-bot-token
ANTHROPIC_API_KEY=your-anthropic-key

Basic 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.js

Open 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 trial

Handle 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 → Disable

With 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.

Try free for 24 hours

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:

  1. Create bot with BotFather, get token
  2. In OpenClaw config, paste the token
  3. Enable Telegram channel
  4. Done

You get group support, inline keyboards, image handling, and conversation persistence without writing code.

Related guides

Free 24-hour trial

Telegram AI bot in 2 minutes

OpenClaw on Molted. Paste your bot token, start chatting. 24-hour free trial.

Start free trial

24-hour free trial · No credit card required · Cancel anytime

Ready to try OpenClaw?

Deploy your AI personal assistant in 60 seconds. No coding required.

Start free trial

24-hour free trial · No credit card required