| name | telegram-bot-creator |
| description | Complete Telegram bot creation for AI agents and pipelines. Build end-to-end bots that bridge backend agents/logic to Telegram chat. Supports multiple frameworks (aiogram, python-telegram-bot), LLM integration (Claude/OpenRouter), multi-step workflows, and various deployment options (polling, webhooks). Use when: (1) Creating a new Telegram bot from scratch, (2) Adding Telegram interface to existing backend agents/pipelines, (3) Building conversational AI bots, (4) Designing customer support/routing bots, (5) Implementing multi-step automated workflows, or (6) The agent needs a Telegram bot created. |
Telegram Bot Creator
When to use this skill
- Use when the user request matches this skill's domain and capabilities.
- Use when this workflow or toolchain is explicitly requested.
When not to use this skill
- Do not use when another skill is a better direct match for the task.
- Do not use when the request is outside this skill's scope.
Overview
Build production-ready Telegram bots that bridge backend agents and pipelines to Telegram chat. This skill handles complete bot creation: from scaffolding, to agent integration, to deployment.
Key architectural pattern: Backend agents do the business logic; Telegram bot provides the chat interface and state management.
Quick Start (5 minutes)
1. Choose Your Framework
pip install aiogram python-dotenv
pip install python-telegram-bot python-dotenv
Framework comparison: See frameworks.md for detailed comparison.
2. Get Telegram Bot Token
- Message @BotFather on Telegram
- Create new bot:
/newbot
- Copy token:
123456:ABC-DEF...
3. Scaffold Bot Project
python3 scripts/bot_initializer.py --name my_bot --framework aiogram
This creates:
main.py - Bot entry point with example handlers
.env.example - Config template
requirements.txt - Dependencies
4. Implement Your Agent
Copy scripts/agent_adapter.py to your project, then subclass it:
from agent_adapter import TelegramAgentAdapter
class MyAgent(TelegramAgentAdapter):
async def process_agent_request(self, message: str, user_id: str) -> str:
return f"Agent response: {message}"
5. Run Locally
export TELEGRAM_BOT_TOKEN="your_token_here"
python3 main.py
Find your bot on Telegram and send a message!
Use Cases & Patterns
Pattern 1: Simple Routing Agent
Route messages to different handlers based on content.
When to use: Customer support, FAQ bots, request classification
See: Agent integration guide ā Pattern 1
class SupportRouter(TelegramAgentAdapter):
async def process_agent_request(self, message: str, user_id: str) -> str:
if "refund" in message.lower():
return "š§ Routing to refunds team..."
elif "technical" in message.lower():
return "š§ Routing to support..."
return "ā¹ļø How can I help?"
Pattern 2: LLM-Based Conversational Bot
AI-powered chat that understands natural language.
When to use: Virtual assistants, customer support, Q&A
See: Agent integration guide ā Pattern 2
Easy setup with OpenRouter (free Claude access):
import httpx
class ChatBot(TelegramAgentAdapter):
async def process_agent_request(self, message: str, user_id: str) -> str:
async with httpx.AsyncClient() as client:
response = await client.post(
"https://openrouter.io/api/v1/chat/completions",
headers={"Authorization": f"Bearer {OPENROUTER_KEY}"},
json={
"model": "claude-3-5-sonnet:free",
"messages": [{"role": "user", "content": message}],
"max_tokens": 1024
}
)
data = response.json()
return data['choices'][0]['message']['content']
Pattern 3: Multi-Step Workflow
Guide users through sequential steps (onboarding, forms, processes).
When to use: Onboarding, multi-step forms, guided workflows
See: Agent integration guide ā Pattern 3, also assets/example_bot_comprehensive.py
class OnboardingBot(TelegramAgentAdapter):
async def process_agent_request(self, message: str, user_id: str) -> str:
state = self.get_user_state(user_id)
step = state.get("step", 0)
if step == 0:
self.update_user_state(user_id, "name", message)
self.update_user_state(user_id, "step", 1)
return "Thanks! Now what's your email?"
elif step == 1:
self.update_user_state(user_id, "email", message)
self.update_user_state(user_id, "step", 2)
return "š Onboarding complete!"
Pattern 4: External Agent Integration
Your agent logic lives on a separate service; bot just forwards requests.
When to use: Large agents, existing backends, microservices
See: Agent integration guide ā Pattern 4
class RemoteAgent(TelegramAgentAdapter):
async def process_agent_request(self, message: str, user_id: str) -> str:
async with httpx.AsyncClient() as client:
response = await client.post(
"https://your-api.com/agent/process",
json={"user_id": user_id, "message": message},
timeout=30.0
)
return response.json()["response"]
Pattern 5: Agentskills.io Protocol
Integrate agents following the agentskills.io specification.
See: Agent integration guide ā Pattern 5
Deployment
Development: Polling (Simplest)
export TELEGRAM_BOT_TOKEN="your_token"
python3 main.py
Advantages: No setup, works on localhost, perfect for testing
Limitations: Higher latency, not ideal for high volume
Production: Polling (Scaled)
Run on cloud platform (keep bot running):
- DigitalOcean App Platform
- Google Cloud Run (persistent container)
- Heroku
- AWS ECS
Production: Webhooks (High Scale)
Telegram sends updates directly to your server. Lower latency, more scalable.
Requirements:
- HTTPS endpoint with SSL certificate
- Public domain
Setup: See deployment.md for full webhook guide and Cloud Run/Lambda examples.
Quick webhook with aiogram:
from aiohttp import web
WEBHOOK_URL = "https://yourdomain.com/webhook/telegram"
async def on_startup():
await bot.set_webhook(url=WEBHOOK_URL, secret_token="random-secret")
State Management
Simple: In-Memory (Development)
Built into agent_adapter.py. Uses get_user_state() and update_user_state() methods.
async def handle_message(self, user_id: str, message: str) -> str:
state = self.get_user_state(user_id)
self.update_user_state(user_id, "key", "value")
return response
Limitation: Data lost on restart. Only for development.
Production: Redis
Fast, distributed, recommended for most bots.
docker run -d -p 6379:6379 redis:7-alpine
See: state_management.md for full Redis integration code
Production: PostgreSQL
For structured data, complex queries, compliance.
See: state_management.md for schema and integration
Docker Compose (All-in-One)
docker-compose up
See: assets/docker-compose.yml for configuration
Framework-Specific Features
Aiogram: FSM (Finite State Machine)
For multi-step conversations with explicit state transitions:
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.storage.redis import RedisStorage
class MyStates(StatesGroup):
step1 = State()
step2 = State()
storage = RedisStorage.from_url("redis://localhost")
dp = Dispatcher(storage=storage)
@dp.message(MyStates.step1)
async def handle_step1(message: types.Message, state: FSMContext):
await state.set_state(MyStates.step2)
Aiogram: Middleware
Route messages intelligently before handlers:
@dp.middleware()
async def agent_selector(handler, event, data):
user_id = event.from_user.id
data["agent"] = get_agent_for_user(user_id)
return await handler(event, data)
Python-telegram-bot: Handlers
Simple handler registration:
app.add_handler(CommandHandler("start", start))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, message_handler))
Common Tasks
Task: Add Conversation History to LLM
Keep messages in memory or database for context-aware responses:
state = self.get_user_state(user_id)
messages = state.get("conversation", [])
messages.append({"role": "user", "content": message})
response = await llm_call(messages)
messages.append({"role": "assistant", "content": response})
self.update_user_state(user_id, "conversation", messages)
Task: Handle Long-Running Operations
Async task without blocking user:
@dp.message()
async def handle_long_operation(message: types.Message):
await message.answer("Processing... š")
result = await long_operation()
await message.answer(f"Done! {result}")
Task: Inline Buttons & Callbacks
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
@dp.message()
async def show_options(message: types.Message):
buttons = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Option 1", callback_data="opt1")],
[InlineKeyboardButton(text="Option 2", callback_data="opt2")]
])
await message.answer("Choose:", reply_markup=buttons)
@dp.callback_query()
async def handle_callback(query: types.CallbackQuery):
if query.data == "opt1":
await query.answer("You chose option 1!")
Task: Error Handling & Logging
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@dp.message()
async def safe_handler(message: types.Message):
try:
response = await risky_operation()
await message.answer(response)
except Exception as e:
logger.error(f"Error for user {message.from_user.id}: {e}")
await message.answer("ā ļø Error processing request. Try again later.")
Task: Rate Limiting
Prevent spam:
from collections import defaultdict
from datetime import datetime, timedelta
user_messages = defaultdict(list)
@dp.message()
async def rate_limited_handler(message: types.Message):
user_id = message.from_user.id
now = datetime.now()
user_messages[user_id] = [
ts for ts in user_messages[user_id]
if now - ts < timedelta(minutes=1)
]
if len(user_messages[user_id]) >= 5:
await message.answer("ā±ļø Too many requests. Wait a minute.")
return
user_messages[user_id].append(now)
Reference Material
Framework Setup & Comparison:
ā frameworks.md
Agent Integration Patterns:
ā agent_integration.md
Polling vs Webhooks & Deployment:
ā deployment.md
State Management (Redis, PostgreSQL, etc):
ā state_management.md
Scripts & Templates
Agent Base Class:
scripts/agent_adapter.py - Subclass this to create your agent. Handles state, typing indicators, error wrapping.
Bot Initializer:
scripts/bot_initializer.py - Scaffold new bot project with framework of choice.
Example Bot:
assets/example_bot_comprehensive.py - Full example with support routing, LLM chat, and multi-step onboarding.
Docker:
assets/Dockerfile - Container image for bot
assets/docker-compose.yml - Full stack (bot + Redis + PostgreSQL)
Config:
assets/.env.example - Environment variables template
Quick Reference: Create a New Bot
python3 scripts/bot_initializer.py --name my_bot --framework aiogram
cp scripts/agent_adapter.py my_bot/
export TELEGRAM_BOT_TOKEN="token_from_botfather"
cd my_bot
python3 main.py
Troubleshooting
Bot doesn't respond?
- Check TELEGRAM_BOT_TOKEN is set correctly
- Verify bot is running (no errors in logs)
- Search for bot in Telegram by username from BotFather
Agent returning errors?
- Check agent logic (add print statements, see logs)
- Use agent_adapter error handling:
_error_response()
- Test agent separately before integrating
Slow responses?
- Polling adds latency (polling_timeout). Use webhooks for faster response
- Check agent logic takes too long. Consider async operations
- Redis is much faster than polling each time
State not persisting?
- In-memory state (default) is lost on restart. Use Redis/PostgreSQL
- Docker Compose includes Redis/PostgreSQL setup
Webhook not receiving messages?
- Check HTTPS certificate is valid (not self-signed in production)
- Verify webhook URL is correct and accessible
- See deployment.md for webhook setup details
Next Steps
- Choose framework: aiogram (modern) or python-telegram-bot (simple)
- Scaffold project: Use
bot_initializer.py
- Implement agent: Subclass
TelegramAgentAdapter, implement process_agent_request()
- Add handlers: Message routing, commands, callbacks
- Test locally: Use polling (simplest)
- Scale: Add state management (Redis), then webhooks if needed
- Deploy: Docker + DigitalOcean/AWS/GCP
For specific patterns, agent types, or deployment scenarios, see reference material linked above.