飞书对接 AI 第六步:不写代码搭出推送机器人——n8n + 飞书 Webhook 全流程(签名校验、社区节点,2026 新版)
前五课都在写代码。这一课换个阵营:一行代码不写,用 n8n 拖拽搭出"定时 → AI 生成 → 推送到飞书群"的完整流水线。
适合三类人:不会 Python 的运营/产品、想快速做告警通知的运维、以及评估"这事到底要不要开发"的技术负责人。工具链两样:飞书自定义机器人(群里直接加,免审核)+ n8n 社区节点 n8n-nodes-lark-webhook(提示岛站内 id=12239 收录,GitHub ★19,MIT)。
〇、先看全景:两条路线怎么选
| 代码路线(L2-L5) | 零代码路线(本课) | |
|---|---|---|
| 机器人类型 | 应用机器人(开发者后台建应用) | 自定义机器人(群设置直接加) |
| 门槛 | 要服务端部署 + 公网回调 | n8n 界面拖拽 |
| 能力 | 读表格、收消息、卡片回调、跨群 | 只能往本群发消息 |
| 鉴权 | tenant_access_token + scope | webhook URL + 关键词/IP/签名 |
| 限流 | 同用户/群 5 QPS | 单租户单机器人 100 次/分钟、5 次/秒 |
| 适合 | 对话机器人、业务数据管道 | 告警、日报、通知类单向推送 |
官方原话划清边界:自定义机器人不具任何数据访问权限——要读表格(L5)、收消息(L4),仍得走应用机器人。本课覆盖的是"往外推"这一半。
一、添加自定义机器人:30 秒拿到 webhook
群设置 → 群机器人 → 添加机器人 → 自定义机器人 → 设头像名称 → 复制 webhook 地址(格式 https://open.feishu.cn/open-apis/bot/v2/hook/xxxx)。
官方红字提醒:请妥善保存此地址,不要公布在 GitLab、博客等公开网站——泄露即被人恶意刷消息。这条对做教程的你同样成立:下文所有示例都用 **** 打码。
二、webhook 消息格式:和 L2 接口有四个关键差异
调用方式:向 webhook POST 一段 JSON。以文本为例:
{
"msg_type": "text",
"content": { "text": "新更新提醒" }
}
与 L2 的 im/v1/messages 对比,四点必须记住:
| 差异点 | L2 应用接口 | 本课 webhook |
|---|---|---|
| content 类型 | JSON 字符串(要双重序列化) | 直接对象({"text": "..."},不用 dumps 两次!) |
| 体积上限 | 文本 150KB | 整个请求体 ≤20KB |
| 消息位置 | 任意用户/群(receive_id) | 固定本群(webhook 即身份) |
| 返回成功 | code=0 + message | {"code":0,"msg":"success"} |
第二点最容易把 L2 的老习惯带进来——webhook 的 content 是对象,照 L2 再 json.dumps 一次必报 9499 Bad Request。
支持的消息类型速查:
| msg_type | 说明 | content 关键结构 |
|---|---|---|
text | 文本 | {"text": "..."};@人用 <at user_id="ou_xxx">Tom</at> |
post | 富文本 | {"post": {"zh_cn": {"title": "...", "content": [[{"tag":"text","text":"..."},{"tag":"a","text":"链接","href":"https://..."},{"tag":"at","user_id":"ou_xxx"}]]}}} |
image | 图片 | {"image_key": "img_xxx"}(仍需先上传换 key) |
share_chat | 群名片 | {"share_chat_id": "oc_xxx"} |
interactive | 卡片 | 顶层用 card 字段(不是 content):{"msg_type":"interactive","card":{...}}。官方 webhook 卡片示例用的是 schema 2.0 结构;如果你复用 L3 的 1.0 卡片 JSON,同样放进 card 字段(两套协议差异见 L3) |
三、三种安全设置:错误码对照 + 签名算法
webhook 裸奔 = 谁拿到地址谁就能发。官方提供三种防护(可叠加):
| 方式 | 规则 | 失败错误码 |
|---|---|---|
| 自定义关键词 | 最多 10 个,消息须含其一。只过滤 text/title 这类文本参数值,不过滤 href | 19024 Key Words Not Found |
| IP 白名单 | 最多 10 个,支持 123.12.1.*、123.1.1.1/24 段 | 19022 Ip Not Allowed |
| 签名校验 | 请求体带 timestamp + sign | 19021 sign match fail... |
签名算法(官方 Python 示例,注意它比常见的 HMAC 用法特殊:签名字符串当 key、对空字符串做 HmacSHA256):
import base64
import hashlib
import hmac
def gen_sign(timestamp: int, secret: str) -> str:
# 官方算法:string_to_sign = timestamp + "\n" + 密钥;对空串做 HmacSHA256 再 Base64
string_to_sign = "{}\n{}".format(timestamp, secret)
hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
return base64.b64encode(hmac_code).decode("utf-8")
发送时把两个字段并进请求体:
import json
import time
import urllib.error
import urllib.request
WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/****" # 你的真实地址别外泄
SECRET = "****" # 开启签名校验后后台给的秘钥
CODE_HINTS = {
9499: "请求体格式错误:对照第二节检查 content 结构、确认 ≤20KB",
19021: "签名校验失败:检查 secret、timestamp(秒级、距当前≤1小时)、服务器时钟",
19022: "来源 IP 不在白名单",
19024: "消息未包含自定义关键词:标题或正文里带上关键词",
11232: "触发限流(100次/分、5次/秒):排队重试;避开整点/半点高峰",
}
def send_webhook(msg_type: str, content=None, card=None) -> dict:
body = {"msg_type": msg_type}
if card is not None:
body["card"] = card # interactive:card 直接放对象
else:
body["content"] = content # 其余:content 也是对象,无需二次序列化
if SECRET:
ts = int(time.time()) # 秒级时间戳
body["timestamp"] = str(ts)
body["sign"] = gen_sign(ts, SECRET)
req = urllib.request.Request(
WEBHOOK_URL,
data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
payload = json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as e:
payload = json.loads(e.read().decode("utf-8"))
if payload.get("code") != 0:
hint = CODE_HINTS.get(payload.get("code"), "查官方自定义机器人指南错误码")
raise RuntimeError(f"[{payload.get('code')}] {payload.get('msg')} | 排查:{hint}")
return payload
if __name__ == "__main__":
send_webhook("text", content={"text": "每日巡检:全部服务正常 ✅"})
四、n8n 路线:装社区节点,10 分钟拖出流水线
节点信息来自提示岛站内条目 id=12239「n8n 飞书自定义机器人节点」(GitHub ★19、MIT、TypeScript,作者 bestony):
- 支持操作:Send Text Message / Send Markdown Message (via card) / Send Post / Send Card——正好覆盖第二节四种主力格式
- 凭证配置:官方 README 两步——①群里创建自定义机器人 ②复制 Webhook URL 粘进 n8n credential 页面
安装与搭建 7 步:
| 步骤 | 操作 | 成功标志 |
|---|---|---|
| 1 | n8n 里 Settings → Community Nodes → Install | 搜到 n8n-nodes-lark-webhook 确认安装(需 n8n 允许社区节点) |
| 2 | 目标群添加自定义机器人,复制 webhook 地址 | 拿到 .../bot/v2/hook/xxxx |
| 3 | n8n 新建 Credentials,粘贴 webhook | 凭证保存成功 |
| 4 | 工作流起点加 Schedule 节点(如每天 9:00) | 节点启用 |
| 5 | 加 OpenAI/LLM 节点,Prompt 填第七节模板 | 测试运行输出报告文本 |
| 6 | 加 Lark Webhook 节点,Operation 选 Send Text,内容引用上一节点输出 {{ $json.output }} | 节点亮绿 |
| 7 | Execute Workflow 手动跑一次 | 群里收到 AI 生成的日报 |
不想装社区节点?等价方案:n8n 原生 HTTP Request 节点直接 POST 第二节的 JSON 到 webhook——效果相同,只是要手填 body。社区节点省掉拼 JSON 这步。
五、四个必踩的坑
坑 1:把 L2 的双重序列化习惯带进来(9499)
webhook 的 content 是对象不是字符串。从 L2 迁移代码的人最常在这翻车——json.dumps(content) 删掉,直接传 dict。
坑 2:限流节奏和应用机器人完全不同(11232)
自定义机器人是单租户单机器人 100 次/分钟、5 次/秒,且官方明确提醒:尽量避开 10:00、17:30 等整点半点——平台压力集中时更容易限流失败,失败会导致消息丢失。定时日报把触发时间设成 9:02、17:33 这种"错峰分钟",比踩着整点发稳妥得多。
坑 3:关键词只过滤文本参数值(19024)
设了关键词"报警",但富文本消息只在 href 里带"报警"——照样被拦。官方规则:只检查 text、title 这类参数值。把关键词放进标题是最稳的做法。
坑 4:签名对不上(19021)
三个高频原因:timestamp 用了毫秒(要秒级)、超过 1 小时(每次发送现算,别缓存 sign)、服务器时钟漂移(校准 NTP)。另注意本课签名是"string_to_sign 当 key、对空串求 HmacSHA256"这个特殊形态,别按通用 HMAC 习惯把 body 当消息签。
结论:webhook 四查——content 别序列化、错峰防 11232、关键词放标题、签名秒级现算。
六、两段可以直接复制的报告类提示词
流水线的 AI 节点里填什么?这两段来自提示岛站内条目,变量槽和 n8n 上游节点输出天然对应。
① 每日/活动报告——id=12018「营销活动报告生成」(4 个变量槽,全文照抄):
You are an AI marketing report writer. Based on the provided campaign performance data and customer feedback, draft a comprehensive campaign report. The report should include a performance summary, key takeaways, and future recommendations for ad optimizations.
My product/service is {{Product/Service:}}
My audience is {{Audience:}}
My Customer Feedbacks are {{Customer Feedback:}}
My Campaign performance is {{Campaign Performance:}}
变量槽 ← n8n 数据源映射:{{Campaign Performance:}} ← 上游 HTTP 节点拉回的后台数据/Google Sheets 节点输出;{{Customer Feedback:}} ← 第五课那种表格读出的行数据;{{Product/Service:}}/{{Audience:}} ← Set 节点常量的固定值。四个槽三个能自动化喂数,两个一次配置固定——这就是报告机器人"全自动"的真相:提示词只是模板,变量来自工作流。
② 监控巡检报告——id=11395「广告投放频次监控」:
Function as a {{Ad Frequency:}} ad campaign manager. Devise a comprehensive process for routinely observing the effectiveness of my ad campaigns for the product/service. My product/service is {{Product/Service:}}, and my audience is {{Audience:}}
The strategy should be capable of meticulously analyzing key performance indicators and should include a plan for improving the campaign based on these observations.
用法差异:①产出"这一期的报告"(配 Schedule 定期推),②产出"持续监控的机制建议"(一次性生成 SOP,结果可存进多维表格再让①每期引用)。
结论:报告机器人的提示词要"留满变量槽"——每个槽接一个自动化数据源,机器人才能真正无人值守。
这一课做完,你手上有什么
- 自定义机器人 webhook 的正确用法(content 对象、20KB、错峰限流)
- 签名校验完整实现(官方算法 + 5 个错误码中文映射)
- n8n 社区节点 7 步搭建流程(零代码版"AI 日报机器人")
- 两段变量槽对齐 n8n 数据流的报告提示词
下一课(L7,收官):完整项目复盘——把 L1-L6 拧成一个"多机器人协作"的实战架构,并盘点提示岛站内那 147 条飞书插件里还有哪些可直接拿来用的轮子。
附:提示岛是什么
本文节点与提示词来自提示岛(prompts.ssjintaitong.com),AI 提示词与 Skill 库,实测收录 10909 条,其中文字提示词 3484 条(完整全文、一键复制),Skill/插件 5298 条,23 个分类。免登录、免注册。
飞书相关入口:
- 飞书 AI 自动化专题(147 条):
prompts.ssjintaitong.com/topic/feishu - 本文节点原文:
prompts.ssjintaitong.com/prompts/12239(附 GitHub 源码链接) - 本文两段提示词:
prompts.ssjintaitong.com/prompts/12018、/prompts/11395 - 本系列 L1-L5 教程条目:同专题内搜「飞书对接 AI」
站内两个实用功能:Skill 质量评分(5298 个插件条目按四维度打 A-D 档,报告在 /quality-report);每条附原始出处(GitHub 链接 + 许可证)。搜索技巧:用场景词搜,搜「飞书」有 133 条,站内搜「n8n 飞书」直接命中本课节点。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)