DEV Community

AI Release
AI Release

Posted on Originally published at ai-release.org

Build and deploy an AI Telegram bot in Python, start to finish

A Telegram bot that answers with an LLM is an afternoon of work. The parts that actually stall people are small and specific: where the token comes from, how to call the model from Python without leaking the key, and how to keep the process alive once your laptop closes. Here is the path from an empty folder to a bot that keeps answering while your machine is off.

Everything below works on Windows 10/11, macOS 12+, and Ubuntu 22.04+ with Python 3.10 or newer. You need basic Python and some comfort with cd and pip install — nothing else.

What you need before writing any code

  • A Telegram account, because you'll be talking to @botfather, the official bot that creates other bots.
  • A token from BotFather — a long password-like string that proves your code owns the bot.
  • An API key from an LLM provider. An LLM is just the model that generates the replies. Free tiers exist if you're not ready to pay; the code doesn't change, only the base URL and the model id do.
  • A free GitHub account to hold the code, and an account on any PaaS. PaaS means Platform as a Service: hosting that runs your process so you never touch a server.

Step 1: create the bot and grab the token

Search Telegram for @botfather, press Start, and send /newbot. It asks for a display name (My AI Helper works) and then a username that has to end in bot, something like my_ai_helper_bot.

You'll get back a message containing a line like Use this token to access the HTTP API: 1234567890:AAE... plus a link to your new bot. Store the token somewhere safe immediately. It is the only credential your code needs, and every Telegram API call carries it.

Step 2: folder, virtual environment, secrets

A virtual environment keeps this project's packages separate from everything else on your machine.

mkdir ai-tg-bot && cd ai-tg-bot
python -m venv .venv
source .venv/bin/activate      # Windows: .venv\Scripts\activate
pip install aiogram openai python-dotenv
Enter fullscreen mode Exit fullscreen mode

Your prompt should now start with (.venv) and pip should print Successfully installed aiogram-... openai-... python-dotenv-.... Three packages, three jobs: aiogram receives Telegram updates, openai talks to the model API, and python-dotenv loads secrets from a file.

Next, create a file named exactly .env in the project root:

TELEGRAM_TOKEN=1234567890:AAE...
LLM_API_KEY=sk-...
Enter fullscreen mode Exit fullscreen mode

Add .env to .gitignore before you continue. Keeping secrets out of the source means you can back up or share the repository without handing out your keys.

Step 3: the bot, from code to first reply

Create bot.py. This is the entire thing — polling loop, model call, reply:

import asyncio
import os

from aiogram import Bot, Dispatcher, types
from dotenv import load_dotenv
from openai import AsyncOpenAI

load_dotenv()

bot = Bot(os.getenv("TELEGRAM_TOKEN"))
dp = Dispatcher()
client = AsyncOpenAI(api_key=os.getenv("LLM_API_KEY"))

SYSTEM_PROMPT = "You are a concise assistant. Answer in under 80 words."

@dp.message()
async def handle(message: types.Message):
    response = await client.chat.completions.create(
        model="your-model-name",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": message.text},
        ],
    )
    await message.answer(response.choices[0].message.content)

if __name__ == "__main__":
    asyncio.run(dp.start_polling(bot))
Enter fullscreen mode Exit fullscreen mode

Two details matter here. start_polling is a loop that keeps asking Telegram "anything new?" and passes each update to your handler. And your-model-name has to be the exact model id from your provider's dashboard, not a guess.

The system message is the cheapest way to change behaviour: the model reads it before every reply, so one line can make the bot terse, formal, or bilingual. No fine-tuning needed.

Now run it:

python bot.py
Enter fullscreen mode Exit fullscreen mode

No output and no traceback means it's alive. Open the link BotFather gave you, press Start, send Hello. An answer should arrive within a few seconds. If nothing comes back, inspect the token before you inspect the model — a bad token is the culprit far more often.

Step 4: deploy so it outlives your laptop

Commit and push first:

pip freeze > requirements.txt
git init && git add . && git commit -m "first bot"
git remote add origin https://github.com/<your-name>/ai-tg-bot.git
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

The repository page should show bot.py, requirements.txt, and .gitignore — and no .env. If .env made it in, revoke the keys and start again.

Then create a new service on your PaaS from that repo:

  • Start command: python bot.py
  • Environment variables: TELEGRAM_TOKEN and LLM_API_KEY, same values as in .env
  • Deploy.

The platform installs requirements.txt, injects the variables as real environment variables, and keeps the process alive. Close your laptop, message the bot from your phone, and it should still answer.

Checklist before you call it finished:

  • [ ] Token lives in .env and in the PaaS settings, never in code
  • [ ] .env is listed in .gitignore
  • [ ] requirements.txt is generated and committed
  • [ ] Start command is python bot.py
  • [ ] The bot replies with your laptop switched off

Three errors you'll probably hit

TelegramUnauthorizedError: Unauthorized (401). Telegram rejected the token. Send /mybots to BotFather, pick your bot, open API Token, copy it fresh. Paste it with no quotes and no trailing spaces. If it still fails, confirm that load_dotenv() runs before Bot(...) is constructed — otherwise the variable is None.

Conflict: terminated by other getUpdates request. Two copies are polling the same token, usually your laptop and the cloud. Stop the local one with Ctrl+C, or scale the cloud service down to a single instance. One token, one polling process.

Silence in group chats. Bots have privacy mode on by default, so in groups they only see messages that mention them or reply to them. Send /setprivacy to BotFather, choose the bot, pick Disable, then remove the bot from the group and add it back — the change only applies after a re-add.

Takeaway

The bot above handles one message at a time and forgets everything between requests. That's a perfectly good first version. The next steps are small: keep a per-chat list of recent user and assistant messages and append it to the messages array for memory (keep it short, since every stored message costs tokens), and later let the bot call tools instead of only replying.

Ship the plain version first. The deployment you actually finished beats the agent you're still designing.

This article was originally published on AI Release — https://ai-release.org. More guides and updates land in the channel: https://t.me/ai_release1.

Top comments (0)