飞书自定义机器人使用指南
整理时间: 2026-02-06 15:47
来源: 飞书开放平台官方文档
原文链接: https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot
整理人: AI助手
摘要
自定义机器人是一种只能在当前群聊中使用的机器人,无需租户管理员审核即可通过调用 webhook 地址完成消息推送。本文档详细介绍自定义机器人的添加、配置、安全设置以及支持的消息类型。
1. 注意事项
- 仅当前群聊可用:自定义机器人只能在当前群聊内使用,无法添加到其他群聊
- 需要开发基础:需具备服务端开发基础,通过 HTTP POST 请求调用 webhook
- 无需审核:添加后即可使用,但不具有任何数据访问权限
- 频率限制:单租户单机器人 100 次/分钟,5 次/秒
- ⚠️ 建议避开整点及半点时间(如 10:00、17:30),避免 11232 限流错误
- 请求体大小限制:不能超过 20 KB
2. 功能介绍
适用场景:
- 监控报警推送
- 销售线索通知
- 运营内容推送
- 自动化消息通知
安全设置支持三种维度:
1. 自定义关键词
2. IP 白名单
3. 签名校验
3. 在群组中添加自定义机器人
3.1 操作步骤
- 邀请机器人进群
- 进入目标群组 → 点击右上角「设置」
- 选择「群机器人」→「添加机器人」
- 找到并点击「自定义机器人」
-
设置头像、名称与描述,点击「添加」
-
获取 webhook 地址
https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx
⚠️ 请妥善保存,不要公布在 Gitlab、博客等公开网站 -
测试调用
macOS:
bash
curl -X POST -H "Content-Type: application/json" \
-d '{"msg_type":"text","content":{"text":"request example"}}' \
https://open.feishu.cn/open-apis/bot/v2/hook/****
Windows (cmd):
bash
curl -X POST -H "Content-Type: application/json" -d "{\"msg_type\":\"text\",\"content\":{\"text\":\"request example\"}}" https://open.feishu.cn/open-apis/bot/v2/hook/****
Windows (PowerShell):
bash
curl.exe -X POST -H "Content-Type: application/json" -d '{\"msg_type\":\"text\",\"content\":{\"text\":\"requestexample\"}}' https://open.feishu.cn/open-apis/bot/v2/hook/****
成功返回:
json
{
"code": 0,
"data": {},
"msg": "success"
}
4. 安全设置
4.1 方式一:自定义关键词
- 最多设置 10 个关键词,回车间隔
- 消息需至少包含一个关键词才能发送成功
- 仅对
text、title等文本参数生效
校验失败返回:
{
"code": 19024,
"msg": "Key Words Not Found"
}
4.2 方式二:IP 白名单
- 最多设置 10 个 IP 地址或地址段
- 支持段输入:
123.12.1.*或123.1.1.1/24
校验失败返回:
{
"code": 19022,
"msg": "Ip Not Allowed"
}
4.3 方式三:签名校验
使用 HmacSHA256 算法计算签名:
签名字符串格式: timestamp + "\n" + 密钥
时间戳要求: 距当前时间不超过 1 小时(3600 秒)
示例代码
Java:
private static String GenSign(String secret, int timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signData = mac.doFinal(new byte[]{});
return new String(Base64.encodeBase64(signData));
}
Python:
import hashlib
import base64
import hmac
def gen_sign(timestamp, secret):
string_to_sign = '{}\n{}'.format(timestamp, secret)
hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
sign = base64.b64encode(hmac_code).decode('utf-8')
return sign
Go:
func GenSign(secret string, timestamp int64) (string, error) {
stringToSign := fmt.Sprintf("%v", timestamp) + "\n" + secret
h := hmac.New(sha256.New, []byte(stringToSign))
_, err := h.Write([]byte{})
if err != nil {
return "", err
}
signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
return signature, nil
}
请求体示例:
{
"timestamp": "1599360473",
"sign": "xxxxxxxxxxxxxxxxxxxxx",
"msg_type": "text",
"content": {
"text": "request example"
}
}
校验失败返回:
{
"code": 19021,
"msg": "sign match fail or timestamp is not within one hour from current time"
}
5. 支持发送的消息类型
5.1 文本消息 (text)
{
"msg_type": "text",
"content": {
"text": "新更新提醒"
}
}
@ 用法:
<!-- @ 单个用户 -->
<at user_id="ou_xxx">名字</at>
<!-- @ 所有人 -->
<at user_id="all">所有人</at>
@ 用户示例:
{
"msg_type": "text",
"content": {
"text": "<at user_id=\"ou_xxx\">Tom</at> 新更新提醒"
}
}
5.2 富文本消息 (post)
{
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "项目更新通知",
"content": [
[{
"tag": "text",
"text": "项目有更新: "
}, {
"tag": "a",
"text": "请查看",
"href": "http://www.example.com/"
}, {
"tag": "at",
"user_id": "ou_18eac8********17ad4f02e8bbbb"
}]
]
}
}
}
}
支持的标签:
| 标签 | 说明 | 必填字段 |
|------|------|----------|
| text | 文本 | text |
| a | 超链接 | text, href |
| at | @用户 | user_id |
| img | 图片 | image_key |
5.3 群名片 (share_chat)
{
"msg_type": "share_chat",
"content": {
"share_chat_id": "oc_f5b1a7eb27ae2****339ff"
}
}
5.4 图片消息 (image)
{
"msg_type": "image",
"content": {
"image_key": "img_ecffc3b9-8f14-400f-a014-05eca1a4310g"
}
}
图片需通过「上传图片」接口获取 image_key
5.5 飞书卡片 (interactive)
{
"msg_type": "interactive",
"card": {
"schema": "2.0",
"config": {
"update_multi": true
},
"body": {
"direction": "vertical",
"padding": "12px 12px 12px 12px",
"elements": [
{
"tag": "markdown",
"content": "西湖,位于中国浙江省杭州市...",
"text_align": "left"
},
{
"tag": "button",
"text": {
"tag": "plain_text",
"content": "🌞更多景点介绍"
},
"behaviors": [{
"type": "open_url",
"default_url": "https://baike.baidu.com/..."
}]
}
]
},
"header": {
"title": {
"tag": "plain_text",
"content": "今日旅游推荐"
},
"template": "blue"
}
}
}
注意事项:
- 仅支持 URL 跳转,不支持回调服务端
- @ 用户仅支持 Open ID 或 User ID,不支持 email、union_id
- 需将 content 替换为 card 结构体并 JSON 转义
6. 常见问题
Q1: 如何实现 @ 指定人、@ 所有人?
- 文本消息:使用
<at user_id="ou_xxx">名字</at> - 富文本消息:使用
"tag": "at", "user_id": "ou_xxx" - 卡片消息:使用
<at id=ou_xxx></at> - @ 所有人:
user_id填all
Q2: 如何获得 @ 指定人时的 open_id?
自定义机器人本身不能获取 open_id,需通过以下方案:
方案一:通过邮箱/手机号反查
1. 创建自建应用
2. 申请权限:contact:user.id:readonly
3. 调用「通过手机号或邮箱获取用户 ID」接口
方案二:解析用户消息
1. 创建自建应用
2. 申请权限:im:message、im:message.p2p_msg
3. 订阅「接收消息」事件
4. 从消息中解析被 @ 用户的 open_id
Q3: 自定义机器人能响应用户消息吗?
不能。自定义机器人只能推送消息,无法接收和响应用户消息。
Q4: 如何撤回自定义机器人发送的消息?
调用「撤回消息」API,需传入发送消息时返回的 message_id。
7. 相关链接
本文档基于飞书开放平台官方文档整理,如有更新请以官方文档为准。