Format and deliver rich Telegram messages with HTML formatting via direct Telegram API.
Auto-invoked by the main session for substantive Telegram output — no other skills need to call it.
Decision rule: If your Telegram reply is >3 lines or contains structured data (lists, stats, sections, reports),
spawn this as a Haiku sub-agent to format and send. Short replies (<3 lines) go directly via OpenClaw message tool.
Handles: research summaries, alerts, status updates, reports, briefings, notifications — anything with visual hierarchy.
Format and deliver rich Telegram messages with HTML formatting via direct Telegram API.
Auto-invoked by the main session for substantive Telegram output — no other skills need to call it.
Decision rule: If your Telegram reply is >3 lines or contains structured data (lists, stats, sections, reports),
spawn this as a Haiku sub-agent to format and send. Short replies (<3 lines) go directly via OpenClaw message tool.
Handles: research summaries, alerts, status updates, reports, briefings, notifications — anything with visual hierarchy.
metadata
{"openclaw":{
"os": ["darwin", "linux"],
"requires": {
"binaries": ["jq", "curl"],
"config": ["channels.telegram.accounts.<account>.botToken"]
},
"credentials": "Reads Telegram bot token from OpenClaw config file (~/.openclaw/openclaw.json or ~/.openclaw/clawdbot.json). The specific account name must be provided by the caller — the skill does not auto-select accounts.",
"network": ["api.telegram.org"]
}}
model-preference
claude-haiku-4-5
subagent
true
allowed-tools
exec, Read
Telegram Compose
Format and deliver rich, scannable Telegram messages via direct API with HTML formatting.
How This Skill Gets Used
This skill is auto-invoked by the main session agent. No other skills need to know about it.
Decision Rule (for the main session agent)
Before sending a message to Telegram, check:
Short reply (<3 lines, no structure): Send directly via OpenClaw message tool. Done.
Substantive content (>3 lines, or has lists/stats/sections/reports): Spawn this skill as a sub-agent.
Read the telegram-compose skill at {baseDir}/SKILL.md for formatting rules, then format and send this content to Telegram.
Bot account: <account_name> (e.g., "main" — must match a key in channels.telegram.accounts)
Chat ID: <chat_id>
Thread ID: <thread_id> (omit this line if not a forum/topic chat)
Content to format:
---
<raw content here>
---
After sending, reply with the message_id on success or the error on failure. Do NOT include the formatted message in your reply — it's already been sent to Telegram.
IMPORTANT: The caller MUST specify which bot account to use. The sub-agent must NOT auto-select or iterate accounts.
CRITICAL: The sub-agent announcement routes back to the main session, NOT to Telegram. So the main session should reply NO_REPLY after spawning to avoid double-messaging. The sub-agent's curl call is what delivers to Telegram.
What the sub-agent receives
Skill path — so it can read the formatting rules
Bot account name — which Telegram bot account to use (must be specified, never auto-selected)
Chat ID — where to send
Thread ID — topic thread if applicable
Raw content — the unformatted text/data to turn into a rich message
Credentials
Bot token: Stored in the OpenClaw config file under channels.telegram.accounts.<name>.botToken.
The account name is always provided by the caller. Never auto-select or iterate accounts.
# Auto-detect config path
CONFIG=$([ -f ~/.openclaw/openclaw.json ] && echo ~/.openclaw/openclaw.json || echo ~/.openclaw/clawdbot.json)
# ACCOUNT is provided by the caller (e.g., "main")# Validate the account exists before extracting the token
ACCOUNT="<provided_account_name>"
BOT_TOKEN=$(jq -r ".channels.telegram.accounts.$ACCOUNT.botToken""$CONFIG")
if [ "$BOT_TOKEN" = "null" ] || [ -z "$BOT_TOKEN" ]; thenecho"ERROR: Account '$ACCOUNT' not found in config or has no botToken"exit 1
fi
<b>bold</b> <i>italic</i> <u>underline</u> <s>strike</s>
<code>mono</code> <pre>code block</pre>
<tg-spoiler>hidden until tapped</tg-spoiler>
<blockquote>quote</blockquote>
<blockquote expandable>collapsed by default</blockquote>
<a href="url">link</a>
<a href="tg://user?id=123">mention by ID</a>
Escaping
Escape these characters in text content only (not in your HTML tags):
& → & (do this FIRST to avoid double-escaping)
< → <
> → >
Common gotcha: content containing & (e.g., "R&D", "Q&A") will break HTML parsing if not escaped.
Structure Pattern
EMOJI <b>HEADING IN CAPS</b>
<b>Label:</b> Value
<b>Label:</b> Value
<b>SECTION</b>
• Bullet point
• Another point
<blockquote>Key quote or summary</blockquote>
<blockquote expandable><b>Details</b>
Hidden content here...
Long details go in expandable blocks.</blockquote>
<a href="https://...">Action Link →</a>
Style Rules
Faux headings:EMOJI <b>CAPS TITLE</b> with blank line after
Emojis: 1-3 per message as visual anchors, not decoration
Whitespace: Blank lines between sections
Long content: Use <blockquote expandable>
Links: Own line, with arrow: Link Text →
Examples
Status update:
📋 <b>TASK COMPLETE</b>
<b>Task:</b> Deploy v2.3
<b>Status:</b> ✅ Done
<b>Duration:</b> 12 min
<blockquote>All health checks passing.</blockquote>
Alert:
⚠️ <b>ATTENTION NEEDED</b>
<b>Issue:</b> API rate limit at 90%
<b>Action:</b> Review usage
<a href="https://dashboard.example.com">View Dashboard →</a>
Never use <pre> for stats, summaries, or visual layouts.<pre> uses monospace font and wraps badly on mobile, breaking alignment and tree characters. Reserve <pre> for actual code/commands only.
For structured data, use emoji + bold + separators: