先看结论
lark-cli不是简单把飞书 API 包一层命令,而是把复杂 SaaS 平台拆成三种 CLI 能力:
- 资源 API:把平台 OpenAPI 元数据映射成
service resource method,用于结构化覆盖。 - Raw API:保留
HTTP method + OpenAPI path的兜底入口,用于覆盖长尾接口。 - Shortcut:把高频、易错、多步骤的用户任务封装成
service +verb,用于提高人和 Agent 的成功率。
这三层不是互相替代,而是分工:
Shortcut:面向用户意图,成功率最高 资源 API:面向平台对象,结构化覆盖 Raw API:面向 HTTP OpenAPI,长尾兜底从资源和动作说起
做平台 CLI 时,第一步不是写命令,而是先定义两类东西:
- 资源:平台中可被操作的业务对象,例如日历事件、云盘文件、消息、任务、权限成员、知识库节点。
- 动作:资源上可发生的操作,例如
create、get、list、patch、delete、copy、forward、transfer_owner。
飞书的资源 API 大体按这个结构展开:
service = 业务域 resource = 业务对象 method = 对象动作例子:
calendar.events.create calendar.events.delete calendar.events.instance_view drive.files.list drive.files.copy drive.permission.members.create im.chats.create im.messages.delete im.reactions.create task.tasks.create task.tasks.patch task.subtasks.create这些动作可以粗略归类:
- 读:
get、list、search、batch_query、instance_view - 写:
create、patch、update、delete - 关系:
add_members、remove_members、transfer_owner - 执行:
send、forward、approve、reject、urgent - 媒体:
upload、download、export、import - 观察:
status、statistics、view_records、quota
注意:平台对象不一定都能统一成标准 CRUD。比如im.messages.forward是执行动作,drive.permission.members.transfer_owner是关系迁移,calendar.events.instance_view是视图查询。
资源 API
资源 API 是从平台 metadata 自动注册出来的结构化命令。
形态:
lark-cli<service><resource><method>--params'{}'--data'{}'真实例子:
lark-cli task tasks create--data'{...}'lark-cli drive files list--params'{...}'lark-cli calendar events instance_view--params'{...}'代码上,lark-cli会遍历 metadata 中的services -> resources -> methods,并注册成命令:
- 命令树注册入口:service.go:L32-L48
- resource/method 注册逻辑:service.go:L78-L100
资源 API 的价值:
- 覆盖平台对象能力。
- 参数、scope、risk 可以通过 schema 查询。
- 比 Raw API 更结构化。
- 比 Shortcut 更接近底层平台能力。
但资源 API 不一定覆盖所有业务域。比如docs文档域就没有暴露docs documents create这种资源命令。
Raw API
Raw API 基本就是通过 CLI 直接发飞书 HTTP OpenAPI。
形态:
lark-cli api GET /open-apis/calendar/v4/calendars lark-cli api POST /open-apis/im/v1/messages--params'{...}'--data'{...}'它看起来像curl,但不是裸curl。它仍然经过lark-cli的统一运行时:
- 自动处理
user/bot身份。 - 自动获取和刷新 token。
- 自动拼接飞书 OpenAPI base URL。
- 支持
--params、--data、--file、stdin、@file。 - 支持
--dry-run。 - 支持统一 JSON 输出。
- 支持统一错误、权限 hint、scope 修复建议。
所以 Raw API 的本质是:
HTTP 的表达自由 + CLI 的认证、安全、输出、错误协议为什么不只让 Skill 描述接口?
- Skill 可以告诉 Agent “这个接口做什么、参数怎么填”。
- 但 Skill 不能负责 token、身份、权限、输出 envelope、文件上传、dry-run、错误恢复。
- 这些必须由 CLI runtime 承担。
因此 Raw API 仍然值得抽象成 CLI:它不是为了重新发明 HTTP,而是为了让 HTTP 调用进入统一、安全、可恢复的执行协议。
Shortcut
Shortcut 是用户任务级命令,不是 API 级命令。
形态:
lark-cli<service>+<verb>[flags]例子:
lark-cli docs +create --api-version v2--content'<title>报告</title>'lark-cli docs +fetch --api-version v2--doc'<url>'--detailwith-ids lark-cli docs +update --api-version v2--doc'<url>'--commandappend--content'<p>补充内容</p>'Shortcut 的判断标准:
- 用户经常说的是这个任务,而不是底层 API。
- 直接调 API 容易错。
- 需要处理格式、权限、默认值、状态锚点。
- 可能是多步骤编排。
- 输出会被后续步骤继续使用。
docs +create是典型例子。它不是资源命令层的docs documents create,而是一个 Shortcut,底层直接调用:
POST /open-apis/docs_ai/v1/documents相关代码:
docs +create调用 create API:docs_create_v2.go:L48-L74docs +fetch调用 fetch API:docs_fetch_v2.go:L63-L81docs +update调用 update API:docs_update_v2.go:L124-L170
为什么文档域主要做 Shortcut?
- 文档创建和编辑不是简单 CRUD。
- 它涉及 XML / Markdown、标题、block id、revision、资源块、bot 创建后的用户权限、长文档分段写入。
- 如果只暴露底层 API,Agent 仍然要猜很多业务规则。
- 所以
lark-cli把文档能力产品化成docs +create/+fetch/+update。
三层关系
使用顺序可以理解为:
优先 Shortcut:任务更明确,成功率最高 没有 Shortcut:用资源 API,结构化调用平台对象 还不够:用 Raw API,直接访问长尾 OpenAPIlark-cli 的 SKILL 怎么设计
lark-cli的 Skill 不是再造一层 API,而是把“怎么正确调用 CLI”写成可执行说明。
它大体做三件事:
- 先做意图路由:先判断这是文档、消息、日历还是云盘问题。
- 优先走 Shortcut:有高频任务封装时,先用
+create、+fetch、+update这类成功率更高的命令。 - 必要时下探:Shortcut 不够,再落到资源 API,最后才用 Raw API 兜底。
所以lark-cli的 Skill 设计重点,不是描述“某个 HTTP 接口怎么调”,而是描述:
- 这个任务应该选哪个 domain。
- 先查什么 schema 或参考。
- 优先用哪个 Shortcut。
- 什么情况下切到资源 API 或 Raw API。
- 遇到身份、权限、scope 问题时怎么修复。
可以把它理解成:Skill 负责任务路由和调用策略,CLI runtime 负责真正执行。
CLI 的公共运行时
三层命令最终都应该经过同一个运行时,而不是各自处理认证和输出。
lark-cli的公共能力包括:
config:配置应用、品牌、profile。auth:登录、登出、状态、scope 检查。--as:显式选择user或bot身份。schema:查看资源 API 的参数、响应、scope、risk。--dry-run:只构造请求,不执行副作用。risk / --yes:高风险操作确认。--format / --jq:人和机器都可消费的输出。--file / @file / -:统一文件和 stdin 输入。- JSON envelope:统一成功输出。
- typed error + hint:统一失败恢复建议。
这就是 CLI 的真正价值:不只是多了一种调用方式,而是提供一个 Agent 可依赖的执行协议。
产品转 CLI 的方法
1. 抽资源 API
先从平台对象出发,形成结构化命令:
platform-cli <domain> <resource> <method>适合自动生成:
- 来自 OpenAPI / RPC / IDL / metadata。
- 保持和平台接口一致。
- 用 schema 保证参数可查询。
- 用统一 runtime 处理身份、权限、输出、错误。
2. 抽 Shortcut
再从真实任务出发,形成意图命令:
platform-cli <domain> +<intent>适合人工设计:
- 高频任务。
- 多参数易错。
- 多步骤编排。
- 需要默认值和业务兜底。
- 需要返回后续可用的状态锚点。
例子:
workflow +debug-smoke doc +create-report env +deploy-current3. 保留 Raw API
最后保留兜底入口:
platform-cli api <method> <path>适合长尾能力:
- 新接口还没生成资源命令。
- 没有必要设计 Shortcut。
- Agent 或开发者知道具体 endpoint。
- 仍然需要 CLI runtime 的认证、安全和输出协议。
最值得复制的模式
- Narrow Waist:所有命令经过同一套 runtime。
- Progressive Disclosure:常用走 Shortcut,不够用走资源 API,再不够用走 Raw API。
- Agent Contract First:stdout、stderr、exit code、JSON envelope、hint、risk 都是协议。
- Schema Before Action:不熟悉的接口先查 schema,再执行。
- Dry-run First:副作用操作先预览请求,再执行。
- Stateful Outputs:每次操作返回下一步需要的 ID、URL、revision、log_id、rollback token。
一句话总结
把一个产品转成 CLI,不是把按钮翻译成命令,而是把平台能力拆成三层:
资源 API 保证覆盖率 Raw API 保证长尾不断供 Shortcut 保证真实任务的成功率真正的核心,是让三层都进入同一个认证、安全、输出和错误恢复协议。