Skip to main content
Bots can wire button clicks and select-menu choices to your own async handlers — across Telegram, Discord, and Slack — through a small registry API.
The user taps a button or menu in chat; your registered handler runs and the bot replies.

Quick Start

1

Use a built-in slash-command button (zero config)

Buttons wired to slash commands fire automatically — no handler registration needed.
When the user taps Get Help, the existing /help handler fires automatically via the built-in command namespace.
2

Register a custom namespace handler

For your own button logic, create a registry and register an async handler.
encode_action("approval", ...) produces "approval:yes" / "approval:no". When a user taps the button, registry.dispatch() routes the click to on_approval.

How It Works


Decoding Rules

decode_callback(data) maps raw callback_data to a (namespace, payload) tuple: After dispatch(), the registry also writes decoded_namespace and decoded_payload into ctx.platform_data before calling your handler.

Choosing a Namespace Style


Durable callback payload store

When a reply / select value overflows the channel’s inline-callback byte-cap (Telegram’s 64 UTF-8 bytes), the framework persists it under a short reference so the exact value round-trips back to your handler. TelegramBot wires this for you — it shares one store between its renderer and the inbound registry. To do it yourself, pass a store to create_registry:
Without a store, overflowing values fall back to the lossy reply:#<sha1[:16]> hash and the handler is skipped. See Interactive Callback Payload Store for the full flow, configuration, and custom backends.

Platform-Specific Context

Each adapter populates ctx.platform_data with native objects so you can access full platform functionality inside your handler.
Access example:
Access example:
Access example:

Common Patterns

A button that fires an existing slash command — no handler registration needed.
Clicking Check Status triggers the built-in /status command automatically.

API Reference

InteractiveContext

Passed to every handler by the registry’s dispatch() method. After dispatch(), platform_data also contains:
  • decoded_namespace — the decoded namespace string
  • decoded_payload — the decoded payload dict

InteractiveHandler

Return a non-None string to mark the click as handled (stops the chain). Return None to fall through to the fallback handler.

InteractiveRegistry

Functions

Built-in Namespaces

Every platform adapter (Telegram, Discord, Slack) registers these automatically:

Best Practices

Each bot adapter should have its own registry to prevent namespace collisions when running multiple bots in the same process.
get_registry(), register_handler(), and unregister_handler() operate on a process-global registry and are deprecated. Multiple adapters sharing one registry can cause namespace conflicts. Always use create_registry() for new code.
Inline-button callbacks are HMAC-signed. The signing key is the persisted gateway secret at ~/.praisonai/gateway/.gateway_secret (mode 0600, auto-created on first use) — no configuration needed on a single-host deploy. Buttons survive gateway restarts by default.Set PRAISONAI_CALLBACK_SECRET to a shared value when running the gateway on multiple hosts so every replica verifies the same signatures:
Returning None lets the fallback handler run. This is useful when one namespace handler is shared across multiple button types and you only want to handle specific values.
Unhandled exceptions inside a handler are logged, but the registry will still try the fallback. Users won’t see a useful error message unless you handle it yourself.

Messaging Bots

Complete bot configuration and platform setup

Unknown-User Pairing

Owner-approval flow for new users using the pair namespace

Callback Payload Store

Round-trip long reply/select values past a channel’s 64-byte cap