简介
这是一个小 Python helper,把 LLM 输出的纯 markdown 转成合法的 Slack Block Kit JSON —— header / section / divider / fields / buttons / image —— 自动把超过 Slack 3001 字符/块限制的文本切块。Slack 消息不用 Block Kit 难看,用 Block Kit 又要写脆弱的手工 JSON。这个 helper 把两者打通。适合发摘要、告警、每日 digest、报告到 Slack 频道的 AI bot。兼容 Slack Bolt SDK(Python/JS)、Slack chat.postMessage REST。装机时间 5 分钟。
Helper 代码
from typing import Iterable
def md_to_blocks(text: str) -> list[dict]:
blocks = []
for raw in text.split("\n\n"):
chunk = raw.strip()
if not chunk:
continue
if chunk.startswith("# "):
blocks.append({"type": "header", "text": {"type": "plain_text", "text": chunk[2:].strip()[:150]}})
elif chunk == "---":
blocks.append({"type": "divider"})
else:
for piece in _split_3000(chunk):
blocks.append({"type": "section", "text": {"type": "mrkdwn", "text": piece}})
return blocks
def _split_3000(s: str, limit: int = 2900) -> Iterable[str]:
while len(s) > limit:
cut = s.rfind("\n", 0, limit)
if cut == -1:
cut = s.rfind(" ", 0, limit) or limit
yield s[:cut]
s = s[cut:].lstrip()
if s:
yield s
def add_actions(blocks: list[dict], buttons: list[tuple[str, str, str]]) -> list[dict]:
if not buttons:
return blocks
blocks.append({
"type": "actions",
"elements": [
{"type": "button", "text": {"type": "plain_text", "text": label},
"action_id": action_id, "url": url}
for label, action_id, url in buttons
],
})
return blocks配 Bolt 用
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
import os
app = App(token=os.environ["SLACK_BOT_TOKEN"])
llm_text = '''# Daily AI Digest
今天 TokRepo 上新了 *5 个 MCP server*。
- Stripe MCP —— 支付
- Datadog MCP —— 可观测
- Linear MCP —— issue tracker
---
最热反应:stripe-mcp 6 小时拿了 47 星。'''
blocks = md_to_blocks(llm_text)
blocks = add_actions(blocks, [("打开 TokRepo", "open_tokrepo", "https://tokrepo.com/explore")])
app.client.chat_postMessage(channel="#ai-digest", blocks=blocks, text="Daily AI Digest")Slack Block Kit 限制(cheat sheet)
| 项目 | 限制 |
|---|---|
| 每条消息块数 | 50 |
| Section 文本 | 3,000 字符 |
| Header 文本 | 150 字符 |
| 每 actions 块元素数 | 25 |
| 总消息大小 | 40 KB |
FAQ
Q: 为啥用 mrkdwn 不用 markdown?
A: Slack 的 mrkdwn 是 markdown 的子集 —— *粗体*(一个星号不是两个)、_斜体_、<url|文字> 链接,没标题,没表格。Helper 输出 mrkdwn 风味文本。手动转换 LLM markdown 就是这个 helper 省的力气。
Q: LLM 需要知道 Block Kit 吗? A: 不需要 —— 这就是重点。让它输出普通 markdown,helper 负责转。把 Block Kit JSON 写进 prompt 反而让输出又脆又啰嗦。
Q: 超过 50 块怎么办?
A: Slack 报 invalid_blocks 错。当成 thread 发 —— 第一条用前 50 块,再用 chat.postMessage 带 thread_ts 续发。或者拆成多条顶层消息,按天/分节加标题。