Slash Command Menu

Native `/` autocomplete for Telegram and Discord bots — commands are discoverable by typing

Typing / in Telegram or Discord shows a native menu of every bot command with its description.

python
from praisonaiagents import Agent
from praisonai.bots import TelegramBot

agent = Agent(name="assistant", instructions="Be helpful.")
bot = TelegramBot(token="YOUR_TOKEN", agent=agent)

# Register a custom command — it appears in the native `/` menu automatically
async def handle_ping(message):
    return "Pong!"

bot.register_command("ping", handle_ping, description="Check if bot is alive")

import asyncio
asyncio.run(bot.start())
# Type "/" in your chat — Telegram/Discord shows the full command list.
Diagram

👤 User types /

📋 Platform native menu

📜 Autocomplete list
from CommandRegistry

✅ Tap → dispatch

The shared CommandRegistry is the single source of truth. Adapters project it into each platform’s native menu at startup — no extra code, and every register_command-added command shows up too.

What Appears in the Menu

Both built-in and custom commands surface in the / menu, filtered per user by CommandAccessPolicy.

Built-in commandsCustom commands
/status, /new, /help, /stop, /modelAny command added with register_command(name, handler, description=...)
/usage, /compress, /queue, /undoThe description you pass becomes the menu label
/sessions, /resume, /retry, /reasoningRestrict to platforms with channels=[...]
/whoami, /learnHidden from a user’s menu when the policy denies it
/automations, /blueprint (Telegram)See Automation Suggestions

Admins see everything; regular users only see the commands their user_allowed_commands allows.

Platform Support

PlatformNative menuHow
Telegram✅bot.set_my_commands(BotCommand(...)) at startup
Discord✅Application commands on CommandTree, sync() on on_ready
Slack⚠️Base no-op — commands still work by typing, no native menu yet
WhatsApp⚠️Base no-op — WhatsApp has no / command menu API
Diagram

telegram

discord

slack

whatsapp

Which platform?

✅ Native menu
set_my_commands

✅ Native menu
CommandTree.sync

⚠️ No native menu yet
commands still work by typing

⚠️ No / menu API on WhatsApp

Quick Start

  1. Start a Telegram bot — built-ins appear automatically

    Every built-in command shows up in / autocomplete with no extra code.

    python
    from praisonaiagents import Agent
    from praisonai.bots import TelegramBot
    
    agent = Agent(name="assistant", instructions="Be helpful.")
    bot = TelegramBot(token="YOUR_TOKEN", agent=agent)
    
    import asyncio
    asyncio.run(bot.start())
    # Type "/" — Telegram lists /status, /new, /help, /stop, /model, /usage,
    # /compress, /queue, /undo, /sessions, /resume, /retry, /reasoning,
    # /whoami, /learn.
  2. Register a custom command — it joins the menu

    Pass a description — it becomes the label users see in the menu.

    python
    async def handle_ping(message):
        return "Pong!"
    
    bot.register_command("ping", handle_ping, description="Check if bot is alive")
    # /ping now appears in the native menu alongside the built-ins.
  3. Restrict a command to specific platforms

    Use channels=[...] to keep a command out of other platforms’ menus.

    python
    bot.register_command(
        "tgstats",
        handle_ping,
        description="Telegram-only stats",
        channels=["telegram"],
    )
    # Telegram's menu lists /tgstats; Discord's menu does not.

How It Works

At startup each adapter builds policy-filtered (name, description) pairs from the registry, then publishes them to the platform’s native menu.

Diagram
PlatformPolicyRegistryAdapterPlatformPolicyRegistryAdapterTelegram set_my_commands /Discord CommandTree.syncStartupbuild_command_menu_entries(user_id=None)resolve registry + _command_policy + _command_channelsmenu_entries(platform, policy, user_id, extra_commands)filter by allowed commandsallowed (name, description) tuplesentriespublish_command_menu(entries)menu registered
StepMethodWhere
Build entriesbuild_command_menu_entries(user_id)ChatCommandMixin
Resolve truthregistry.menu_entries(platform, policy, user_id, extra_commands)CommandRegistry
Publishpublish_command_menu(entries)Adapter override

Menu publishing is best-effort: a missing SDK, network error, or unsupported platform is logged and swallowed, so startup is never blocked.

Access-Control Interaction

CommandAccessPolicy filters menu_entries() per user — admins see everything, regular users only see commands in their user_allowed_commands.

Diagram

admin?

regular user

👤 User taps /

Registry.menu_entries(policy, user_id)

✅ Full menu
built-ins + custom

🔒 Filtered by
user_allowed_commands

Command Access Control

admin_users, user_allowed_commands, and /whoami

Custom Commands API

Custom commands use the same register_command() API documented in Bot Chat Commands.

Best Practices

Always pass a description

The description becomes the native menu label. A command with no description shows a generic placeholder.

Restrict privileged commands with CommandAccessPolicy

Filtered menus keep the UX safe — a user never sees a command they cannot run. See Command Access Control.

Use channels for platform-specific commands

Pass channels=["telegram"] when a command only makes sense on one platform — it’s hidden from other platforms’ menus.

Menu publishing is best-effort

A failure at startup never blocks the bot. If the menu is empty on Telegram or Discord, check the startup logs for a swallowed set_my_commands / CommandTree.sync error.

Related