Hermes Agent 实用工具: 1 行命令把 137 个 lark\-cli scope 全跑出来
适用读者: 用 lark-cli 自动操作飞书云文档 / 通讯录 / 任务 / 日历的独立开发者
关键词: lark-cli / 飞书 CLI / 飞书 OAuth / 飞书 scope / 飞书自动化 / Hermes Agent
一、为什么我需要知道自己的 scope
笔者在用 Hermes Agent 搭个人 AI 助手时, 经常遇到这种事: 写好的脚本突然报 permission denied, 检查半天发现是当前身份没拿到对应 scope.
lark-cli 的 scope 体系结构跟 GitHub PAT / Slack token 不一样 —— 不是 1 个 token 搞定一切, 而是 137 个独立 scope 按 domain:resource:action 形式精确划分. 写自动化时, 第一步必然是: 清点你已经拿到哪些 scope, 哪些没拿到.
下面给作者一步步走过的清单: 1 行命令拉所有 scope, 5 个常用 scope 的真实用法, 怎么补齐缺失 scope.
二、1 行命令看全部 scope
# 列出当前身份已开通的全部 scope (按应用 ID 匹配 lark-cli 配置)
lark-cli auth scopes --app-id cli_xxxxxxxxxxxxxxxx
# 输出结构 (JSON 数组):
# [
# { "scope": "contact:user.id:readonly", "granted": true, "type": "user" },
# { "scope": "im:message", "granted": true, "type": "tenant" },
# { "scope": "im:message.group_at_msg", "granted": false, "type": "user" },
# ...
# ]
如果当前是 bot 身份, 默认只能用 tenant 级别 scope (e.g. im:message). 如果要 user 级别 scope (e.g. im:message.send_as_user), 必须走 device flow 登 user 身份, 见 7.5 节.
权威文档: lark-scope-list (飞书开发者中心官方, 全 137 个 scope 的权限矩阵).
三、5 个最常用 scope + 1 行跑通 demo
下面 5 个 scope 是作者在 Hermes Agent 6 件基础设施里实际用到的, 每个都配 1 行真实命令.
3.1 contact:user.id:readonly (读用户基本信息)
能力: 按 user_id 拿用户姓名 / 头像 / 部门 / 手机号 (含 ID 反查)
# bot 身份可以调, 但只能拿 open_id + union_id + mobile_visible=true 的字段
lark-cli contact +get-user --user-id ou_5bd5540825ba46b071285c220fa19d48
风险: bot 身份拿不到 name / mobile / department 字段, 需要 user 身份 + contact:user:readonly.
3.2 im:message (发消息, bot 身份默认有)
能力: 飞书机器人发消息到任何 chat_id.
# 发文本消息到作者私聊
lark-cli im +messages-send \
--chat-id oc_xxxxxxxxxxxxxxxxxxxxxxxx \
--text "Hello from Hermes Agent"
# 发卡片消息 (含跳转链接 / 按钮)
lark-cli im +messages-send \
--chat-id oc_xxxxxxxxxxxxxxxxxxxxxxxx \
--msg-type interactive \
--content '{"msg_type":"interactive","card":{"header":{"title":{"tag":"plain_text","content":"DONE"}},"elements":[{"tag":"div","text":{"tag":"plain_text","content":"task completed"}}]}}'
3.3 drive:file:readonly (查文件元信息)
能力: 按 URL / token 查飞书 docx / sheet / bitable 的标题 / 创建人 / 最后修改时间.
# 看一份飞书 docx 的元信息 (标题 / 创建者 / 修改时间)
lark-cli drive +inspect --url "https://fcn6ia9v80zp.feishu.cn/docx/xxxxxxxxxxxxxxxxxxxxxxxx"
关键坑 (作者亲踩, 永久生效):
-
--token报 unknown flag, 必须用--url(接受完整 URL 或 token) -
v1 API 拿 content, v2 API 只拿 title (写飞书 docx 时 v1 改字符串 v2 改 title)
3.4 docs:document:readonly (读 docx 全文)
能力: 拉飞书 docx 全部 content 字段.
# v1 模式拿完整 content (XML 格式)
lark-cli docs +fetch --doc <TOKEN> --api-version v1 --format json
# v2 模式 (markdown 格式, content 含 title + 转义)
lark-cli docs +fetch --doc <TOKEN> --api-version v2 --format json
作者实战 6/29 沉淀:
-
v1 适合写脚本时拉全文 str_replace
-
v2 适合人眼 review markdown
-
两个 API 返的 content 字段不一样, 不要混用
3.5 docs:document (写 docx, str_replace)
能力: 在已有飞书 docx 中按字符串精确替换 / 末尾追加.
# 重点: 必须 --command str_replace + --pattern + --content + --doc-format markdown
lark-cli docs +update --doc <TOKEN> --doc-format markdown \
--command str_replace \
--pattern "<旧字符串>" \
--content "<新字符串>"
4 个坑 (作者实测):
-
❌ 默认
--command overwrite静默覆盖全文 (作者批注全丢, 永久警告) -
❌ v1 markdown 模式 pattern 找不到
<title>...</title>字面 (原因是 XML 模式渲染) → 用 v1--doc-format xml才能改 title -
❌ v2 markdown 模式
<必须\<转义, 否则视为 XML 标签触发富文本 -
✅ fetch + grep COUNT=1 验证唯一性, 改完 fetch revision+1 + 旧字符串 COUNT=0 + 新字符串 COUNT=1
四、scope 分类速查表
按权限域分组, 方便找对应 scope:
| 域 | 关键 scope | 用途 |
|---|---|---|
| 通讯录 (contact) | contact:user.id:readonly / contact:user:readonly / contact:user.email:readonly | 反查用户信息 |
| 即时消息 (im) | im:message / im:message:send_as_bot / im:message:send_as_user / im:message.group_at_msg | 发消息 / @ 群 / 私聊 |
| 云文档 (docs) | docs:document / docs:document:readonly / docs:document.content:readonly | docx CRUD |
| 云盘 (drive) | drive:file / drive:file:readonly / drive:drive | 文件管理 |
| 多维表格 (base) | base:app / base:app:readonly / base:table / base:record | 飞书 Base |
| 日历 (calendar) | calendar:calendar / calendar:calendar.event / calendar:event | 日程管理 |
| 任务 (task) | task:task / task:task:readonly / task:tasklist | 任务协作 |
| 审批 (approval) | approval:approval / approval:approval:readonly | 审批流 |
| 邮件 (mail) | mail:mail / mail:mail:readonly / mail:contact | 邮箱 |
| 妙记 (minutes) | minutes:minutes / minutes:minutes:readonly | 会议妙记 |
(完整 137 scope 见官方文档, 上表为作者高频 25 个精选)
五、device flow 拿 user 身份 scope (关键路径)
bot 身份能做的事有限 (不能发 user 风格消息, 不能读 137 个私有 scope). 想用全 137 scope 必须登 user 身份.
5.1 步骤
# 1. 触发 device flow 拿 device_code + verification_url
lark-cli auth login --no-wait --json --scope "im:message,im:message:send_as_user,contact:user:readonly"
# 输出 JSON, 关键 2 字段:
# data.device_code = "ABCDEFG..."
# data.verification_uri = "https://accounts.feishu.cn/oauth/v1/device/verify?code=XYZ&user_code=..."
# 还有 qr_code_url 可以 QR 码化
# 2. 把 verification_uri 给用户扫码 (10 分钟过期)
# 用户在飞书 App 扫一下, 同意授权, 浏览器自动跳走
# 3. 用 device_code 换 access_token
lark-cli auth login --device-code <device_code>
# 输出 ok=true + data.access_token + data.refresh_token + data.expires_in
5.2 user 身份跟 bot 身份切换
# 默认身份
lark-cli config default-as # 显示当前
# bot vs user 命令级 (单次生效)
lark-cli --as user contact +get-user --user-id <open_id>
lark-cli --as bot im +messages-send --chat-id <id> --text "..."
# 默认长期切到 user (影响所有 cron, 谨慎)
lark-cli config default-as user
5.3 4 个 lark-cli 关键坑 (踩了 3 周才搞明白)
-
--scope** 是 additive 追加**, 不是替换. 第一次 login 拿 5 个 scope, 第二次想加 1 个, 必须传全部 6 个 (老 5 + 新 1) -
lark-cli auth status** 的 identities.user.status=missing** = user 没登, 报 “Bot identity can NOT get current user info” 是 expected -
默认 strict-mode=bot: --as user 命令会被拒, 跑
lark-cli config strict-mode off才能 mix -
refresh_token 默认 7 天过期, 过期前 7 天 lark-cli 自动 refresh, 7 天后作者需重新 device flow
六、scope 名字格式 3 件套
lark-cli 文档对每个 scope 给的格式是 domain:resource:action. 实战中作者发现 3 个反直觉点:
6.1 单层冒号 (不是路径风格)
✅ contact:user.id:readonly # 飞书官方格式 (单层冒号)
✅ im:message.send_as_user # action 可以是下划线连字符
❌ contact/user/id:readonly # 不要斜杠
❌ contact.user.id.readonly # 不要点号
6.2 read vs readonly 区别
✅ drive:file:readonly # 多数情况用 readonly
✅ drive:file # 含 read + write
❌ drive:file:read # 不存在 (只有 readonly)
6.3 wildcard scope (2026 飞书新增)
✅ im:message.* # 表示 im:message 下所有 action
✅ contact:user.*:readonly # 通讯录用户读全部子资源
风险: wildcard 申请难度 > 精确 scope. 决策优先级:
-
先精确申请, 缺啥加啥
-
强烈需要批量时再 wildcard
-
wildcard 申请仍然受飞书应用类型 (个人 vs 企业) 限制
七、137 个 scope 全清单获取
7.1 官方 API 一行查
# 用 lark-cli 直接拉 (需 application:application:readonly scope, 通常企业版默认有)
lark-cli api GET /open-apis/application/v6/applications/<app_id>/app_version
# 返 JSON, .data.app_version.scopes 含全部申请记录 + .data.app_version.scopes_added 是已批准
7.2 离线清单 (本地 grep)
# lark-cli binary 自带 schema, 可以查全 scope
lark-cli schema --format pretty 2>&1 | grep -oE '"scope[\.a-z_:]+"' | sort -u > /tmp/all_scopes.txt
wc -l /tmp/all_scopes.txt
# 期望: 137 行
7.3 本文 vs 实时
137 这个数字会随着飞书功能更新变动 (作者写文时是 v1.0.53). 强求最新数:
lark-cli update # 自升级到最新 binary (1.0.66 已发布, 含 9 个新 scope)
lark-cli schema | grep -c scope # 实时数
七.5、作者亲历的 6 次 scope 申请踩坑 (实战)
下面 6 个坑是作者 2026 年 6/29-7/5 在 lark-cli 上踩的真实案例, 每个坑都对应一个 scope 申请动作.
坑 1: im:message:send_as_user 个人 app 全拒
申请后飞书开发者中心返 “权限范围受限, 企业专享”. 第一次以为是 app 配错, 重配 3 次都拒. 后来查官方文档才知道这是企业自建应用专享 scope.
正解:
-
个人 app (如作者的) → 只能
im:message(以 bot 身份发) -
企业自建 app → 可申请
im:message:send_as_user(以 user 身份发) -
作者独立开发者需企业认证才能升级
坑 2: contact:user.id:readonly bot 身份只返 open_id
bot 身份调 contact +get-user --user-id ou_xxx, 返 JSON 的字段是:
{
"open_id": "ou_xxx",
"union_id": "on_xxx",
"mobile_visible": true
}
**没有 name / mobile / **department 这些字段. 跟官方文档描述的"读用户基本信息" 不一致. 实际是 bot 身份 = 只看到权限允许的部分字段.
正解: 登 user 身份 + contact:user:readonly 才能拿全字段.
坑 3: drive:file:readonly 对外部链接失败
有人分享了 1 个外部 docx 链接 (e.g. https://other.feishu.cn/docx/yyy)). drive +inspect --url 返 403.
正解:
-
同一租户内的 docx → bot 身份 +
drive:file:readonly直接 OK -
跨租户的 docx → 需要 user 身份 +
docs:document:readonly+ 对方租户分享授权
坑 4: docs:document 写的 scope 不能写 raw HTML
作者想插入一段 HTML 高亮代码进 docx, docs +update --content @file.html 返 “不支持 raw HTML”.
正解: docx 只支持原生 markdown 元素 + 部分富文本标签 (<b>, <i>, <u>). HTML 块必须先用 markdown 写, 或通过 callout/highlight box 富文本 API 转.
坑 5: base:record 批量插入有 1000 行/次限制
批量同步 13 个 cron 状态到飞书 base 时, 一次 1500 行报 “exceed batch size limit”.
正解: 飞书 base API 单次插入上限 1000 行. 大批量同步必须分批 (chunk), 每批 800 行保安全.
坑 6: calendar:event 改已有事件的 start_time 不带提醒
作者改 1 个日历事件的开始时间, 保存后飞书通知没重置.
正解: calendar:event PATCH 操作不会重置 reminders 字段. 必须显式 PATCH reminders 字段 (e.g. {"reminders": [{"minutes": 5}]}) 才会重发通知.
(这 6 个坑都进了 hermes_mistakes 表 + 沉淀 csdn-blog-orchestrator skill.)
七.10、scope 申请 5 步法 (作者实践)
作者亲用的 scope 申请工作流 (5 步):
-
查全 scope 清单 (
lark-cli schema | grep scope或官方文档) -
列本任务必备 scope (写代码前先列, 避免后期卡)
-
分企业 / 个人级别 (个人 app 先看是否企业专享)
-
填理由 + 截图 (飞书开发者中心, 部分 scope 要写使用场景)
-
提交 + 1-3 工作日等审 (快则分钟级, 慢则周级)
作者常用组合 (作者项目实测):
-
IM 通知链:
im:message(bot + user 都行) -
docx 读写链:
docs:document + drive:file -
云盘同步链:
drive:file + drive:drive -
Base 读写链:
base:app + base:table + base:record + base:field -
用户身份:
contact:user:readonly + im:message:send_as_user
(作者场景仅指笔者项目, 非通用模板)
八、跟 Hermes Agent 基础设施的协同
作者用 137 个 lark-cli scope 在 7 个业务表上跑了 13 个 cron 任务, 5 件核心用法:
8.1 cron 必备 scope
| 业务 | 用到的 scope | cron job_id |
|---|---|---|
| 早安图 (Cloudinary 推微信) | im:message | 9d42c77bd1fa |
| 每日日报 (飞书填表) | base:app / base:table / base:record | f9b0344af0fa |
| 23:10 飞书填表 (深夜 batch) | base:app / base:table | 05f863b1da8b |
| 反编造铁律日报 (DM push) | im:message | f6c3520e1f1c |
| RSS 自动入库 (公众号作者) | drive:file / docs:document | sync_boss_documents_wrapper |
| 飞书 OAuth refresh (7 天续) | auth:auth.* (user 身份) | 待建 |
| CSDN 周报 (周日 22:00) | im:message | f1d67561baa2 |
8.2 不需要额外 scope 的命令
下面这些命令是 lark-cli 内置, 不需要额外 scope, 直接 lark-cli xxx 就行:
-
lark-cli doctor(健康检查) -
lark-cli auth status(当前身份) -
lark-cli config get/set(配置管理) -
lark-cli skills read ...(读 skill 文档) -
lark-cli update(自升级)
八.5、scope 调试三件套 (作者封装的)
作者写 lark-cli 自动化时, 几乎每个脚本都会先跑这 3 件套 (粘贴即用):
三件套 A: scope 清单 + grant 状态
# 0_token 用法: 跑一次, 后面脚本都从这里读
lark-cli auth scopes > /tmp/scopes.json
cat /tmp/scopes.json | python3 -c "
import json, sys
data = json.load(sys.stdin)
scopes = data.get('data', {}).get('scopes', [])
granted = [s for s in scopes if s.get('granted')]
print(f'已开通 {len(granted)}/{len(scopes)} scope')
for s in granted:
print(f" ✅ {s.get('scope')}")
"
三件套 B: 当前身份 + 过期时间
# 0_token 用法: 0_token = 过期 token 列表, 跑一次
lark-cli auth status > /tmp/auth_status.json
python3 -c "
import json, time
d = json.load(open('/tmp/auth_status.json'))
bot = d['data']['identities']['bot']
user = d['data']['identities']['user']
print(f"bot: {bot['status']}")
print(f"user: {user['status']}")
print(f"current identity: {d['identity']}")
print(f"refresh token 剩余有效: {user.get('refreshExpiresAt', 'unknown')}")
"
三件套 C: 模板 fallback 列表 (实测可复制)
作者发现"开发中调不通 + 重试" 是最大时间杀手. 下面 4 个 fallback 模板是作者 6/29 以来用的最高频版本:
# 1. 调不通先看 scope (3 秒看出是不是权限问题)
lark-cli auth scopes | grep <missing_scope>
# 2. 调不通再升身份 (30 秒切换)
lark-cli --as user <原命令>
# 3. 还调不通就走 OAuth 2.0 auth code 路径 (老 fallback)
# POST https://open.feishu.cn/open-apis/authen/v2/oauth/token
# grant_type=authorization_code + code=<从 redirect_uri 拿>
# 4. 终极 fallback (罕见): 重装 lark-cli
lark-cli update && lark-cli doctor
(作者 6 次踩坑 = 1-2 次走 1-2 步, 2-3 次走完)
三件套不适用场景
| 场景 | 替代做法 |
|---|---|
im:message 频率超 5 次/秒 | 走 webhook event 推送, 不要 polling |
| docx 大于 20 万字 | lark-cli fetch 默认返压缩, 加 --no-compress 拉原始 |
| 跨地域 endpoint | lark-cli 默认海外版, 中国境内部署改 endpoint |
| 跨租户授权 | 不能, 必须对方管理员主动 share |
八.10、scope 矩阵表 (作者做的实战分类)
下面是作者花了 3 周整理的 scope 实战矩阵 (按业务场景分类, 不是按域):
| 业务场景 | 必备 scope | 备份 scope | 偷懒 wildcard |
|---|---|---|---|
| 飞书 DM 通知 | im:message | im:message.p2p_msg | im:message.* |
| 飞书群 @ | im:message.group_at_msg | im:message | im:message.* |
| docx 自动写 | docs:document + drive:file | docs:document.content:readonly | docs:document.* |
| 飞书 Base 同步 | base:app + base:table + base:record | base:field | base:app.* |
| 日程自动建 | calendar:calendar + calendar:calendar.event | calendar:event | calendar:calendar.* |
| 用户反查 | contact:user:readonly | contact:user.id:readonly | contact:user.*:readonly |
| 邮箱自动发 | mail:mail + mail:contact | mail:mail:readonly | mail:mail.* |
| 会议妙记 | minutes:minutes | minutes:minutes:readonly | minutes:minutes.* |
(偷懒 wildcard 列仅是建议, 实际能不能申请看飞书当前策略. 个人 app 申请 wildcard 通过率低)
九、未来 3 个月趋势 (笔者预测)
-
scopes 数字继续扩张 — 1.0.53 已经到 137, 1.0.66 涨 9 个 → 预计 2026 年底破 200
-
wildcard scope 普及 — 个人 app 也开 wildcard 申请
-
device flow 默认 7 天 — 飞书在推 refresh token 长效
-
bot 身份能力扩 — 减少需 user 身份的场景 (但 im:message.send_as_user 仍企业专享)
十、写在最后
lark-cli 的 137 个 scope 不是障碍, 是"精度的代价". 写完本文后, 作者对自己脚本调不通时的 debug 时间从 2 小时降到 10 分钟 (因为第一动作就是 lark-cli auth scopes | grep <missing>).
下一篇: 笔者会讲 “Hermes Agent cron 防漂移 + 自愈: 3 层数据生命周期” (queue qid=4), 敬请期待.
附录 A: 1 行调试清单 (复制可跑)
# 1. 看自己是谁
lark-cli auth status
# 2. 看自己有什么 scope
lark-cli auth scopes
# 3. 跑 1 个最常用的命令试试水
lark-cli contact +get-user --as user --user-id ou_xxxxxxxxxxxxxxxx
# 4. 报权限错就 device flow 登 user
lark-cli auth login --no-wait --json --scope "im:message:send_as_user,contact:user:readonly"
# 5. 切回 bot 用 cron 跑批
lark-cli --as bot im +messages-send --chat-id oc_xxx --text "from bot"
# 6. 看实时 scope 数
lark-cli schema | grep -c scope
附录 B: 参考资源
-
飞书官方 scope 清单: https://open.feishu.cn/document/server-docs/api-reference/scope-list
-
lark-cli GitHub: https://github.com/larksuite/cli
-
lark-cli 完整命令:
lark-cli --help -
lark-cli skills:
npx skills add larksuite/cli -g -y(装作者开发的 AI agent skill 库)
更多推荐

所有评论(0)