Telegram Bot Commands List

Telegram Bot Commands List: A DevOps Guide to Building One

Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.

Every well-designed Telegram bot exposes a clear telegram bot commands list to its users, and that list is more than cosmetic — it’s the primary interface contract between your bot and the people (or systems) that talk to it. This guide walks through how Telegram’s command system actually works, how to design a telegram bot commands list that scales as your bot grows, and how to wire it into a real automation stack running on your own infrastructure.

If you’ve ever opened a Telegram chat with a bot and typed / to see a menu pop up, you’ve already interacted with this system. What looks like a small UI convenience is backed by a specific API method, a set of scoping rules, and a few design decisions that determine whether your bot stays usable once it has thirty commands instead of five.

Why a Telegram Bot Commands List Matters

A bot without a visible command list forces users to guess syntax or dig through documentation. Telegram solves this natively: bots can register a machine-readable telegram bot commands list via the setMyCommands API method, and Telegram’s client renders it as an autocomplete menu the moment a user types / in the chat. This single feature removes an entire category of “how do I use this bot” support questions.

For anyone building a bot that automates real infrastructure work — deployments, monitoring, task queues, log tailing — the command list is also a safety mechanism. A well-scoped, well-documented set of commands limits what a user (or an integration) can accidentally trigger, and it gives you a natural place to enforce access control before a handler ever runs.

How Telegram Renders the Command Menu

When a client opens a chat with your bot, it fetches the registered command list and shows it as a scrollable menu next to the message input. Each entry pairs a command (lowercase, no spaces, up to 32 characters) with a short description (up to 256 characters). Telegram does not execute anything on your server when a user taps an entry — it just inserts the command text into the input field, exactly as if the user typed it themselves. Your bot’s webhook or long-polling loop still has to receive that message and route it like any other incoming update.

Command Naming Constraints

