MessagePresentation alongside their reply text β Telegram renders it as a native inline keyboard; other platforms fall back to plain text until their renderer is wired.
Quick Start
Quick-Reply Buttons
The simplest way to add buttons β each tapped choice feeds the value back to the agent as the next user message:
How It Works
Theadapt_presentation() function runs a channel-agnostic adaptation pass before rendering: it truncates buttons to platform limits, degrades select menus to button rows when unsupported, and degrades web_app actions to URLs on channels without mini-app support.
Block Types
| Block type | Method | Description |
|---|---|---|
text | PresentationBlock.make_text(content) | Plain or markdown text |
buttons | PresentationBlock.make_buttons(items) | Row of clickable buttons |
quick_replies | PresentationBlock.quick_replies(choices) | Shortcut for reply-action buttons |
select | PresentationBlock.make_select(options) | Dropdown menu (degraded to buttons on Telegram) |
divider | PresentationBlock.make_divider() | Visual separator |
context | PresentationBlock.make_context(content) | Smaller contextual text |
Action Types
| Action | Factory | Description |
|---|---|---|
callback | PresentationAction.callback(value) | Opaque callback data for your handler |
reply | PresentationAction.reply(value) | Feed value back as next agent input |
command | PresentationAction.command("/cmd") | Trigger a slash command |
url | PresentationAction.open_url(url) | Open a URL |
web_app | PresentationAction(type="web_app", web_app_url=url) | Open a mini-app (Telegram only) |
Platform Support & Limits
| Platform | Presentation support | Notes |
|---|---|---|
| Telegram | β Native inline keyboard | Wired in PR #2483 |
| Slack | π Planned | Falls back to plain text |
| Discord | π Planned | Falls back to plain text |
| β Native interactive (reply buttons + list messages) | Delivered via Cloud API interactive payloads (button / list) β see Bot Presentations |
Telegram Limits
| Limit | Value |
|---|---|
max_buttons per row/message | 8 |
max_button_rows | 100 |
max_button_label | 64 characters |
callback_data | 64 UTF-8 bytes |
max_text_length | 4096 characters |
| Native select menu | β (degraded to buttons) |
Web app (web_app_url) | β |
WhatsApp Limits
| Limit | Value |
|---|---|
max_buttons (list rows) | 10 |
| Reply buttons per message | 3 |
max_button_rows | 1 |
max_button_label (list row) | 24 characters |
| Reply-button title | 20 characters |
max_options (list rows) | 10 |
max_option_label | 24 characters |
max_text_length (text / list body) | 4096 characters |
| Reply-button message body | 1024 characters |
Reply / list-row id | 256 characters |
| Native select menu | β (rendered as a list message) |
| Markdown | β |
Web app (web_app_url) | β (degraded via adapt_presentation) |
Button Priorities
When more buttons are defined than the platform limit allows, the adaptation pass keeps the highest-priority buttons and drops the rest:
Best Practices
Use reply actions for simple choices
Use reply actions for simple choices
PresentationAction.reply(value) feeds the chosen value back directly as the userβs next message β your agent sees it as normal input without needing any callback handler.Keep callback values short and ASCII
Keep callback values short and ASCII
Telegramβs 64-byte callback cap is measured in UTF-8 bytes. Emoji, CJK, or long UUIDs can exhaust the budget quickly. Use compact IDs (e.g.
"approve:42") as callback payloads.Presentations are cleared after each turn
Presentations are cleared after each turn
The captured presentation is popped after
chat() in both streaming and non-streaming paths, so cancelling or returning never leaves stale buttons visible.Test with adapt_presentation()
Test with adapt_presentation()
Call
adapt_presentation(presentation, PresentationLimits.telegram()) before sending to preview which buttons survive the Telegram limit and how select menus are degraded. Use PresentationLimits.whatsapp(), .slack(), or .discord() to preview the other channels.Related
Approval Secure Backend
Durable approval buttons with actor authorisation
Bot Presentations
Overview of bot presentation capabilities
Interactive Bot Actions
Handling button taps and callbacks
Channel Capabilities
What each platform can render

