直接通过飞书开放平台 API 发送图片(绕过 OpenClaw 插件的限制),而非以文件附件形式发送。使用场景:需要发送截图、二维码等图片给用户时。
---
name: feishu-image-sender
description: 直接通过飞书开放平台 API 发送图片(绕过 OpenClaw 插件的限制),而非以文件附件形式发送。使用场景:需要发送截图、二维码等图片给用户时。
---
# feishu-image-sender
通过飞书开放平台 API 直接发送图片到用户,图片以内嵌方式显示,而非文件附件。
## 核心逻辑
两步走:
1. 上传图片到飞书服务器,获取 `image_key`
2. 用 `image_key` 发一条 image 类型消息
## 操作步骤
### 第一步:获取 Access Token
```bash
curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
-H "Content-Type: application/json" \
-d '{"app_id":"<APP_ID>","app_secret":"<APP_SECRET>"}'
```
响应:`{"code":0,"tenant_access_token":"t-xxx","expire":3339}`
记录返回的 `tenant_access_token`。
### 第二步:上传图片
```bash
curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/images" \
-H "Authorization: Bearer <tenant_access_token>" \
-F "image_type=message" \
-F "image=@/path/to/image.png"
```
响应:`{"code":0,"data":{"image_key":"img_v3_xxx"},"msg":"success"}`
记录返回的 `image_key`。
### 第三步:发送图片消息
```bash
curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
-H "Authorization: Bearer <tenant_access_token>" \
-H "Content-Type: application/json" \
-d '{
"receive_id": "<open_id>",
"msg_type": "image",
"content": "{\"image_key\":\"<image_key>\"}"
}'
```
`receive_id` 可选 `open_id`(用户唯标识)、`chat_id`(群会话)、`user_id`、`union_id`。
响应成功:`{"code":0,"data":{"message_id":"om_xxx",...}}`
## 完整示例(单次执行)
```bash
#!/bin/bash
# 参数
IMAGE_PATH="$1"
OPEN_ID="$2"
APP_ID="cli_a924632610b8dbd9"
APP_SECRET="c3TXscIJPF1f8jcQ4mJJegNVk72ktbwK"
# 1. 获取 token
TOKEN=$(curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
-H "Content-Type: application/json" \
-d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" | \
python3 -c "import sys,json; print(json.load(sys.stdin)['tenant_access_token'])")
# 2. 上传图片
IMAGE_KEY=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/images" \
-H "Authorization: Bearer $TOKEN" \
-F "image_type=message" \
-F "image=@$IMAGE_PATH" | \
python3 -c "import sys,json; print(json.load(sys.stdin)['data']['image_key'])")
# 3. 发送图片
curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"receive_id\":\"$OPEN_ID\",\"msg_type\":\"image\",\"content\":\"{\\\"image_key\\\":\\\"$IMAGE_KEY\\\"}\"}"
echo "Done: $IMAGE_KEY"
```
## 工具调用封装(Node.js)
```javascript
const fs = require('fs');
const path = require('path');
async function feishuSendImage(imagePath, openId, appId, appSecret) {
// 1. get token
const tokenRes = await fetch('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ app_id: appId, app_secret: appSecret })
});
const { tenant_access_token } = await tokenRes.json();
// 2. upload image
const imageBuffer = fs.readFileSync(imagePath);
const uploadRes = await fetch('https://open.feishu.cn/open-apis/im/v1/images', {
method: 'POST',
headers: { 'Authorization': `Bearer ${tenant_access_token}` },
body: (() => {
const form = new FormData();
form.append('image_type', 'message');
form.append('image', new Blob([imageBuffer]), path.basename(imagePath));
return form;
})()
});
const { data: { image_key } } = await uploadRes.json();
// 3. send image message
const sendRes = await fetch(`https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${tenant_access_token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
receive_id: openId,
msg_type: 'image',
content: JSON.stringify({ image_key })
})
});
return sendRes.json();
}
```
## 限制与注意事项
- 图片大小限制:每个文件最大 30MB
- 支持格式:jpg、png、gif、webp、bmp、heic
- token 有效期 2 小时,超时需重新获取
- `receive_id_type` 必须与 `receive_id` 匹配(open_id / user_id / chat_id / union_id)
- 图片消息不能通过 web 预览,必须是桌面端或手机端才能直接查看
don't have the plugin yet? install it then click "run inline in claude" again.
restructured into implexa's 6-component format, added explicit decision points for credential validation, file size limits, format checks, and token expiry, detailed error handling and retry logic, specified output contracts with both success and failure json schemas, and clarified outcome signals including platform-specific rendering behavior.
send images directly to feishu users via open platform api. images render inline, not as file attachments. use this when you need to push screenshots, qr codes, or other images into a feishu chat without going through the openclaw plugin layer.
this skill uploads an image to feishu's servers and sends it as an embedded message to a user, group, or chat. the image renders natively in feishu clients instead of appearing as a downloadable file. deploy this when you're generating screenshots, qr codes, or other visual assets on the fly and need to get them in front of a feishu user without friction. the skill bypasses openclaw's file attachment constraints by hitting the feishu api directly.
feishu app credentials (required):
APP_ID: feishu app id. set via env var FEISHU_APP_ID or pass inline.APP_SECRET: feishu app secret. set via env var FEISHU_APP_SECRET or pass inline. treat as sensitive; never log it.image file (required):
IMAGE_PATH: absolute or relative path to the image file on disk.recipient identifier (required):
RECEIVE_ID: the feishu user, group, or chat id.RECEIVE_ID_TYPE: one of open_id, user_id, chat_id, union_id. must match the type of RECEIVE_ID.network requirements:
open.feishu.cn must be open (firewall, vpc, proxy rules).open.feishu.cn must succeed.fetch tenant access token
APP_ID, APP_SECRET.https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal with json body {"app_id":"<APP_ID>","app_secret":"<APP_SECRET>"}.tenant_access_token (string) and expire (seconds, typically 3339 = ~55 min). store tenant_access_token in memory for steps 2 and 3.upload image to feishu
IMAGE_PATH, tenant_access_token from step 1.https://open.feishu.cn/open-apis/im/v1/images. include headers: Authorization: Bearer <tenant_access_token>, Content-Type: multipart/form-data. form fields: image_type=message, image=<binary file content>.IMAGE_PATH exists, is readable, and is <= 30 mb. confirm mime type matches one of the supported formats. if validation fails, return descriptive error without attempting upload.data.image_key (string, e.g., img_v3_xxx). store image_key for step 3.send image message
tenant_access_token from step 1, image_key from step 2, RECEIVE_ID, RECEIVE_ID_TYPE.https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=<RECEIVE_ID_TYPE>. headers: Authorization: Bearer <tenant_access_token>, Content-Type: application/json. json body: {"receive_id":"<RECEIVE_ID>","msg_type":"image","content":"{\"image_key\":\"<image_key>\"}"}.data.message_id (string, e.g., om_xxx). message_id confirms delivery to feishu backend.if credentials are missing:
APP_ID or APP_SECRET env vars are not set and no inline credentials provided, return error stating "feishu app credentials required: set FEISHU_APP_ID and FEISHU_APP_SECRET or pass inline". do not attempt api call.if image file does not exist:
if image file exceeds 30 mb:
if image format is unsupported:
if access token fetch fails:
if image upload returns success but image_key is missing or malformed:
if image message send returns success but receive_id_type does not match receive_id:
open_id as receive_id but receive_id_type is user_id, feishu will reject with code non-zero. return error early: "receive_id_type if token expires during execution (< 1 minute remaining):
if network timeout occurs:
success case:
{"status":"success","message_id":"om_xxx","image_key":"img_v3_xxx","recipient":"<RECEIVE_ID>"}.message_id proves the message reached feishu backend. the image will render inline in the target chat within 1-2 seconds.failure case:
{"status":"error","code":<numeric_error_code>,"message":"<human_readable_error>","step":<step_number>}.{"status":"error","code":400,"message":"image exceeds 30 mb limit","step":2}.file location:
the skill worked if:
message_id.you know it failed if: