Skip to main content
Typing / in Telegram or Discord shows a native menu of every bot command with its description.
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.
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, /sethome, /learnHidden from a user’s menu when the policy denies it
Admins see everything; regular users only see the commands their user_allowed_commands allows.

Platform Support

PlatformNative menuHow
Telegrambot.set_my_commands(BotCommand(...)) at startup
DiscordApplication 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

Quick Start

1

Start a Telegram bot — built-ins appear automatically

Every built-in command shows up in / autocomplete with no extra code.
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, /sethome, /learn.
2

Register a custom command — it joins the menu

Pass a description — it becomes the label users see in the menu.
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.
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.
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.

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.
Any command registered via register_command(..., description=...) appears in the native / menu automatically. Descriptions ARE the menu labels — write them for humans.

Best Practices

The description becomes the native menu label. A command with no description shows a generic placeholder.
Filtered menus keep the UX safe — a user never sees a command they cannot run. See Command Access Control.
Pass channels=["telegram"] when a command only makes sense on one platform — it’s hidden from other platforms’ menus.

Bot Chat Commands

Built-in and custom commands

Command Access Control

admin_users, user_allowed_commands, /whoami

Gateway

Gateway and control-plane overview

Learn a Skill

The privileged /learn command