lark-identify-sender.xiaokui/SKILL.md
2026-04-10 19:54:04 +08:00

5.3 KiB
Raw Blame History

name description
lark-identify-sender 识别飞书对话中消息发送者的身份。当你收到飞书用户的消息时,使用此技能获取对方的 user_id 和真实姓名, 以便进行身份识别和权限判断。 触发场景:需要知道对面是谁、身份识别、权限检查、用户鉴权。

识别飞书消息发送者身份

核心概念

飞书有三种用户 ID

ID 类型 格式特征 作用域 适合做身份识别?
user_id 短字符串,如 cb2815b4 租户级唯一,所有 bot 通用 推荐
open_id ou_ 开头 应用级,不同 bot 看到不同值 不推荐跨应用使用
union_id on_ 开头 同一开发者下所有应用通用 ⚠️ 可用但不如 user_id 直接

结论:始终使用 user_id 作为身份标识。

方法一:查询已有用户列表(首选)

公司全员的 user_id 已记录在 /root/.openclaw/skills/lark-send-message-as-bot/vala_users_list.md

如果你已经知道对方姓名,直接查表获取 user_id

cat /root/.openclaw/skills/lark-send-message-as-bot/vala_users_list.md

方法二:通过飞书 API 用 user_id 查真实姓名

前置条件

  • Bot 应用需要有 contact:user.base:readonly 权限(在飞书开发者后台开通)
  • Bot 凭证已配置在 /root/.openclaw/credentials/<agent_name>/config.json

步骤

1. 获取 tenant_access_token

APP_ID=$(jq -r '.apps[0].appId' /root/.openclaw/credentials/<agent_name>/config.json)
APP_SECRET=$(jq -r '.apps[0].appSecret' /root/.openclaw/credentials/<agent_name>/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')

2. 用 user_id 查询用户信息

USER_ID="<目标user_id>"

curl -s -X GET "https://open.feishu.cn/open-apis/contact/v3/users/${USER_ID}?user_id_type=user_id" \
  -H "Authorization: Bearer $TOKEN" \
  | jq '.data.user | {name, en_name, department_ids}'

返回示例:

{
  "name": "刘庆逊",
  "en_name": "Liu Qingxun",
  "department_ids": ["od-xxxxx"]
}

3. 用 open_id 查询用户信息(如果只有 open_id

OPEN_ID="ou_xxxxxxxx"

curl -s -X GET "https://open.feishu.cn/open-apis/contact/v3/users/${OPEN_ID}?user_id_type=open_id" \
  -H "Authorization: Bearer $TOKEN" \
  | jq '.data.user | {name, user_id, open_id}'

这样可以从 open_id 反查 user_id 和姓名。

方法三:从收到的消息事件中提取发送者

当你通过飞书 bot 收到消息时,消息事件 JSON 中已包含发送者信息:

{
  "sender": {
    "sender_id": {
      "open_id": "ou_xxxx",
      "user_id": "cb2815b4",
      "union_id": "on_xxxx"
    },
    "sender_type": "user",
    "tenant_key": "xxx"
  },
  "message": {
    "message_id": "om_xxxx",
    "chat_type": "p2p",
    "content": "{\"text\":\"你好\"}",
    ...
  }
}

从中直接取 sender.sender_id.user_id 即可。

如何拿到事件中的 user_id

飞书事件推送是否包含 user_id 取决于应用权限:

  • contact:user.id:readonly 权限 → 事件中会包含 user_id 字段
  • 没有该权限 → 事件中只有 open_id,需要调 API 转换(见方法二第 3 步)

重要: 如果你发现事件中 user_id 为空,请联系管理员在飞书开发者后台为 bot 应用开通 contact:user.id:readonly 权限。

方法四:通过 lark-cli 查询群成员获取 user_id

LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/<agent_name> \
  lark-cli im chat.members get \
  --params '{"chat_id":"<群的chat_id>","member_id_type":"user_id"}' \
  --as bot

返回结果中 member_id 即为 user_id

身份识别实战流程

当你收到一条飞书消息需要判断对方身份时:

1. 检查消息中是否已带有发送者姓名(系统通常会在消息前加上 "姓名: 消息内容"
   → 如果有,直接使用

2. 如果没有姓名,检查是否有 user_id
   → 如果有,查 vala_users_list.md 对照表
   → 如果表中没有,调 contact API 查询(方法二)

3. 如果只有 open_id以 ou_ 开头)
   → 调 contact API 用 open_id 查 user_id 和姓名(方法二第 3 步)

4. 拿到 user_id 后,可用于权限判断

权限分级参考

可在 agent 配置中维护权限表,基于 user_id 进行分级:

{
  "access_levels": {
    "admin": ["cb2815b4", "1da2afbf"],
    "editor": ["2c856846", "63943ebf", "8g42f9b4"],
    "viewer": ["*"]
  }
}

所有 bot 共用同一份 user_id 权限表,无需为每个 bot 单独维护。

常见问题

问题 原因 解决方式
事件中 user_id 为空 缺少 contact:user.id:readonly 权限 在开发者后台开通
调 contact API 返回 99991672 缺少 contact:user.base:readonly 权限 在开发者后台开通
不同 bot 拿到的 open_id 不同 正常行为open_id 是应用级的 改用 user_id

安全规则

  • 禁止在终端明文输出 appSecretaccessToken
  • <agent_name> 根据当前 agent 身份确定(如 xiaokui、xiaoxi、xiaoban、xiaobian 等)