Model or dataset
bostrot/telegram-support-bot avatar
bostrot/telegram-support-bot

Telegram Support Bot: turning a staff group into a ticket queue

A Telegram ticketing/supporting system.

616 stars206 forksTypeScriptGPL-3.0

At a glance

What is it?
Telegram Support Bot is a TypeScript service where every user message becomes a MongoDB backed ticket in a staff group and staff answer by replying. Version 5 adds roles, canned responses, escalation and webhooks, with optional LLM answers and triage on top.
Who is it for?
Adopt Telegram Support Bot when your support traffic already arrives over Telegram or Signal and your staff are willing to work inside a chat group, since that is the model the whole design assumes. Skip it if you need a multi-channel helpdesk with email intake or a regulated audit trail, and note the LLM answers only from the knowledge base you supply.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Every message becomes a ticket, staff answer by replying

The core loop of Telegram Support Bot is short enough to state in one sentence: users write to the bot, every message becomes a ticket in your staff group, and staff answer by simply replying. The README spells out the mechanics of that loop. When a user sends a message to the support bot, it creates a ticket which is forwarded to the staff group, and any admin in the staff group can answer that ticket by replying to it, with a salutation added automatically. Photos and files are forwarded too, so the group thread mirrors the conversation rather than degrading to text only. The appeal is obvious for small teams, since no new agent interface has to be learned, and the cost is that the ticketing state lives in a chat app that does not natively model ticket state. That tension explains most of the feature list, which reads as a series of ways of imposing support workflow on top of a chat group.

MongoDB holds the ticket state, not the group

The durable state sits in MongoDB, and the compose stack makes that explicit with a MONGO_URI pointing at the mongodb service and a support database. The README lists MongoDB backed open and closed tickets, reopen, ban and unban, and anti-spam as part of the ticketing feature set. Other features depend on that store as well. Tickets can be routed by categories and sub-categories to different staff groups, there is a private one to one reply tunnel, and tickets and replies can be anonymous. The bot can run inside a single forum topic of the staff group through the staffchat_thread_id setting, or open a new ticket per message when ticket_per_message is enabled, which is the switch between a shared queue view and one thread per case. A user can close their own ticket when allow_user_close is set, and a configurable confirmation message can show ticket ids to users. The application code is TypeScript, with mongoose among the dependencies and a test suite run through jest using the detectOpenHandles and forceExit options.

Version 5 turns the group into a working queue with roles and escalation

The v5 feature block is where this project stops being a forwarding bridge and starts being a helpdesk. Staff can assign tickets, set priorities from low through urgent, apply tags, and mute or unmute someone, and there are staff roles named admin, supervisor and agent with a /staff overview listing the configured staff and their roles. Internal notes never reach the user and can be written with /note or by starting a reply with !note or !internal. Canned responses are defined once by key and sent with /key as a reply, so a repeated answer costs one short command. /ticket shows a ticket's details and last messages, /open marks tickets that were already answered, and /broadcast can message every user when allow_broadcast is enabled, with replies mirrored to the parent category group through forward_replies_to_parent. Escalation rules cover unanswered tickets, stale tickets can be auto-closed, and business hours produce an offline message. Read that list as the price of not having a dedicated support UI: every capability a helpdesk would give you natively is here a command in a chat.

The LLM answers only from the knowledge base you write

The optional AI layer is configured entirely through the config.yaml file. The bot can connect to OpenAI or any OpenAI-compatible API, with LiteLLM, Ollama and vLLM given as examples, and it answers users automatically from a knowledge base you provide. The configuration block looks like this.

yaml
use_llm: true # Will enable show_auto_replied when set to true
llm_api_key: 'API_KEY'
llm_base_url: 'https://api.openai.com/v1'
llm_model: 'gpt-4o-mini'
llm_knowledge: >
    Q: What is Botspace?
    A: Botspace is a cloud-based project management tool designed for teams to collaborate, track tasks, and manage workflows efficiently.

    Q: What platforms are supported?
    A: Web, iOS, and Android.

# optional
llm_memory_depth: 10          # previous messages of the ticket sent as context (0 = off)
auto_triage: false            # classify new tickets (category, priority, summary, sentiment)
sentiment_alert_threshold: 2  # alert staff when sentiment score <= this (1-5)
translate_enabled: false      # translate staff replies to translate_target_language

The design choice worth noticing is the constraint at the bottom of that block. The README states that llm_knowledge must not be empty, because the model is instructed to answer only from it and otherwise stay silent, and the bot warns about this at startup. So the automatic answer is a lookup with a language model in front of it, not a general chatbot, and a question outside the knowledge base is forwarded to staff as a normal ticket rather than answered with a guess. Triage, sentiment alerts and translation of staff replies are separate switches, and conversation memory is bounded by llm_memory_depth. The knowledge base is plain question and answer pairs in a YAML string, which makes it easy to review and easy to keep thin on purpose.

