telegram-composeFormat 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.
Install via ClawdBot CLI:
clawdbot install tmchow/telegram-composeFormat and deliver rich, scannable Telegram messages via direct API with HTML formatting.
This skill is auto-invoked by the main session agent. No other skills need to know about it.
Before sending a message to Telegram, check:
message tool. Done.The main session agent calls sessions_spawn with:
sessions_spawn(
model: "claude-haiku-4-5",
task: "<task content โ see template below>"
)
Task template:
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.
Bot token: Stored in the OpenClaw config file under channels.telegram.accounts..
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" ]; then
echo "ERROR: Account '$ACCOUNT' not found in config or has no botToken"
exit 1
fi
CONFIG=$([ -f ~/.openclaw/openclaw.json ] && echo ~/.openclaw/openclaw.json || echo ~/.openclaw/clawdbot.json)
# ACCOUNT provided by caller โ never auto-select
BOT_TOKEN=$(jq -r ".channels.telegram.accounts.$ACCOUNT.botToken" "$CONFIG")
# Without topic thread
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg chat "$CHAT_ID" \
--arg text "$MESSAGE" \
'{
chat_id: $chat,
text: $text,
parse_mode: "HTML",
link_preview_options: { is_disabled: true }
}')"
# With topic thread
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg chat "$CHAT_ID" \
--arg text "$MESSAGE" \
--argjson thread $THREAD_ID \
'{
chat_id: $chat,
text: $text,
parse_mode: "HTML",
message_thread_id: $thread,
link_preview_options: { is_disabled: true }
}')"
<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>
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.
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>
EMOJI CAPS TITLE with blank line afterLink Text โ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>
List:
โ
<b>PRIORITIES</b>
โข <s>Review PR #234</s> โ done
โข <b>Finish docs</b> โ in progress
โข Deploy staging
<i>2 of 3 complete</i>
Never use for stats, summaries, or visual layouts. uses monospace font and wraps badly on mobile, breaking alignment and tree characters. Reserve for actual code/commands only.
For structured data, use emoji + bold + separators:
โ BAD (wraps on mobile):
<pre>
โโ ๐ Reddit 32 threads โ 1,658 pts
โโ ๐ Web 8 pages
</pre>
โ
GOOD (flows naturally):
๐ <b>Reddit:</b> 32 threads ยท 1,658 pts ยท 625 comments
๐ต <b>X:</b> 22 posts ยท 10,695 likes ยท 1,137 reposts
๐ <b>Web:</b> 8 pages (supplementary)
๐ฃ๏ธ <b>Top voices:</b> @handle1 ยท @handle2 ยท r/subreddit
Other patterns:
Record cards:
<b>Ruby</b>
Birthday: Jun 16 ยท Age: 11
<b>Rhodes</b>
Birthday: Oct 1 ยท Age: 8
Bullet lists:
โข <b>hzl-cli:</b> 1.12.0
โข <b>skill:</b> 1.0.6
If formatted message exceeds 4,096 chars:
HEADING blocks)(continued)If Telegram API returns an error:
| Error | Action |
|-------|--------|
| Bad Request: can't parse entities | HTML is malformed. Strip all HTML tags and resend as plain text. |
| Bad Request: message is too long | Split per the rules above and retry. |
| Bad Request: message thread not found | Retry without message_thread_id (sends to General). |
| Too Many Requests: retry after X | Wait X seconds, then retry once. |
| Any other error | Report the error back; don't retry. |
Fallback rule: If HTML formatting fails twice, send as plain text rather than not sending at all. Delivery matters more than formatting.
When running as a sub-agent, follow this sequence:
& then < then > in text content only (not in your HTML tags)"ok": trueGenerated Mar 1, 2026
A market research firm uses this skill to format and send detailed research summaries to client Telegram groups. The sub-agent structures findings with headings, bullet points, and expandable blocks for data-heavy sections, ensuring readability and compliance with Telegram's HTML formatting rules.
An IT operations team employs this skill to send formatted system status updates and outage reports to a Telegram channel. It highlights critical issues in bold, includes timestamps, and uses emojis for visual urgency, helping teams quickly scan and respond to incidents.
A fintech company uses this skill to deliver daily financial reports to investor Telegram groups. The sub-agent formats key metrics like revenue and growth stats with structured sections, blockquotes for highlights, and links to detailed documents, maintaining a professional presentation.
A media agency leverages this skill to send content briefings and editorial calendars to remote teams via Telegram. It organizes topics with headings, bullet lists for tasks, and expandable blocks for detailed guidelines, streamlining communication across distributed workflows.
Offer this skill as part of a SaaS platform that automates notifications and reports for businesses. Charge a monthly subscription based on message volume, providing value through formatted, scannable updates that enhance user engagement and reduce manual formatting effort.
Provide managed services where agencies use this skill to deliver client reports and alerts via Telegram. Bill clients on a retainer or per-project basis, leveraging the skill's automation to improve efficiency and presentation quality in client communications.
License this skill as a developer tool for integration into custom applications. Generate revenue through one-time licensing fees or usage-based pricing, targeting developers who need reliable, formatted Telegram messaging without building from scratch.
๐ฌ Integration Tip
Ensure the main session agent correctly handles the NO_REPLY directive after spawning to prevent duplicate messages, and validate bot account configurations before deployment to avoid token errors.
iMessage/SMS CLI for listing chats, history, watch, and sending.
Use when you need to control Discord from Clawdbot via the discord tool: send messages, react, post or upload stickers, upload emojis, run polls, manage threads/pins/search, fetch permissions or member/role/channel info, or handle moderation actions in Discord DMs or channels.
Use when you need to control Slack from Clawdbot via the slack tool, including reacting to messages or pinning/unpinning items in Slack channels or DMs.
Send WhatsApp messages to other people or search/sync WhatsApp history via the wacli CLI (not for normal user chats).
Build or update the BlueBubbles external channel plugin for Clawdbot (extension package, REST send/probe, webhook inbound).
OpenClaw skill for designing Telegram Bot API workflows and command-driven conversations using direct HTTPS requests (no SDKs).