Skip to main content
PolyBot provides a fluent, type-safe builder hierarchy to construct structured InputRichMessage payloads for Telegram. Instead of manually stitching together raw block objects and formatting entities, RichMessageBuilder and RichTextBuilder let you compose layout blocks, rich inline typography, tables, and embedded media declaratively.

Composing rich messages

Use RichMessageBuilder to assemble high-level document blocks like paragraphs, headings, block quotations, collapsible details, and media.
RichMessageBuilder implements an implicit conversion operator to InputRichMessage. You can pass the builder directly anywhere an InputRichMessage is expected.

Structural & layout blocks

RichMessageBuilder provides helpers for every standard block type. Overloads accept raw strings for quick plain text, child block collections, or an inline Action<RichTextBuilder> to format text inline.

Tables

You can render tables using grid matrices of text or customize cells using RichBlockFactory.Cell for alignment and spans.

Media blocks & attachments

Attach media directly to block sequences or associate upload identifiers with embedded media definitions.

Inline text formatting: RichTextBuilder

Whenever you pass Action<RichTextBuilder> into a block, you can chain inline formatting styles, mentions, links, and entity tokens without escaping delimiters manually.

Advanced inline entities

RichTextBuilder supports special Telegram entity types such as timestamps, custom emoji, user mentions, and deep anchors:

Nested formatting

All RichTextBuilder formatting methods provide overloads accepting pre-built RichText nodes, making deep nesting straightforward:

Buttons: RichButtonsBuilder

Use RichButtonsBuilder to compose a standalone buttons block (as opposed to a button embedded inside a paragraph via RichTextBuilder). Every button kind has a plain-label overload and a RichButtonTextBuilder overload whose label is restricted to the entity subset the Bot API allows inside button text (plain text, custom emoji, date/time):
The generic Button(...) overloads accept a pre-built RichText label plus exactly one action (url, callbackData, webApp, loginUrl, switchInlineQuery, switchInlineQueryCurrentChat, switchInlineQueryChosenChat, or copyText). Build() returns RichMessageButton[], and an implicit conversion to the array type exists, so a RichButtonsBuilder can be passed anywhere a button collection is expected.
RichMessageButtonStyle (Primary, Success, Danger, …) styles the button inside the rich-message render; disabled: true renders the button as non-interactive.

Low-level composition: RichBlockFactory & RichTextFactory

For scenarios where dynamic block construction or AST-like manipulation is required, use RichBlockFactory and RichTextFactory directly. The factory handles setting block discriminators automatically so you only populate content models.

Special considerations for Thinking blocks

The Thinking block represents a collapsible AI thought process placeholder, mapping to the custom <tg-thinking> tag. An InputRichBlockThinking block cannot be sent inside standard SendRichTextMessage requests. Calling SendRichTextMessage with a thinking block will throw an API exception:
Thinking blocks are restricted by Telegram exclusively to SendRichMessageDraft calls and will never appear on received message payloads. When configuring thinking blocks, you can pair them with Telegram’s official AI Actions custom emoji to indicate progress states:

Message configurations

RichMessageBuilder includes flags to control message text direction and rendering behavior before calling Build():