Docker compose is the supported path, and only one port is public

Installation goes through a sample configuration file and the compose stack.

bash
cp config/config-sample.yaml config/config.yaml   # set bot_token, staffchat_id, owner_id
docker compose up -d

The stack starts four services. The supportbot service builds from the local Dockerfile and mounts ./config at /bot/config. The mongodb service runs the mongo:8.0 image. The signal-cli service runs bbernhard/signal-cli-rest-api in json-rpc mode, which is how staff groups on Signal are supported. An optional mongo-express service gives a web view of the database. The networking detail is the part to notice: only the bot's web port 8080 is published, and the other services bind to 127.0.0.1, including MongoDB on 127.0.0.1:27017 and signal-cli on 127.0.0.1:40153, while mongo-express sits on 127.0.0.1:8081 with a basic auth username and password pair from the compose file. That is a sensible default for a single-host install, though the mongo-express credentials in the compose file are placeholders you should change before exposing anything. If you do not want Docker, Node.js 24 or newer and a MongoDB instance are required, and the run path is the standard npm sequence.

bash
npm ci
npm run build
npm run prod

Signal support and the web widget widen the intake side

Support groups can sit on Telegram or Signal, and there is an embeddable web chat widget, so the same staff queue can receive traffic from three surfaces. The Signal path depends on the signal-cli service in the compose file, which runs in json-rpc mode with an AUTO_RECEIVE_SCHEDULE parameter that is present but commented out and enabled on demand, which matters if you want unattended message receipt rather than manual polling. Beyond the chat platforms, the project publishes outbound webhooks with an HMAC signature for ticket.created, ticket.replied, ticket.closed, ticket.banned, csat.rated and ticket.escalated, which is the seam where you would connect a CRM, a status page or your own reporting. Analytics come as a /stats command and a daily summary posted to the staff chat, with a CSAT rating survey sent when a ticket closes. There are also experimental Slack and Discord addons, and it is worth being precise about that word, experimental, because those are the integrations to treat as provisional.

The Node.js 24 requirement and the Dockerfile do not match

There is a real inconsistency worth catching before deployment. The package.json declares the engines field as node greater than or equal to 24.0.0, the README states that without Docker, Node.js 24 or newer is required, and the upgrade notes for v5.0.0 say that Node.js 24 or newer is required. The Dockerfile, however, uses node:22-alpine as the base image for both the builder stage and the production stage, installs dependencies with npm ci, runs npm run build, and finally starts the process with node./build/index.js. So the container image pins an older Node.js line than the manifest and the documentation require. Whether the code path actually breaks on 22 is something the repository does not settle, but the mismatch is a fact you can see, and if you run the compose stack you are running Node 22. The rest of the packaging is conventional and healthy: an ESLint configuration, a sonar-project.properties file, a SECURITY.md, a Dockerfile.signal alongside the main Dockerfile, a.github directory, and a published v5.0.0 release on 2026-09-05 preceded by 5.0.0-rc.4 on 2025-08-21 and rc.3 on 2025-08-19, with the last push on 2026-10-20. The project is licensed GPL-3.0, which obliges you to distribute modifications under the same terms if you ship a derivative, and it also offers a hosted version at botspace.bostrot.com, which is the faster route if you do not want to run MongoDB and a container yourself.

Editorial conclusion

Adopt Telegram Support Bot when your support traffic already arrives over Telegram or Signal and your staff are willing to work inside a chat group, since that is the model the whole design assumes. Skip it if you need a multi-channel helpdesk with email intake or a regulated audit trail, and note the LLM answers only from the knowledge base you supply. Verify first that Node.js 24 or newer is what you run, because the Dockerfile still builds on node:22-alpine, and that the staff group id, bot token and owner id in config.yaml match your setup.

Frequently asked questions

How do I install Telegram Support Bot with Docker?

Copy config/config-sample.yaml to config/config.yaml and set bot_token, staffchat_id and owner_id, then run docker compose up -d. The stack starts the bot, MongoDB 8, signal-cli and an optional mongo-express, and only the bot's web port 8080 is published.

Which Node.js version does Telegram Support Bot need?

Node.js 24 or newer, as stated in the README and declared in the engines field of package.json. The Dockerfile still builds on node:22-alpine, so a container run uses the older line.

How does the LLM feature decide what to answer?

The model is instructed to answer only from the llm_knowledge block in the configuration and to stay silent otherwise, and the bot warns at startup if that knowledge base is empty. Questions it cannot answer from the knowledge base are forwarded to staff as ordinary tickets.

Official sources

  1. bostrot/telegram-support-bot on GitHub
  2. License: GPL-3.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bostrot-telegram-support-bot.svg)](https://hysenlabs.com/projects/bostrot-telegram-support-bot)

Was this useful?