飞书发图片 & 文件 Skill
强制规则(Feishu channel)
- - 任务产出了图片,必须主动发送到当前会话,不等用户催促。
- 用户说"发给我/群里看图"时,必须走脚本,不能只返回本地路径。
- 发送后记录
code、msg、message_id 用于排查。
关键:receive_id 前缀判断
| 前缀 | receiveidtype | 场景 |
|---|
| INLINECODE3 | INLINECODE4 | 私聊(单人) |
| INLINECODE5 |
chat_id | 群聊 |
脚本已自动判断,不需要手动传 type。
获取凭据
从 OpenClaw 配置读取 appid / appsecret:
CODEBLOCK0
从 context inboundmeta 获取 receiveid(去掉 user: 前缀保留 ou_... 部分)。
发送图片
方式一:用脚本(推荐)
CODEBLOCK1
参数说明:
- -
image_path:要发送的图片路径(JPEG/PNG/WEBP/GIF/TIFF/BMP/ICO) - INLINECODE10 :接收者 ID,支持
ou_...(私聊)或 oc_...(群聊),脚本自动判断类型 - INLINECODE13 :飞书应用 ID(从
openclaw.json 的 channels.feishu.appId 读取) - INLINECODE16 :飞书应用密钥(从
openclaw.json 的 channels.feishu.appSecret 读取) - INLINECODE19 :可选,默认
feishu;国际版 Lark 传 INLINECODE21
示例:
CODEBLOCK2
完整路径示例:
CODEBLOCK3
发送文件
方式一:用脚本(推荐)
CODEBLOCK4
参数说明:
- -
file_path:要发送的文件路径(HTML/PDF/ZIP/代码文件等) - INLINECODE23 :接收者 ID,支持
ou_...(私聊)或 oc_...(群聊),脚本自动判断类型 - INLINECODE26 :飞书应用 ID(从
openclaw.json 的 channels.feishu.appId 读取) - INLINECODE29 :飞书应用密钥(从
openclaw.json 的 channels.feishu.appSecret 读取) - INLINECODE32 :可选,自定义文件名(不填则用原文件名)
示例:
CODEBLOCK5
完整路径示例:
CODEBLOCK6
方式二:手动两步
Step 1 - 上传文件:
CODEBLOCK7
Step 2 - 发送消息:
CODEBLOCK8
脚本底层逻辑说明
发送原理
飞书消息链路中,发送文件或图片的最佳方式是采用“两步法”:
- 1. 先上传:将本地文件上传到
im/v1/files 或 im/v1/images,获取持久化的 file_key 或 image_key。 - 后发送:调用
im/v1/messages 接口,指定 msg_type 为 file 或 image 并携带对应的 Key。
直接传递本地路径字符串到消息接口通常会导致客户端只显示路径文本。本脚本通过自动化这两步流程,确保用户在飞书里实际看到图片本体或可预览的文件。
普通文件 vs 图片的链路区别
- - 普通文件:
im/v1/files -> file_key -> INLINECODE43 - 图片:
im/v1/images -> image_key -> INLINECODE46
脚本会自动处理这些差异。
排查
- - 发送失败先看
code / INLINECODE48 - 群发失败检查:机器人已入群 + sendmessage 权限 + 使用正确的
oc_ chatid - INLINECODE50 误当
open_id 发必定报错 - 不要把本地路径回显误判为发送成功
- 飞书 file_type 用
stream 适用于所有普通文件类型
飞书发图片 & 文件 Skill
强制规则(Feishu channel)
- - 任务产出了图片,必须主动发送到当前会话,不等用户催促。
- 用户说发给我/群里看图时,必须走脚本,不能只返回本地路径。
- 发送后记录 code、msg、message_id 用于排查。
关键:receive_id 前缀判断
| 前缀 | receiveidtype | 场景 |
|---|
| ou... | openid | 私聊(单人) |
| oc... |
chatid | 群聊 |
脚本已自动判断,不需要手动传 type。
获取凭据
从 OpenClaw 配置读取 appid / appsecret:
bash
grep -A 2 feishu /root/.openclaw/openclaw.json | grep -E (appId|appSecret)
从 context inboundmeta 获取 receiveid(去掉 user: 前缀保留 ou_... 部分)。
发送图片
方式一:用脚本(推荐)
bash
python3 skills/feishu-send-file/scripts/sendimage.py path> id> id> [domain]
参数说明:
- - imagepath:要发送的图片路径(JPEG/PNG/WEBP/GIF/TIFF/BMP/ICO)
- receiveid:接收者 ID,支持 ou...(私聊)或 oc...(群聊),脚本自动判断类型
- appid:飞书应用 ID(从 openclaw.json 的 channels.feishu.appId 读取)
- appsecret:飞书应用密钥(从 openclaw.json 的 channels.feishu.appSecret 读取)
- domain:可选,默认 feishu;国际版 Lark 传 lark
示例:
bash
发个人(ou_...)
python3 skills/feishu-send-file/scripts/send
image.py ./chart.png ouxxx $APP
ID $APPSECRET
发群(oc_...)
python3 skills/feishu-send-file/scripts/send
image.py ./chart.png ocxxx $APP
ID $APPSECRET
国际版 Lark
python3 skills/feishu-send-file/scripts/send
image.py ./chart.png ouxxx $APP
ID $APPSECRET lark
完整路径示例:
bash
python3 /root/.openclaw/workspace/skills/feishu-send-file/scripts/send_image.py \
/root/myfiles/generated-images/demo.png \
RECEIVEID> \
APPID> \
APPSECRET>
发送文件
方式一:用脚本(推荐)
bash
python3 skills/feishu-send-file/scripts/sendfile.py path> id> id> secret> [filename]
参数说明:
- - filepath:要发送的文件路径(HTML/PDF/ZIP/代码文件等)
- receiveid:接收者 ID,支持 ou...(私聊)或 oc...(群聊),脚本自动判断类型
- appid:飞书应用 ID(从 openclaw.json 的 channels.feishu.appId 读取)
- appsecret:飞书应用密钥(从 openclaw.json 的 channels.feishu.appSecret 读取)
- file_name:可选,自定义文件名(不填则用原文件名)
示例:
bash
发个人
python3 skills/feishu-send-file/scripts/send
file.py ./report.pdf ouxxx $APP
ID $APPSECRET
发群
python3 skills/feishu-send-file/scripts/send
file.py ./report.pdf ocxxx $APP
ID $APPSECRET
完整路径示例:
bash
python3 /root/.openclaw/workspace/skills/feishu-send-file/scripts/send_file.py \
/root/myfiles/report.html \
RECEIVEID> \
APPID> \
APPSECRET> \
report.html
方式二:手动两步
Step 1 - 上传文件:
bash
TOKEN=$(curl -s -X POST https://open.feishu.cn/open-apis/auth/v3/tenantaccesstoken/internal \
-H Content-Type: application/json \
-d {appid:ID>,appsecret:SECRET>} | python3 -c import json,sys; print(json.load(sys.stdin)[tenantaccesstoken]))
FILE_KEY=$(curl -s -X POST https://open.feishu.cn/open-apis/im/v1/files \
-H Authorization: Bearer $TOKEN \
-F file_type=stream \
-F file_name=<文件名> \
-F file=@<文件路径> | python3 -c import json,sys; print(json.load(sys.stdin)[data][file_key]))
Step 2 - 发送消息:
bash
curl -s -X POST https://open.feishu.cn/open-apis/im/v1/messages?receiveidtype=open_id \
-H Authorization: Bearer $TOKEN \
-H Content-Type: application/json \
-d {\receiveid\:\ID>\,\msgtype\:\file\,\content\:\{\\\filekey\\\:\\\$FILE_KEY\\\}\}
脚本底层逻辑说明
发送原理
飞书消息链路中,发送文件或图片的最佳方式是采用两步法:
- 1. 先上传:将本地文件上传到 im/v1/files 或 im/v1/images,获取持久化的 filekey 或 imagekey。
- 后发送:调用 im/v1/messages 接口,指定 msg_type 为 file 或 image 并携带对应的 Key。
直接传递本地路径字符串到消息接口通常会导致客户端只显示路径文本。本脚本通过自动化这两步流程,确保用户在飞书里实际看到图片本体或可预览的文件。
普通文件 vs 图片的链路区别
- - 普通文件:im/v1/files -> filekey -> msgtype=file
- 图片:im/v1/images -> imagekey -> msgtype=image
脚本会自动处理这些差异。
排查
- - 发送失败先看 code / msg
- 群发失败检查:机器人已入群 + sendmessage 权限 + 使用正确的 oc chatid
- oc... 误当 openid 发必定报错
- 不要把本地路径回显误判为发送成功
- 飞书 filetype 用 stream 适用于所有普通文件类型