--- name: lark-send-message-as-bot description: | 以 Bot 身份通过飞书发送消息和文件。支持两种目标: (1) 给个人用户发私聊消息(基于 user_id)[注意] ./vala_users_list.md中已经记录了vala全员的user_id,请首先查询这个文档! (2) 给群组发消息(基于 chat_id) 当 agent 需要主动推送消息、通知用户、向群组发送信息时使用。 触发场景:发消息、通知某人、推送到群、Bot 发消息、主动消息、发文件、发报表。 --- # 以 Bot 身份发送飞书消息和文件 ## 前置条件 - Bot 应用的凭证已配置在 `/root/.openclaw/credentials//config.json` - 目标用户必须在 Bot 应用的**可用范围**内(开发者后台配置) - 目标群必须已将 Bot 添加为群成员 ### Agent 凭证目录 | Agent | 凭证路径 | |-------|---------| | xiaoxi | `/root/.openclaw/credentials/xiaoxi/config.json` | | xiaoban | `/root/.openclaw/credentials/xiaoban/config.json` | | xiaobian | `/root/.openclaw/credentials/xiaobian/config.json` | | xiaokui | `/root/.openclaw/credentials/xiaokui/config.json` | | xiaoyan | `/root/.openclaw/credentials/xiaoyan/config.json` | --- ## 第一步:获取 tenant_access_token **所有发送操作前必须先获取 token**,token 有效期 2 小时,同一批操作复用即可: ```bash APP_ID=$(jq -r '.apps[0].appId' /root/.openclaw/credentials//config.json) APP_SECRET=$(jq -r '.apps[0].appSecret' /root/.openclaw/credentials//config.json) 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\"}" \ | jq -r '.tenant_access_token') ``` > ⚠️ 将 `` 替换为当前 agent 名称(xiaoxi / xiaoban / xiaokui 等) --- ## 发送文本消息 ### 给个人发消息(user_id) 使用 `receive_id_type=user_id`,`receive_id` 填 user_id(如 `4aagb443`): ```bash curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=user_id" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "receive_id": "", "msg_type": "text", "content": "{\"text\":\"消息内容\"}" }' ``` > 📋 user_id 查询:首先查阅 `./vala_users_list.md` 获取对应的 user_id ### 给群组发消息(chat_id) 使用 `receive_id_type=chat_id`,`receive_id` 填群 ID(如 `oc_xxx`): ```bash curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "receive_id": "", "msg_type": "text", "content": "{\"text\":\"消息内容\"}" }' ``` --- ## 发送文件 文件发送分两步:**先上传文件获取 file_key,再发送文件消息**。 ### 步骤一:上传文件 ```bash UPLOAD_RESP=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \ -H "Authorization: Bearer $TOKEN" \ -F "file_type=<类型>" \ -F "file_name=<显示文件名>" \ -F "file=@<本地文件路径>") FILE_KEY=$(echo "$UPLOAD_RESP" | jq -r '.data.file_key') ``` **file_type 对照表:** | file_type | 适用文件 | |-----------|---------| | `xls` | Excel 文件(.xlsx / .xls) | | `pdf` | PDF 文件 | | `doc` | Word 文档(.docx / .doc) | | `ppt` | PPT 演示文稿(.pptx / .ppt) | | `stream` | 其他任意格式文件(通用) | > ⚠️ `file_name` 是飞书消息中展示的文件名,可以是中文(如 `每周报表.xlsx`),会自动 URL 编码 ### 步骤二:发送文件消息 **发送给个人(user_id):** ```bash curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=user_id" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"receive_id\":\"\",\"msg_type\":\"file\",\"content\":\"{\\\"file_key\\\":\\\"${FILE_KEY}\\\"}\"}" ``` **发送给群组(chat_id):** ```bash curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"receive_id\":\"\",\"msg_type\":\"file\",\"content\":\"{\\\"file_key\\\":\\\"${FILE_KEY}\\\"}\"}" ``` --- ## 完整示例:发送 Excel 报表到群组 ```bash #!/bin/bash # 获取token APP_ID=$(jq -r '.apps[0].appId' /root/.openclaw/credentials//config.json) APP_SECRET=$(jq -r '.apps[0].appSecret' /root/.openclaw/credentials//config.json) 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\"}" \ | jq -r '.tenant_access_token') # 上传Excel FILE_KEY=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \ -H "Authorization: Bearer $TOKEN" \ -F "file_type=xls" \ -F "file_name=每周报表.xlsx" \ -F "file=@/tmp/report.xlsx" | jq -r '.data.file_key') if [ -z "$FILE_KEY" ] || [ "$FILE_KEY" = "null" ]; then echo "ERROR: 文件上传失败" exit 1 fi # 发送到群组 SEND_RESP=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"receive_id\":\"oc_xxx\",\"msg_type\":\"file\",\"content\":\"{\\\"file_key\\\":\\\"${FILE_KEY}\\\"}\"}") MSG_ID=$(echo "$SEND_RESP" | jq -r '.data.message_id') if [ -z "$MSG_ID" ] || [ "$MSG_ID" = "null" ]; then echo "ERROR: 消息发送失败: $(echo $SEND_RESP | jq -r '.msg')" exit 1 fi echo "发送成功: $MSG_ID" ``` --- ## 消息类型参考 | msg_type | content 格式 | 用途 | |----------|-------------|------| | `text` | `{"text":"纯文本"}` | 普通文本消息 | | `file` | `{"file_key":"file_v3_xxx"}` | 文件消息(需先上传) | | `post` | `{"zh_cn":{"title":"标题","content":[[{"tag":"text","text":"正文"}]]}}` | 富文本(支持@、链接、图片) | | `interactive` | 卡片 JSON | 消息卡片 | --- ## ID 类型说明 | ID 类型 | 格式 | 用途 | 获取方式 | |---------|------|------|---------| | `user_id` | 如 `4aagb443` | 给个人发消息 | 查阅 `./vala_users_list.md` | | `chat_id` | 如 `oc_xxx` | 给群组发消息 | `lark-cli im chats list` | > **重要:** 使用 `user_id`(租户级唯一标识),**不要使用** `open_id`(应用级标识,不同 Bot 看到的同一用户 open_id 不同)。 --- ## 常见错误 | 错误码 | 含义 | 解决方式 | |-------|------|---------| | 230013 | Bot 没有该用户的可用范围权限 | 在开发者后台将用户加入应用的可用范围 | | 230001 | Bot 不在目标群中 | 将 Bot 添加到目标群 | | 99992351 | 无效的 ID 格式 | 检查 receive_id_type 与 receive_id 是否匹配 | --- ## 安全规则 - 发送前必须确认用户意图,禁止未经确认自动发送 - 禁止在终端明文输出 `appSecret` 或 `accessToken` - `` 根据当前 agent 身份确定,参考上方凭证目录表