名称: telegram-compose
描述: |
通过 Telegram 官方 API,使用 HTML 格式发送结构清晰、视觉层次丰富的 Telegram 消息。
此技能由主会话代理自动调用,用于处理实质性的 Telegram 输出——其他技能无需调用。
决策规则:如果你的 Telegram 回复超过 3 行或包含结构化数据(列表、统计数据、章节、报告),则生成此技能作为 Haiku 子代理进行格式化和发送。简短回复(少于 3 行)直接通过 OpenClaw 的 message 工具发送。
处理范围:研究摘要、警报、状态更新、报告、简报、通知——任何需要视觉层次的内容。
元数据: |
{"openclaw":{
"os": ["darwin", "linux"],
"requires": {
"binaries": ["jq", "curl"],
"config": ["channels.telegram.accounts.
},
"credentials": "从 OpenClaw 配置文件(~/.openclaw/openclaw.json 或 ~/.openclaw/clawdbot.json)中读取 Telegram 机器人令牌。具体的账户名必须由调用者提供——此技能不会自动选择账户。",
"network": ["api.telegram.org"]
}}
model-preference: claude-haiku-4-5
subagent: true
允许工具: exec, Read
通过 Telegram 官方 API 和 HTML 格式,编排并发送结构清晰、易于浏览的富文本消息。
此技能由主会话代理自动调用。 其他技能无需知晓其存在。
在向 Telegram 发送消息前,请检查:
message 工具发送。完成。主会话代理调用 sessions_spawn,参数如下:
sessions_spawn(
model: "claude-haiku-4-5",
task: "<任务内容——请见下方模板>"
)
任务模板:
读取位于 {baseDir}/SKILL.md 的 telegram-compose 技能以了解格式化规则,然后将此内容格式化并发送到 Telegram。
机器人账户:<account_name> (例如:"main" —— 必须与 channels.telegram.accounts 中的一个键名匹配)
聊天 ID:<chat_id>
主题 ID:<thread_id> (如果不是论坛/话题聊天,则省略此行)
待格式化的内容:
---
<原始内容在此>
---
发送后,成功则回复消息 ID,失败则回复错误信息。请勿在你的回复中包含格式化后的消息——它已经发送到 Telegram。
重要: 调用者必须指定使用哪个机器人账户。子代理不得自动选择或遍历账户。
关键: 子代理的公告会返回给主会话,而不是发送到 Telegram。因此,主会话在生成子代理后应回复 NO_REPLY 以避免重复发送消息。子代理的 curl 调用才是实际向 Telegram 发送消息的操作。
机器人令牌: 存储在 OpenClaw 配置文件的 channels.telegram.accounts.<name>.botToken 路径下。
账户名始终由调用者提供。 切勿自动选择或遍历账户。
# 自动检测配置文件路径
CONFIG=$([ -f ~/.openclaw/openclaw.json ] && echo ~/.openclaw/openclaw.json || echo ~/.openclaw/clawdbot.json)
# ACCOUNT 由调用者提供(例如:"main")
# 提取令牌前,先验证账户是否存在
ACCOUNT="<provided_account_name>"
BOT_TOKEN=$(jq -r ".channels.telegram.accounts.$ACCOUNT.botToken" "$CONFIG")
if [ "$BOT_TOKEN" = "null" ] || [ -z "$BOT_TOKEN" ]; then
echo "错误:配置中未找到账户 '$ACCOUNT' 或其缺少 botToken"
exit 1
fi
CONFIG=$([ -f ~/.openclaw/openclaw.json ] && echo ~/.openclaw/openclaw.json || echo ~/.openclaw/clawdbot.json)
# ACCOUNT 由调用者提供——永不自动选择
BOT_TOKEN=$(jq -r ".channels.telegram.accounts.$ACCOUNT.botToken" "$CONFIG")
# 无主题线程
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 }
}')"
# 有主题线程
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>粗体</b> <i>斜体</i> <u>下划线</u> <s>删除线</s>
<code>等宽字体</code> <pre>代码块</pre>
<tg-spoiler>点击前隐藏</tg-spoiler>
<blockquote>引用</blockquote>
<blockquote expandable>默认折叠</blockquote>
<a href="url">链接</a>
<a href="tg://user?id=123">通过 ID 提及用户</a>
仅在文本内容中转义以下字符(不在 HTML 标签内):
- & → & (首先执行此操作,避免双重转义)
- < → <
- > → >
常见问题:包含 & 的内容(例如 "R&D", "Q&A")如果不转义,会破坏 HTML 解析。
表情 <b>大写标题</b>
<b>标签:</b> 值
<b>标签:</b> 值
<b>章节</b>
• 要点
• 另一个要点
<blockquote>关键引用或摘要</blockquote>
<blockquote expandable><b>详情</b>
隐藏内容在此...
长内容应放在可展开块中。</blockquote>
<a href="https://...">操作链接 →</a>
表情 <b>大写标题</b>,后跟空行<blockquote expandable>链接文本 →状态更新:
📋 <b>任务完成</b>
<b>任务:</b> 部署 v2.3
<b>状态:</b> ✅ 完成
<b>耗时:</b> 12 分钟
<blockquote>所有健康检查均已通过。</blockquote>
警报:
⚠️ <b>需注意</b>
<b>问题:</b> API 频率限制已达 90%
<b>操作:</b> 检查使用情况
<a href="https://dashboard.example.com">查看仪表板 →</a>
列表:
✅ <b>优先级事项</b>
• <s>审核 PR #234</s> —— 已完成
• <b>完成文档</b> —— 进行中
• 部署到预发布环境
<i>3 项中已完成 2 项</i>
切勿使用 <pre> 显示统计数据、摘要或视觉布局。 <pre> 使用等宽字体,在移动设备上换行效果差,会破坏对齐和树状字符。请将 <pre> 仅用于实际的代码/命令。
对于结构化数据,使用表情符号 + 粗体 + 分隔符:
❌ 错误(在移动端会换行):
<pre>
├─ 🟠 Reddit 32 个主题 │ 1,658 分
└─ 🌐 Web 8 个页面
</pre>
✅ 正确(自然流动):
🟠 <b>Reddit:</b> 32 个主题 · 1,658 分 · 625 条评论
🔵 <b>X:</b> 22 篇帖子 · 10,695 个赞 · 1,137 次转发
🌐 <b>Web:</b> 8 个页面(补充)
🗣️ <b>热门声音:</b> @handle1 · @handle2 · r/subreddit
其他模式:
记录卡片:
<b>Ruby</b>
生日:6月16日 · 年龄:11岁
<b>Rhodes</b>
生日:10月1日 · 年龄:8岁
要点列表:
• <b>hzl-cli:</b> 1.12.0
• <b>skill:</b> 1.0.6
如果格式化后的消息超过 4,096 个字符:
1. 在章节边界处分割(<b>标题</b> 块之间的空行)
2. 每个分块必须是有效的 HTML(不要在标签内分割)
3. 按顺序发送分块,分块之间延迟 1 秒
4. 第一个分块包含完整标题;后续分块添加续接指示符:<i>(续)</i>
如果 Telegram API 返回错误:
| 错误 | 操作 |
|---|---|
Bad Request: can't parse entities |
HTML 格式错误。移除所有 HTML 标签,以纯文本形式重新发送。 |
Bad Request: message is too long |
根据上述规则分割并重试。 |
Bad Request: message thread not found |
不带 message_thread_id 重试(发送到“常规”话题)。 |
Too Many Requests: retry after X |
等待 X 秒,然后重试一次。 |
| 任何其他错误 | 报告错误;不要重试。 |
后备规则: 如果 HTML 格式化失败两次,则发送纯文本,而不是完全不发送。消息送达比格式更重要。
作为子代理运行时,请遵循以下步骤:
& 然后 < 然后 >(不在 HTML 标签内)"ok": true