Skip to main content
Bot platform adapters now ship in the praisonai-bot package. praisonai bot serve still works exactly as documented here; for a standalone install see praisonai-bot Migration.
Agents can reply with structured interactive messages — buttons, dropdowns, dividers, context text — and each channel adapter renders them as native widgets.
The user taps an inline button or dropdown; each channel renders the same structured presentation natively.

Quick Start

1

Reply with two buttons

2

Dropdown selection

3

One-line approval prompt

How It Works

Block Types

Channel renderers always run adapt_presentation() first. Buttons over the per-channel cap are dropped lowest-priority first, so high-priority actions like Confirm or Deny survive on Discord and Slack.

Channel Adaptation

adapt_presentation() runs automatically inside every renderer — you can also call it yourself to preview what a channel will receive.
The input presentation is never mutated — adapt_presentation() always returns a new MessagePresentation.

Channel Limits

max_buttons is per-row capacity; total button cap is max_buttons × max_button_rows.
Telegram has no native select menu (supports_select=False). Any select block is automatically converted to a column of callback buttons by adapt_presentation().
WhatsApp uses split caps: ≤3 non-URL tappable buttons render as native reply buttons (title cap 20). More than 3 buttons — or any select block — promotes to a native list message (row title cap 24, up to 10 rows). URL buttons are never tappable widgets; their links are inlined into the message body as Label: URL lines.

Renderer Registry

Every channel plugs into a platform-keyed registry so adapters resolve a renderer uniformly and unknown channels degrade to readable text. render_for(platform, presentation) resolves the registered renderer and returns its native payload; channels with no renderer fall back to fallback_text(presentation).
Each renderer implements the PresentationRenderer Protocol — two static methods, get_limits() and render(). Register a new channel by adding a class with these methods to _RENDERERS. fallback_text(presentation) flattens a presentation for channels without a registered renderer: text/context/divider blocks become lines, buttons and select options become • Label bullets, and URL buttons inline as • Label: URL so nothing is silently dropped.
See Presentation Renderers for the full registry API, the built-in renderer table, and an “add a channel” recipe.

Native rendering per channel

Call a renderer directly to preview the exact native payload a channel receives.

Capability Degradation

When a channel lacks a capability, adapt_presentation() gracefully degrades to the next best option. select → buttons on Telegram:
web_app → URL button on Slack/Discord:
For long action_id/value combinations, callback payloads are kept under 64 bytes using a SHA1 hash (16-hex truncation) so distinct options remain distinct after truncation.

Approval Prompts

On channels implementing SupportsPresentation, approval prompts render as inline Allow Once, Allow Always, and Deny buttons wired to /approve <approval_id> ... commands — replacing fragile yes/no text classification. Text-keyword backends (TelegramApproval, SlackApproval, DiscordApproval) remain valid fallbacks for channels without presentation support. When the underlying bot uses MessagePresentation.approval(...), the button namespace is automatically actor-bound — see Interactive Callback Authorization.

Best Practices

PresentationBlock.make_text() and make_buttons() are the agent-friendly path — fewer field mistakes than raw dataclass construction.
When a channel forces truncation, adapt_presentation() drops the lowest-priority buttons first. Give Confirm / Deny / Cancel high priority so they always reach the user.
Give Deny or Cancel higher priority so they survive truncation on Discord’s stricter component limits.
Always set MessagePresentation text content so channels without a registered renderer (e.g. Email) still deliver a readable message. WhatsApp now renders interactive presentations natively.
The built-in helper wires standard Allow/Deny buttons consistently across Telegram, Slack, and Discord.

Approval Protocol

Tool approval backends

Bot Gateway

Multi-channel gateway server

Bot Platform Capabilities

PresentationLimits governs interactive widgets; PlatformCapabilities governs message length, chunking, and editing.