Skip to content

[gateway] Add support for Telegram Bot API 10.1 RichBlockTable (native tables) in messaging pipeline #47095

Description

@dmitry-cashtime

Problem

Telegram Bot API 10.1 (released 2026-06-11, four days before this issue) introduced RichBlockTable — a structured block-tree JSON entity that renders as a native, styled table in the Telegram client (mobile + desktop + web), with full per-cell styling, is_bordered / is_striped, and a caption.

The new send method is sendRichMessage (plus streaming partial rich messages), and editMessageText now accepts rich_message.

The Hermes→Telegram gateway currently does NOT convert markdown pipe tables to this new format. When an agent emits a markdown table in a Telegram DM, the user sees it as plain text (or, per the system prompt, auto-rewritten to row-group bullets which is worse).

Real-world trigger

The agent needed to send a 6-column comparison of LLM inference service prices (DeepInfra / Together / Fireworks / OpenRouter / Anthropic / OpenAI / Google × MiniMax-M3, Qwen3-32B-FT, DeepSeek-V4-Pro, etc.). Three attempts:

  1. Markdown pipe table — rendered as plain text in user's client
  2. Monospace code block with str.ljust()-aligned columns — looked like ASCII art, not a table
  3. Pre/code with MarkdownV2 entity — also rendered as text

Final workaround: generate a PNG via Pillow, send via MEDIA: directive. This works but the image is non-selectable, non-responsive, and a hack.

Proposed solution

In the Telegram gateway (gateway/platforms/telegram.py or wherever outbound message construction lives), detect markdown pipe tables in the agent's output, parse them, and emit a RichMessage block via the new sendRichMessage method.

Scope:

  • New module: gateway/rich_text/markdown_to_rich.py — converts standard markdown (bold, italic, lists, code, tables) to the RichMessage block tree.
  • New method (or extend send_message) in gateway/platforms/telegram.py that calls sendRichMessage when the converted payload contains a RichBlockTable or other rich blocks; falls back to plain sendMessage with parse_mode=MarkdownV2 for plain text without tables.
  • Backwards compatible: existing parse_mode=MarkdownV2 flow continues to work; rich pipeline is opt-in by content detection.

Acceptance criteria:

  • Agent emits a 3+ column markdown pipe table → user sees a real bordered table in Telegram client
  • Header row is is_header: true, cells use align: "right" for numeric columns
  • Existing bold/italic/code/blockquote/spoiler keep working through the same code path
  • Falls back gracefully to MarkdownV2 if sendRichMessage is not supported by the user's client version
  • Backwards compatible: existing tests pass; no breaking changes to public API

Environment

  • Hermes version: latest (hermes update)
  • Telegram Bot API: 10.1+
  • Tested with: Telegram Desktop 4.x, Telegram iOS 10.x, Telegram Android 10.x
  • Python: 3.11
  • Pillow already a dep (used for current PNG-table workaround)

Workaround currently in use

While this is being implemented, end-users in the Hermes community have a workaround skill that generates a PNG via Pillow and ships it as MEDIA:. This skill is functional but lossy (no copy/paste, no dark mode, no per-cell styling). It would be retired once native rich tables ship.

Why this matters

Multi-column data comparison degrades to either bullet lists (loses column alignment) or PNG hacks (loses interactivity). Bot API 10.1 closes this gap; the gateway just needs to expose it.

Reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havecomp/gatewayGateway runner, session dispatch, deliveryduplicateThis issue or pull request already existsplatform/telegramTelegram bot adaptertype/featureNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions