How to Build a Telegram Bot with a Free LLM API in Python (2025)
Step-by-step tutorial: build a fully working AI-powered Telegram bot using Python and a free LLM API key — no paid subscriptions, deployed in under 30 minutes.
Why Telegram Bots + Free LLM APIs Are a Perfect Pair
Telegram bots are one of the easiest ways to give an AI assistant a real interface that people actually use. Unlike building a full web app, a Telegram bot requires almost no frontend work — Telegram handles the UI entirely. Combined with a free LLM API key from FreeLLMKeys, you can ship a personal AI assistant in under 30 minutes at zero cost.
This guide walks you through everything: setting up the bot on Telegram, wiring it to GPT-4o via FreeLLMKeys, handling conversation history, and deploying it so it runs 24/7.
What You Will Build
- A Telegram bot that responds to messages using GPT-4o
- Per-user conversation memory (the bot remembers what you said)
- A
/resetcommand to clear conversation history - A
/modelcommand to switch between GPT-4o, Claude, and DeepSeek on the fly
Step 1 — Create Your Telegram Bot
- Open Telegram and search for @BotFather
- Send
/newbot - Give it a name and a username (must end in
bot) - BotFather gives you a token like
7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - Save this token — it is your bot's API key
Step 2 — Install Dependencies
pip install python-telegram-bot openai
Step 3 — Write the Bot
import os
from openai import OpenAI
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters, ContextTypes
# ── Config ────────────────────────────────────────────────
TELEGRAM_TOKEN = "YOUR_TELEGRAM_BOT_TOKEN"
LLM_API_KEY = "sk-your-freellmkeys-key"
BASE_URL = "https://aiapiv2.pekpik.com/v1"
DEFAULT_MODEL = "gpt-4o"
client = OpenAI(base_url=BASE_URL, api_key=LLM_API_KEY)
# Per-user conversation history and model selection
user_histories: dict[int, list] = {}
user_models: dict[int, str] = {}
SYSTEM_PROMPT = "You are a helpful AI assistant. Be concise and friendly."
# ── Command handlers ──────────────────────────────────────
async def start(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text(
"👋 Hi! I'm an AI assistant powered by GPT-4o.
"
"Just send me a message to get started.
"
"Commands:
"
"/reset — Clear conversation history
"
"/model gpt-4o|deepseek-chat|claude-opus-4-7 — Switch model"
)
async def reset(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
uid = update.effective_user.id
user_histories[uid] = []
await update.message.reply_text("✅ Conversation cleared.")
async def set_model(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
uid = update.effective_user.id
args = ctx.args
valid = ["gpt-4o", "deepseek-chat", "claude-opus-4-7", "gemini-2.5-flash"]
if not args or args[0] not in valid:
await update.message.reply_text(f"Usage: /model {'|'.join(valid)}")
return
user_models[uid] = args[0]
await update.message.reply_text(f"✅ Switched to {args[0]}")
# ── Message handler ───────────────────────────────────────
async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
uid = update.effective_user.id
text = update.message.text
model = user_models.get(uid, DEFAULT_MODEL)
history = user_histories.setdefault(uid, [])
# Add user message to history
history.append({"role": "user", "content": text})
# Keep last 20 messages to avoid token overflow
if len(history) > 20:
history = history[-20:]
user_histories[uid] = history
# Show typing indicator
await update.message.chat.send_action("typing")
try:
response = client.chat.completions.create(
model=model,
messages=[{"role": "system", "content": SYSTEM_PROMPT}] + history,
max_tokens=1024,
)
reply = response.choices[0].message.content
history.append({"role": "assistant", "content": reply})
await update.message.reply_text(reply)
except Exception as e:
await update.message.reply_text(f"⚠️ Error: {e}")
# ── Main ──────────────────────────────────────────────────
def main():
app = ApplicationBuilder().token(TELEGRAM_TOKEN).build()
app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("reset", reset))
app.add_handler(CommandHandler("model", set_model))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
print("Bot running...")
app.run_polling()
if __name__ == "__main__":
main()
Step 4 — Run It
python bot.py
Open Telegram, find your bot by its username, send a message. You should get an AI response within 2–3 seconds.
Step 5 — Deploy for 24/7 Uptime (Free)
To keep the bot running when your laptop is closed, deploy it for free on Railway or Render:
- Create a
requirements.txt:pip freeze > requirements.txt - Push your code to a GitHub repo
- Connect the repo on railway.app or render.com
- Add environment variables:
TELEGRAM_TOKENandLLM_API_KEY - Deploy — your bot runs 24/7 on their free tier
Adding Image Support
GPT-4o is multimodal. You can add image understanding with a few extra lines:
async def handle_photo(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
photo = update.message.photo[-1] # highest resolution
file = await photo.get_file()
url = file.file_path # Telegram CDN URL
response = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": url}},
{"type": "text", "text": update.message.caption or "What is in this image?"}
]
}]
)
await update.message.reply_text(response.choices[0].message.content)
# Register in main():
app.add_handler(MessageHandler(filters.PHOTO, handle_photo))
Total cost for a fully functional AI Telegram bot with conversation memory, model switching, and image understanding: $0. Grab your FreeLLMKeys key from the homepage and have it running in 30 minutes.