Build a Telegram bot with AI: a step-by-step guide

Build a Telegram bot with AI: get a token, choose polling or webhooks, store state, add LLM replies, host it on a server and adapt it to Discord.

Solviera Teknoloji 8 min read Türkçe oku

To build a Telegram bot with AI, have a coding agent (Claude Code, Codex or similar) write a bot with python-telegram-bot, put the token in a .env file and run it on your own machine with polling first. From there you add commands, stored state, LLM-powered replies and finally run it 24/7 on a server.

This guide follows Telegram end to end, then shows how to adapt the same bot for Discord. Every step comes with a prompt you can paste into the agent.

What we’re building

The example bot will:

  • Answer /start and /help.
  • Save notes with /note <text> and list them with /notes (stored state).
  • Reply to plain messages with an LLM, with a daily limit per user.
  • Optionally talk only to users you allow.
  • Run continuously on a server with systemd or Docker.

It’s a good first vibe coding project: small, you see the result on your phone straight away, and it’s actually useful.

Picking a stack: Python or TypeScript?

Two good options:

  • Python + python-telegram-bot: mature, well documented and async. The natural choice if your AI, data or automation code is in Python.
  • TypeScript + grammY: modern, typed and lightweight, and comfortable with webhooks on serverless platforms. Go this way if you already live in Node.js.

I’ll use Python here; swap the library name in the prompts and the same steps work for grammY.

Setup:

mkdir telegram-bot && cd telegram-bot
git init
python3 -m venv .venv && source .venv/bin/activate
pip install python-telegram-bot python-dotenv anthropic
printf ".env\n.venv/\n*.db\n" >> .gitignore

I use the Anthropic SDK as the LLM example; with another provider, swap the package, the idea is the same.

Step 1: get a token and put it in .env

Get your token from Telegram’s official bot creation flow: you create a new bot inside Telegram, choose a display name and a unique username ending in “bot”, and you’re given a long token at the end. That token is the bot’s password; anyone who has it can send messages as your bot.

The .env file:

TELEGRAM_TOKEN=your-token
LLM_API_KEY=your-api-key
LLM_MODEL=the-model-you-use
ALLOWED_USER_IDS=123456789
DAILY_LLM_LIMIT=30

Don’t paste the token or API key into the chat with the agent. It doesn’t need the values, only the fact that they come from .env. If the token ever leaks, revoke it in the same official flow and get a new one.

Step 2: the first prompt

Open the agent in the project folder and ask for the simplest bot that works:

Set up a simple Telegram bot with python-telegram-bot (async, ApplicationBuilder).
- Read the token from .env with python-dotenv. Never open or print .env.
- Layout: bot.py (startup and handler registration), handlers.py (commands),
  storage.py (SQLite later), config.py.
- Add /start and /help; /help lists all commands.
- Reply politely to unknown commands.
- Use polling. Use Python logging; never log the token.
- Add an error handler: log the error and send the user a short apology.
When done, tell me how to run it.

Run it:

python bot.py

Find your bot in Telegram and send /start. If it answers, the first loop is done. If not, paste the terminal error to the agent as is; it’s usually an environment variable that wasn’t read.

Step 3: commands and stored state

Most bots need to remember things: user settings, notes, usage counters. Anything kept in memory disappears when the bot restarts. For a small bot SQLite is plenty, with no database server to run.

Add SQLite to storage.py (data/bot.db).
- notes table: id, user_id, text, created_at.
- usage table: user_id, date, llm_count.
- /note <text> saves a note, /notes lists the user's last 10 notes,
  /delete <id> deletes a note only if it belongs to that user.
- All SQL must be parameterized (no string concatenation).
- Write pytest tests for the storage functions and run them.

“Only if it belongs to that user” matters. Agents often skip authorization checks like this, and suddenly anyone who types /delete 5 can delete someone else’s note.

python-telegram-bot also has its own persistence options such as PicklePersistence, which help with conversation state (multi-step forms, for example). For user data I find SQLite more transparent.

Step 4: smart replies with an LLM

Now the part that makes it an AI bot: send plain messages to an LLM and write the answer back.

# llm.py
import os
from anthropic import AsyncAnthropic

client = AsyncAnthropic(api_key=os.getenv("LLM_API_KEY"))

async def reply(history: list[dict]) -> str:
    resp = await client.messages.create(
        model=os.getenv("LLM_MODEL"),
        max_tokens=500,
        system="You are a helpful Telegram assistant who answers briefly.",
        messages=history[-10:],  # only the last 10 messages
    )
    return resp.content[0].text

A prompt for the agent:

Send plain text messages to reply() in llm.py.
- Keep the last 10 messages per user in memory (alternating user/assistant).
- /reset clears the conversation history.
- Enforce DAILY_LLM_LIMIT per user per day (usage table); when it's reached,
  send a clear message.
- If ALLOWED_USER_IDS is not empty, only answer those users.
- Send the "typing..." action while the LLM call runs.
- Split replies longer than Telegram's message length limit.
- On API errors, send the user a short message and log the error.

Why the limits? A public LLM bot that someone discovers and floods with messages will inflate your bill. A daily limit, an allowlist and a short history are the three simplest ways to keep cost under control. The longer the history, the more tokens you send with every request.

Step 5: polling or webhook?

A bot can receive messages from Telegram in two ways:

  • Polling (long polling): the bot keeps asking Telegram “anything new?”. Zero setup: no HTTPS address, domain or open port. Ideal for development and for small to medium bots on a single server.
  • Webhook: Telegram pushes each new update to an HTTPS address you provide. Nothing sits waiting, and on serverless platforms (functions that run per request) it’s the only option. In return you need a valid HTTPS endpoint, and you should verify requests really come from Telegram with a secret path or secret token.