Telegram enforces a few hard rules on command names, and violating them causes setMyCommands to reject the whole batch:

  • Only lowercase Latin letters, digits, and underscores are allowed.
  • Commands must start with a letter.
  • Length is capped at 32 characters.
  • You can register up to 100 commands per scope.
  • Keep names short and verb-first (/deploy, /status, /logs) rather than noun-first (/deployment_status) — shorter commands are easier to type from a phone keyboard and easier to scan in the autocomplete menu.

    Designing a Telegram Bot Commands List for a DevOps Bot

    The structure of your telegram bot commands list should mirror how your team actually thinks about the system it controls, not how your codebase happens to be organized internally. A common, effective pattern for an infrastructure/ops bot separates commands into a few functional groups:

  • Status and visibility/status, /logs, /health, /queue
  • Action commands/deploy, /restart, /rollback
  • Reporting/briefing, /dashboard, /report
  • Task/project management/next_task, /add_task, /complete_task
  • Meta/admin/help, /alerts, /audit
  • Grouping this way also makes it easier to reason about which commands are safe to expose broadly and which should be gated behind an owner-only check inside your handler code.

    Registering Commands Programmatically

    You register a telegram bot commands list by calling setMyCommands with a JSON array of {command, description} pairs. Most bot frameworks (python-telegram-bot, Telegraf, aiogram, node-telegram-bot-api) wrap this in a helper method, but the underlying HTTP call is simple enough to send directly:

    curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/setMyCommands" \
      -H "Content-Type: application/json" \
      -d '{
        "commands": [
          {"command": "status", "description": "Show current system status"},
          {"command": "deploy", "description": "Trigger a deployment"},
          {"command": "logs", "description": "Tail recent service logs"},
          {"command": "queue", "description": "Show pending task queue"},
          {"command": "help", "description": "List all available commands"}
        ]
      }'

    Run this once after any change to your command set — Telegram caches the list client-side, so updates can take a short while to propagate to already-open chats, but new chats pick up the latest list immediately.

    Scoping Commands to Different Chats

    A feature many teams miss when building their first telegram bot commands list is command scopes. Telegram lets you register different command sets for different contexts: all private chats, all group chats, a specific chat, or a specific user within a chat. This matters a lot for DevOps bots that get added to both a personal chat and a shared team group — you probably don’t want /deploy visible (or callable) from a group chat that includes contractors or external stakeholders.

    A typical scoped setup looks like this in pseudocode against the Bot API:

    default_scope:
      commands: [help, status]
    private_chat_scope:
      chat_id: 885407726
      commands: [help, status, deploy, restart, rollback, logs, queue]

    Set the broad, low-privilege list as the default, then use scope: {"type": "chat", "chat_id": <owner_chat_id>} to layer a fuller, higher-privilege telegram bot commands list on top for the one chat that should have it. Telegram falls back to the default scope wherever a more specific scope isn’t defined.

    Routing Commands: From Message to Handler

    Registering a telegram bot commands list only controls what Telegram displays. Actually executing a command still requires your own routing logic on the receiving end — a webhook endpoint or a polling loop that inspects each incoming Message.text, checks whether it starts with /, strips any @botname suffix (Telegram appends this in group chats when multiple bots share a command), and dispatches to the matching handler.

    A minimal routing table pattern, independent of framework, looks like this:

    COMMAND_HANDLERS = {
        "/status": handle_status,
        "/deploy": handle_deploy,
        "/logs": handle_logs,
        "/queue": handle_queue,
    }
    
    def route_message(update):
        text = update.message.text.strip()
        command = text.split()[0].split("@")[0]
        handler = COMMAND_HANDLERS.get(command)
        if handler:
            handler(update)
        else:
            reply_unknown_command(update)

    Layering Natural-Language Intents on Top of Slash Commands

    Slash commands are precise but rigid — a user has to remember exact syntax. Many production bots layer a secondary natural-language intent matcher underneath the slash-command router, so a message like “show me the logs” resolves to the same handler as /logs. The general pattern: check the message against the exact slash-command table first (since it’s unambiguous), and only fall back to keyword/intent matching if no exact command matched. This keeps the telegram bot commands list as the authoritative, discoverable interface while still tolerating loose phrasing from users who forget the exact command.

    Handling Stuck or Long-Running Commands

    Commands that trigger real infrastructure work — a deploy, a rebuild, a full log pull — shouldn’t block your bot’s event loop. The standard approach is to write the command’s intent to a task queue (a directory of JSON files, a Redis list, a database table) with a pending status, and have a separate worker process pick it up, execute it, and report back via a follow-up Telegram message. This also gives you a natural place to detect and recover stuck jobs: if a task has been running past a reasonable timeout, reset it to pending and let the worker retry, rather than leaving the bot silently hung.

    Access Control and Command Safety

    Because a telegram bot commands list is visible to anyone who opens a chat with the bot, treat it as a documented attack surface, not just a UI nicety. A few practices worth enforcing consistently:

  • Verify the sender’s chat_id against an allow-list before executing any command that mutates state (deploys, restarts, task writes) — never trust the presence of a command alone as authorization.
  • Keep destructive commands (/restart, /rollback) separate from read-only ones (/status, /logs) so you can apply stricter checks to the former.
  • Log every executed command with its sender and timestamp, independent of whatever the command itself logs, so you have an audit trail if something runs that shouldn’t have.
  • Rate-limit or debounce repeat invocations of expensive commands to avoid a user (or a buggy script) accidentally hammering a deploy pipeline.
  • If your bot’s automation touches infrastructure covered elsewhere on this site — for example, a Docker Compose stack behind the commands — it’s worth reviewing how to tear down a Compose stack safely and how to debug it with docker compose logs, since /restart or /logs-style bot commands are often just a thin wrapper around exactly those operations.

    Testing Your Command Set Before Shipping

    Before registering a telegram bot commands list in production, test it against Telegram’s Bot API documentation for the exact field constraints, and manually verify in a private test chat that:

  • Every command in the list actually has a matching handler (a registered-but-unhandled command produces a confusing silent failure).
  • Descriptions are accurate and under the character limit — Telegram truncates or rejects oversized ones.
  • Scoped commands appear correctly in the intended chat and don’t leak into chats they shouldn’t.
  • Deploying and Hosting Your Bot

    A Telegram bot built around a solid telegram bot commands list still needs somewhere reliable to run. Long-polling bots need a persistent process; webhook-based bots need a publicly reachable HTTPS endpoint. Running this on a small VPS gives you full control over the process lifecycle, which matters if your command handlers spawn subprocesses or write to a local task queue. Providers like DigitalOcean or Hetzner are common choices for this kind of always-on, low-resource workload.

    If you’re running the bot alongside a broader automation stack — n8n, a task executor, a content pipeline — it’s worth reading up on self-hosting n8n with Docker or comparing n8n against Make for the orchestration layer that often sits next to a command-driven bot like this. Systemd is the simplest way to keep a long-polling bot alive across reboots and crashes — see systemd’s own documentation for unit file basics if you haven’t wired one up before.


    Recommended: Ready to put this into practice? DigitalOcean is a tool we use for exactly this, and we have a real, disclosed affiliate relationship with them.

    FAQ

    How many commands can I register in a telegram bot commands list?
    Telegram allows up to 100 commands per scope. In practice, a usable menu should stay well under that — once a telegram bot commands list grows past 15-20 entries, users struggle to scan it, and it’s usually a sign you should split functionality into subcommands or arguments instead of separate top-level commands.

    Can I use uppercase letters or spaces in command names?
    No. Telegram requires commands to be lowercase Latin letters, digits, and underscores only, starting with a letter. Use underscores (/next_task) instead of spaces or camelCase to separate words.

    Do I need to re-register my telegram bot commands list every time I restart the bot?
    No — setMyCommands persists server-side on Telegram’s infrastructure until you call it again. You only need to re-run it when the command set itself changes, not on every process restart.

    What happens if a user types a command that isn’t in the registered list?
    Telegram still delivers the message to your bot as normal text starting with / — registration only controls the autocomplete menu, not what your bot receives. Your routing logic should handle unrecognized commands gracefully, typically by replying with a short “unknown command, try /help” message rather than failing silently.

    Conclusion

    A telegram bot commands list is a small API surface with outsized impact on usability and safety. Getting it right means treating command registration (setMyCommands, scopes, naming rules) as a distinct concern from command routing and execution, enforcing access control at the routing layer rather than trusting the menu itself, and keeping the list small enough that a user can actually scan it. Combined with a reliable host and a task-queue pattern for long-running actions, a well-designed command list turns a Telegram bot from a novelty into a genuinely useful operational interface.

    Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *