MyClassBot is a Telegram bot that sends each incoming message to a local Ollama model and replies in the Telegram chat. Trigger.dev runs the reply task, while a small local HTTP server receives Telegram webhooks.
It can run on macOS, Windows, or Linux. The services below must run on the same device when using a local Ollama model.
Telegram -> public HTTPS tunnel -> local webhook server -> Trigger.dev task -> local Ollama -> Telegram reply
Telegram cannot call localhost directly, so the webhook server must be exposed through a public HTTPS tunnel.
Install the following on the device that will run the bot:
- Node.js 20 or later (the current LTS release is recommended)
- Ollama
- A public HTTPS tunnel, such as ngrok
- A Telegram account and bot token from @BotFather
- A Trigger.dev account and project API key
The default qwen2.5:7b model is large. If the device does not have enough memory/storage, install a smaller Ollama model and set OLLAMA_MODEL to its exact name instead.
Open Terminal (macOS/Linux) or PowerShell (Windows), then run:
git clone <your-repository-url>
cd MyClassBot
npm installIf you copied the project instead of cloning it, open a terminal in the project folder and run only:
npm installInstall Ollama for your operating system from ollama.com, then download the model:
ollama pull qwen2.5:7bVerify it is installed:
ollama listOllama normally starts automatically after installation. If it is not running, start it with:
ollama serveLeave that terminal open if your operating system does not run Ollama as a background service.
- Open @BotFather in Telegram.
- Run
/newbotand complete the prompts. - Copy the bot token BotFather provides. Treat it like a password.
- Create a project in the Trigger.dev dashboard.
- Create a development API key for that project.
- Copy the key; it normally begins with
tr_dev_.
The project ID in trigger.config.ts must belong to the same Trigger.dev project as TRIGGER_SECRET_KEY. Update it if you use a different project.
Create a local environment file from the template:
macOS/Linux:
cp .env.example .envWindows PowerShell:
Copy-Item .env.example .envOpen .env and provide values for the following settings:
TELEGRAM_TOKEN=your-token-from-botfather
TELEGRAM_WEBHOOK_SECRET=a-long-random-secret
TELEGRAM_WEBHOOK_URL=https://your-public-tunnel-url/telegram/webhook
TRIGGER_SECRET_KEY=your-trigger-development-key
OLLAMA_URL=http://127.0.0.1:11434/api/generate
OLLAMA_MODEL=qwen2.5:7b
CONVERSATION_LOG_PATH=conversations/telegram-conversations.jsonl
CONVERSATION_TRANSCRIPT_PATH=conversations/telegram-conversations.txt
PORT=3000Generate a strong webhook secret with one of these commands:
macOS/Linux:
openssl rand -hex 32Windows PowerShell:
[guid]::NewGuid().ToString('N') + [guid]::NewGuid().ToString('N')OLLAMA_MODEL must exactly match a model shown by ollama list.
Each generated reply is saved locally in two files, created automatically after the first successful model response:
conversations/telegram-conversations.jsonlcontains structured JSON records for software processing.conversations/telegram-conversations.txtis a readable English transcript withStudentandTeacherlabels.
Set CONVERSATION_LOG_PATH or CONVERSATION_TRANSCRIPT_PATH in .env to store either file elsewhere. Conversation logs contain private chat content and are ignored by Git by default.
Telegram requires a publicly reachable HTTPS URL. With ngrok installed and authenticated, run:
ngrok http 3000ngrok displays an HTTPS forwarding URL such as https://example.ngrok-free.app. Copy it and set this value in .env:
TELEGRAM_WEBHOOK_URL=https://example.ngrok-free.app/telegram/webhookKeep ngrok running. Free tunnel URLs usually change when ngrok restarts, in which case update .env and register the webhook again.
Open three terminals in the project folder. Keep all three processes running.
Terminal 1 — Trigger.dev worker:
npm run dev:triggerTerminal 2 — local Telegram webhook receiver:
npm run dev:webhookTerminal 3 — ngrok tunnel:
ngrok http 3000After the tunnel is live and TELEGRAM_WEBHOOK_URL is correct, register the webhook once:
npm run register:webhookOpen your Telegram bot chat, press Start, and send a message. The bot should reply after the Trigger.dev task completes.
Download the model with Ollama, then set its exact name in .env and restart the Trigger.dev worker:
ollama pull <model-name>OLLAMA_MODEL=<model-name>For example, the default configuration uses:
OLLAMA_MODEL=qwen2.5:7bThe HTTPS tunnel cannot reach the local webhook server. Confirm all of the following:
npm run dev:webhookis still running and says it is listening on port 3000.- ngrok is still running and forwarding to port 3000.
TELEGRAM_WEBHOOK_URLcontains the current ngrok HTTPS URL followed by/telegram/webhook.- Run
npm run register:webhookagain after changing the tunnel URL.
- Ensure
npm run dev:triggeris running without errors. - Ensure Ollama is running and
ollama listincludes the value ofOLLAMA_MODEL. - Check the Trigger.dev terminal for task errors.
If Trigger.dev fails with an error mentioning .trigger/tmp/store, stop the worker, remove its disposable local cache, and start it again:
macOS/Linux:
rm -rf .trigger
npm run dev:triggerWindows PowerShell:
Remove-Item -Recurse -Force .trigger
npm run dev:triggerTELEGRAM_WEBHOOK_SECRET does not match the secret registered with Telegram. Check .env and run npm run register:webhook again.
Make sure Ollama is running on the same device and that .env contains:
OLLAMA_URL=http://127.0.0.1:11434/api/generate- Never commit
.env, bot tokens, Trigger keys, or webhook secrets. The supplied.gitignoreexcludes.envfiles. - If a token is exposed, revoke/regenerate it immediately in BotFather or Trigger.dev and update
.env. - This project is designed for local development: a Trigger.dev Cloud worker cannot reach
127.0.0.1on your device. To deploy it permanently, host Ollama on a network-accessible server (with authentication) or move the model inference to a hosted provider. - For a reliable always-on bot, run the webhook receiver, Trigger worker, Ollama, and tunnel as managed services on a device/server that remains online.