My rule: start with polling and move to a webhook when you actually need one. You can’t use both for the same token at once; polling doesn’t work while a webhook is set.

Step 6: running it 24/7 on a server

When your laptop shuts down, the bot goes quiet. A small Linux VPS is enough, and with polling you don’t even need a domain.

systemd

# /etc/systemd/system/telegram-bot.service
[Unit]
Description=Telegram bot
After=network-online.target

[Service]
User=bot
WorkingDirectory=/home/bot/telegram-bot
EnvironmentFile=/home/bot/telegram-bot/.env
ExecStart=/home/bot/telegram-bot/.venv/bin/python bot.py
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now telegram-bot
journalctl -u telegram-bot -f

Docker

Have the agent write a Dockerfile and docker-compose.yml with restart: unless-stopped, env_file: .env and a volume for data/. Forget the volume and your SQLite database is wiped every time the container is recreated.

Don’t run the same bot with polling in two places (say, your laptop and the server); Telegram rejects that with a conflict error. Use a separate test bot with its own token for development.

Step 7: adapting it to Discord

Discord bots are similar in concept, with a few important differences:

  • Token and application: you create an application in Discord’s developer portal, add a bot to it and take the token from there. You add the bot to your server with an invite link that requests the fewest permissions it needs.
  • Intents: to read message content you must enable the message content intent both in the portal and in code. If your bot can’t see messages, this is almost always why.
  • Connection model: Discord bots keep a persistent WebSocket connection to the gateway, so the bot has to be a long-running process; it won’t work as a serverless function.
  • Commands: slash commands are the modern way, and they have to be registered with Discord.
  • Libraries: discord.py for Python, discord.js for Node.js.

The cleanest approach is to separate the bot’s logic from the platform. A prompt:

Separate the bot logic from the platform:
- core/ holds platform-independent functions: handle_note, list_notes,
  ask_llm. They take user_id and text and return text.
- Rewrite telegram_bot.py so its handlers call core/.
- discord_bot.py: /note, /notes and /ask slash commands with discord.py,
  all calling core/. DISCORD_TOKEN comes from .env.
- Add a platform column in storage so Discord and Telegram user ids don't mix.
- Keep existing tests passing; extend the tests for core.

Both bots now share the same database and LLM logic, and each one only deals with its own platform’s details.

Common mistakes: what the AI tends to get wrong

  • Writing against an old API. python-telegram-bot moved to async in version 20, and agents sometimes mix in old synchronous examples. If you hit errors, have the agent check the installed version (pip show python-telegram-bot) and fix the code against that version’s docs.
  • Hardcoding the token. The agent may want to put the token in bot.py “just to test quickly”. Say no.
  • Missing authorization checks. Admin commands end up open to everyone, or users can reach each other’s data.
  • Blocking code. time.sleep or a synchronous HTTP call inside an async handler freezes the whole bot.
  • Swallowed errors. Without an error handler, the bot silently stops answering.
  • State in memory. Everything resets on restart.
  • Not splitting long messages. When the LLM writes a long answer, Telegram rejects the message.

Security

  • Tokens and API keys live only in .env, and .env is in .gitignore.
  • Never paste keys into a chat, a screenshot or a bug report.
  • Read the commands the agent wants to run before approving them, especially anything that reads .env or sends data out.
  • When you forward user text to an LLM, assume it may try to override your instructions (prompt injection). Don’t give the bot dangerous abilities like running commands or deleting files.
  • Tell your users that you store their data and send it to an LLM provider.
  • Don’t run the bot as root on the server; chmod 600 the env file.

Doing it with AgentVera

This project splits naturally into two parallel jobs: one agent writes the Telegram side, another the Discord side. In AgentVera you can run Claude Code in one worktree and Codex in another, in the same grid. After each turn, automatic code review has a second model look at easy-to-miss spots such as authorization checks. You review the changes in the Git panel before merging and see the agents’ token usage while you build the LLM feature. When it’s time for the server, SSH and SFTP moves the files, and the Docker manager shows the container’s logs locally.

None of it is required; a terminal and git will get this bot finished too. If you’re looking for something for your bot to do, the Telegram alerts in building a crypto trading bot with AI are a good example.

Wrapping up

Building a Telegram bot with AI is one of the most enjoyable ways to start vibe coding. Get the token from the official flow and keep it in .env, have the agent write the simplest bot first, then add commands, SQLite state and LLM replies layer by layer. Start with polling, run it on a server with systemd or Docker, and keep the logic separate from the platform so Discord is an easy step. Read the authorization checks the agent writes and the commands it runs yourself; the agent can handle the rest.

Questions

Do I need to know how to code to build a Telegram bot with AI?

Very little. A coding agent can write the whole bot; your job is to give clear prompts, try the bot from your own account and read the commands the agent runs. Basic terminal use and knowing what a .env file is are enough.

Where do I get a Telegram bot token?

From Telegram’s official bot creation flow: you create a new bot inside Telegram, give it a name and a username, and you are shown a token at the end. Keep that token only in your .env file.

Should a Telegram bot use polling or a webhook?

Polling is simpler for development and small bots because it needs no public HTTPS address. Webhooks are more efficient for busy bots and are required on serverless platforms.

How do I add AI (LLM) replies to a Telegram bot?

The bot sends the incoming message to an LLM API and writes the answer back. Keep the API key in .env, and use a per-user daily limit and a short conversation history to keep costs under control.

Can I move the same bot to Discord?

Most of the logic, yes. If command and message handling live in a module that knows nothing about the platform, the Discord side is just a thin layer written with discord.py or discord.js.

Bring your agents to one desk.

Download AgentVera for free; your installed CLIs are ready to go.

More posts