飞书 IM 领域建模与 lark-cli 实战指南核心概念、身份映射与消息增强契约【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200 commands and 20 AI Agent Skills.项目地址: https://gitcode.com/gh_mirrors/cli414/cli本文以 lark-cliLark/飞书官方 CLI 工具由 larksuite 团队维护面向人类与 AI Agent内置的 IM 领域文档skill-template/domains/im.md为骨架系统梳理飞书即时通讯领域的数据模型、资源关系与关键使用约束并结合仓库中的 SKILL 文档与源码实现skills/lark-im/、shortcuts/im/进行纵深展开。读完本文你将掌握 Message/Chat/Thread/Reaction/Flag/Feed 等核心对象的 ID 规则与层级关系理解--as user与--as bot两种身份对权限语义的根本影响以及 lark-cli 在拉取消息时默认附带的 reactions / update_time 富化、可选的资源自动下载、发送者名称解析等关键契约——这些知识是安全、正确地调用lark-cli im系列命令含前缀 Shortcut的前提。一、领域核心概念Core Conceptslark-cli 将飞书 IM 域抽象为一组带明确 ID 前缀和语义的对象。理解这些对象是使用任何 im 命令的第一步它们直接决定了参数取值与输出结构。概念说明ID 形态Message聊天中的单条消息message_id标识om_xxxChat群聊或单聊P2P会话chat_id标识oc_xxxThread消息下的回复话题reply threadthread_id标识om_xxx或omt_xxxReaction消息上的表情回复—Flag消息或话题上的书签bookmark—Feed Shortcut置顶到当前用户 Feed 侧边栏的会话feed_card_id标识CHAT 类型即oc_xxxopen_chat_idoc_xxxCHAT 类型Feed Group对 Feed 卡片分组的标签feed_group_id标识成员为 Feed 卡片由feed_idfeed_type标识分normal显式管理成员与rule按规则自动派生成员两种类型ofg_xxx消息类型msg_type覆盖面很广text、post富文本、image、file、audio、video、sticker、interactive卡片、share_chat、share_user、merge_forward合并转发等。从源码看这些对象被组织在shortcuts/im/下的各个命令实现中。例如shortcuts/im/im_feed_shortcut_create.go、im_feed_shortcut_list.go、im_feed_shortcut_remove.go对应 Feed Shortcut 的三个操作shortcuts/im/im_download_resources.go、convert_lib/resource_extract.go对应资源提取与下载逻辑。二、资源关系Resource RelationshipsIM 域的资源是严格的层级结构父级对象拥有子级对象Chat (oc_xxx) ├── Message (om_xxx) │ ├── Thread (reply thread) │ ├── Reaction (emoji) │ └── Resource (image / file / video / audio) └── Member (user / bot)这一层级在实际命令中的体现拉取消息必须先有chat_idchat-messages-list或message_idmessages-mget下载图片/文件必须先有message_idfile_keymessages-resources-download查询已读状态必须先有message_idmessage-read-users/messages-read-status。三、重要注意事项Important Notes3.1 身份与 Token 映射Identity and Token Mappinglark-cli 的--as参数决定了调用者身份与所用令牌这是 IM 域最容易踩坑的地方--as user用户身份使用user_access_token。调用以授权终端用户身份执行因此权限同时取决于应用 scope 与该用户自身对目标 Chat/Message/Resource 的访问权。--as bot机器人身份使用tenant_access_token。调用以应用机器人的身份执行行为取决于机器人的群成员身份、应用可见性、可用范围以及机器人专属 scope。若某个 IM API 声明同时支持user与bot令牌类型改变的只是操作者是谁。同一 API 在一种身份下成功、在另一种身份下失败是完全正常的——因为群主/管理员状态、群成员关系、租户边界、应用可用性都是针对当前调用者校验的。这一点在skills/lark-im/SKILL.md的各 API 说明中有大量印证例如chat.join_requests.list/handle明确标注仅群主/管理员user_access_token而messages.merge_forward明确标注botonlytenant_access_token。3.2 发送者名称解析Sender Name Resolution在拉取消息的四个命令chat-messages-list、threads-messages-list、messages-mget、messages-search中CLI 会为用户和机器人发送者展示显示名称服务端提供的名称读取类 API 会在每个消息的sender上返回sender_name以及全 i18n 的sender_i18n_names映射CLI 将其呈现为发送者的name字段用户和机器人一视同仁。无需任何名称查询、无需额外权限——不需要 contact scope也不需要application:bot.basic_info:read。回退到 ID当服务端未提供名称时发送者以 ID 展示命令依然以退出码 0 正常结束。没有通讯录contact-directory回退机制。输出细节原始sender_name不会重复出现在输出中其值已并入name完整的sender_i18n_names映射所有语言环境会保留供需要特定语言的消费者使用机器人发送者会附带可选的open_bot_idou_前缀与消息接收事件通道对齐系统消息msg_type: system没有发送者名称——这是正常现象不是错误。3.3 默认消息富化Default message enrichment: reactions / update_time四个消息拉取 Shortcutmessages-mget、chat-messages-list、messages-search、threads-messages-list会自动为每条返回消息附加reactions块以及对已编辑消息的update_time——无需单独调用im.reactions.batch_query。可用--no-reactions退出此行为。完整的契约细节记录在 skills/lark-im/references/lark-im-message-enrichment.md要点如下reactions由im.reactions.batch_query填充结构为{counts, details}。仅当服务端实际返回数据时才附加该字段无表情的消息会省略该字段。thread_replies内的回复与其父消息一并富化收集进同一个 ID 集合因此外层与内层消息语义一致。ID 集合按 20 个分批服务端上限批次以受限并发最多 4 个在途派发——例如第 50 页 约 500 条展开的线程回复 550 个 ID即 ⌈550 / 20⌉ 28 个批次只需几次往返即可完成而不是串行耗时数十秒。update_time仅在updated true消息确实被编辑过时输出。服务端对未编辑消息也会回显update_time create_time但 CLI 会将该输出过滤掉避免消费者把每条消息都误读为已编辑。退出开关每个 Shortcut 都接受--no-reactions在只需要消息正文时跳过额外往返。线程回复展开Thread replies expansionmessages-mget与chat-messages-list还会自动展开线程回复任何携带thread_id的返回消息都会触发对该线程回复的拉取结果作为thread_replies数组附加在宿主消息上。不同线程的拉取以受限并发最多 4 个在途执行。两个上限约束结果perThread默认 50单个线程最多拉取的回复数。totalLimit默认 500本页所有线程累计回复的最大值。totalLimit是在拉取完成后按实际返回的回复数执行的而不是按计划中的单线程上限——因此一个含多个短线程的群如 12 个线程 × 3 条实际回复 36 ≪ 500会附加全部线程尽管计划之和12 × 50 600已超出预算。当某线程的实际回复把累计数推过totalLimit时该线程会被截断以适配剩余预算其宿主消息被标记为thread_has_more: true提示消费者服务端还有更多数据。单线程拉取失败时宿主消息得到thread_replies_error: true与 reactions 数据契约对称被预算截断或跳过的线程不会携带该标记。数据契约——字段缺失 ≠ 拉取失败场景输出消息无表情reactions字段被省略不是{}不是空列表消息从未编辑update_time字段被省略整批失败该批消息不携带reactionsstderr 一行warning: reactions_batch_query_failed: ...部分消息 ID 失败失败 ID 输出到 stderrwarning: reactions_partial_failed: N message(s) failed (...)判断用户是否已点过表情时应基于reactions字段是否存在及其counts内容分支判断而不是判断值是否为null——字段缺失意味着未附加数据通常意味着无表情不代表拉取失败。scope 要求默认富化需要im:message.reactions:read该 scope 已声明在每个 Shortcut 的UserScopes/BotScopes搜索命令为Scopes中框架的预检会在请求发出前暴露missing_scope错误。在此 scope 加入前注册的机器人需要在飞书开发者后台做增量授权用户身份可运行lark-cli auth login --scope im:message.reactions:readskills/lark-im/references/lark-im-reactions.md中还特别提醒默认情况下不要主动调用batch_query——上述四个拉取 Shortcut 已自动完成该调用并附加结果含thread_replies内回复。只有当你在该拉取流程之外持有独立的message_id时才需要调用原始im.reactions.batch_queryAPI。3.4 可选资源自动下载Opt-in resource auto-download:--download-resourceschat-messages-list、messages-mget、threads-messages-list接受--download-resources参数默认关闭——省略时输出与请求数与原来完全一致无resources块、无额外往返。启用后每条携带可下载资源的消息获得resources数组。可下载类型image、file、audio、video、media以及 post 富文本内嵌的img/media。贴纸sticker被排除飞书不支持拉取贴纸资源。每个引用为{message_id, key, type, local_path, size_bytes}——type为image或filemessage_id是用于拉取该资源的 ID。独立消息即其自身 IDmerge_forward 合并转发内的资源则使用顶层容器的message_id下载端点会以234003 File not in msg拒绝子项 ID只能通过容器拉取转发资源。线程回复各自拥有自己的块。文件下载到当前工作目录下的./lark-im-resources/。每个不同的(message_id, file_key)只下载一次去重受限并发最多 3 个在途。失败静默隔离单个资源下载失败会被标记error: true并在 stderr 输出一行warning: resource_download_failed: message_id/key: ...主消息与其他资源不受影响。输出路径被限制在./lark-im-resources/内与messages-resources-download使用相同的守卫异常的含路径分隔符 /../ 绝对路径的file_key会被拒绝。Scope下载使用GET /open-apis/im/v1/messages/:message_id/resources/:file_key需要im:message:readonly——已声明在各列表命令的Scopes中因此--download-resources不需要额外 scope用户身份还需im:message.group_msg:get_as_user/im:message.p2p_msg:get_as_user机器人身份需要im:message.group_msg/im:message.p2p_msg:readonly均已声明。user与bot两种身份均可用。若机器人在im:message:readonly授予前注册单个资源会静默失败error: true stderr 警告而非中止整个拉取。建议需要在一次调用中把二进制拿到磁盘时用--download-resources否则消息内容保留内联资源标记如Image、file .../、audio key... durationXs/之后可用messages-resources-download单独拉取单个资源。单资源下载命令的参数如下完整说明见 skills/lark-im/references/lark-im-messages-resources-download.md# 下载图片保存到当前目录 lark-cli im messages-resources-download --message-id om_xxx --file-key img_v3_xxx --type image # 指定输出路径 lark-cli im messages-resources-download --message-id om_xxx --file-key img_v3_xxx --type image --output ./photo.png # 以机器人身份下载 lark-cli im messages-resources-download --message-id om_xxx --file-key img_v3_xxx --type image --as bot # 只预览请求不实际执行 lark-cli im messages-resources-download --message-id om_xxx --file-key img_v3_xxx --type image --dry-run参数速查--message-id必填om_xxx、--file-key必填img_xxx或file_xxx、--type必填image或file、--output可选须解析到内置允许根目录工作目录、/tmp、~/files系统与凭据目录始终拒绝、--asuser默认 /bot、--dry-run。成功时读取data.saved_path与data.size_bytes。资源类型与消息标记的对应关系消息类型内容标记file_key格式--type图片img_xxximg_xxximage文件file_xxxfile_xxxfile音频file_xxxfile_xxxfile视频file_xxxfile_xxxfile贴纸无法通过该命令下载。文件夹本身不可下载——先用lark-cli im files folder --recursive展开再下载其中文件。3.5 卡片消息Card Messages / Interactiveinteractive类型的卡片消息尚不支持在事件订阅中做紧凑转换——此时会返回原始事件数据并向 stderr 打印提示。补充知识来自 skills/lark-im/SKILL.md发送/回复/更新任何interactive卡片前必须先阅读references/card/lark-im-card-create.md并遵循其工作流传给--msg-type interactive --content发送/回复或messages.patch --data更新的卡片 JSON 必须是该工作流的输出切勿手写或复制卡片负载。interactive卡片支持card.action.trigger回调事件。3.6 Flag 类型Flag TypesFlag书签支持两层消息层 Flag(ItemTypeDefault, FlagTypeMessage)—— 普通消息书签Feed 层 Flag(ItemTypeThread/ItemTypeMsgThread, FlagTypeFeed)—— 把话题作为 Feed 层书签Feed 层 Flag 的 item typeItemTypeThread4 话题风格群topic-style chat中的话题ItemTypeMsgThread11 普通群中的话题对应 Shortcutflag-create默认创建消息层 Flag用--flag-type feed创建 Feed 层 Flagitem_type 根据群模式自动检测、flag-cancel未指定--flag-type时尽力双重取消移除消息层并在 chat_type 可判定时移除 Feed 层、flag-list仅用户身份自动为 Feed 类型话题条目富化消息内容--page-all受--page-limit限制默认 20、最大 1000has_moretrue表示结果不完整。3.7 Feed 快捷方式Feed ShortcutFeed 快捷方式把会话加到当前用户的 Feed 侧边栏与 Flag 是两回事Flag 消息/话题上的书签作用于用户的书签列表Feed shortcut 用户 Feed 侧边栏的条目目前仅会话。关键限制仅CHAT 类型feed_card_id为oc_xxx通过 OpenAPI 暴露doc/app/subscription 快捷方式内部存在但尚未列入白名单创建/移除/列表三个操作仅限用户身份——使用user_access_token签名创建/移除的批量上限为每次 10 个列表是单页包装使用不透明的page_token分页。对应 Shortcutskills/lark-im/SKILL.md中的 Shortcuts 表feed-shortcut-create仅oc_xxx会话 ID--head/--tail控制插入顺序部分失败返回ok:false明细、feed-shortcut-remove移除不存在的快捷方式是幂等成功真实失败返回ok:false明细、feed-shortcut-list省略--page-token取第一页默认在detail下富化 CHAT 条目--no-detail可跳过额外查询与im:chat:readscope。相关实现可参考shortcuts/im/im_feed_shortcut_create.go、im_feed_shortcut_remove.go、im_feed_shortcut_list.go及im_feed_shortcut_test.go。3.8 Feed 分组Feed GroupFeed Group 是分组 Feed 卡片的标签feed_group_id为ofg_xxx格式。成员是 Feed 卡片由feed_idfeed_type标识。两种类型normal成员显式管理rule成员由规则自动派生。相关原始 API 为im.feed.groups下的create、delete、update、batch_query、batch_add_item、batch_remove_item全部仅限用户身份user_access_token分别需要im:feed_group_v1:write/im:feed_group_v1:readscope见 SKILL.md 权限表。Shortcut 包括feed-group-list支持--page-all自动分页、feed-group-list-item按feed_id解析chat_name富化、feed-group-query-item。四、命令使用路径与实战建议4.1 Shortcut 优先推荐skills/lark-im/SKILL.md明确建议有 Shortcut 的操作优先使用lark-cli im verb [flags]。IM 域提供了 20 个 Shortcut覆盖群聊、消息、线程、表情、Flag、Feed 等类别Shortcut群聊chat-create、chat-list、chat-members-list、chat-search、chat-update消息messages-send、messages-reply、messages-edit、messages-mget、messages-search、chat-messages-list、threads-messages-list读取状态messages-read-status、message-read-users资源messages-resources-download表情flag-create、flag-cancel、flag-listFeedfeed-shortcut-create、feed-shortcut-remove、feed-shortcut-list、feed-group-list、feed-group-list-item、feed-group-query-item一个典型组合来自messages-mget的官方场景先用chat-messages-list拿消息列表再用messages-mget批量取详情# 第一步获取消息列表 lark-cli im chat-messages-list --chat-id oc_xxx --format json # 第二步批量获取指定消息详情最多 50 个逗号分隔 lark-cli im messages-mget --message-ids om_aaa,om_bbbmessages-mget参数要点--message-ids必填至少 1 个、最多 50 个om_xxx格式逗号分隔、--no-reactions跳过自动富化、--download-resources默认关闭。输出顶层含messages数组与total计数每条消息含message_id、msg_type、create_time、sender含name、content。AI 使用建议完整内容用--format json表格输出会截断folder消息会展开一层子项post 消息的附件区渲染为content尾部的file key... name.../行。4.2 原生 API 调用先看 schema不使用 Shortcut 时遵循两条铁律lark-cli schema im.resource.method # 调用 API 前必须先查看参数结构 lark-cli im resource method [flags] # 调用 API原生 API 的--data/--params字段格式必须通过schema确认不要猜测。例如表情 API 使用结构化 JSON 输入而非类型化 flag# 添加表情 lark-cli im reactions create \ --params {message_id:om_xxx} \ --data {reaction_type:{emoji_type:SMILE}} # 删除表情 lark-cli im reactions delete \ --params {message_id:om_xxx,reaction_id:ZCaCIjUBVVWSrm5L-3ZTw_xxx}im.reactions系列 API 的 HTTP 映射createPOST/messages/{message_id}/reactions、listGET、deleteDELETE/messages/{message_id}/reactions/{reaction_id}、batch_queryPOST/messages/reactions/batch_query。emoji_type是跨读写 API 使用的枚举式表情标识完整列表185 个如SMILE、LAUGH、THUMBSUP、OK等收录于 skills/lark-im/references/lark-im-reactions.md。4.3 常见错误排查症状根因解决--message-ids requires at least one message ID未提供消息 ID至少提供一个消息 IDinvalid message ID: must start with om_ID 格式错误消息 ID 必须以om_开头权限被拒资源不匹配file_key与message_id来自不同消息重新读取消息并使用匹配的标识权限被拒缺 scopeim:message:readonly未授权用户lark-cli auth login --scope im:message:readonly机器人在开发者后台为应用授权附件不可用消息/资源被删除、隐藏、受限或调用者不可访问不要原样重试报告确切的 CLI 错误空结果消息 ID 不存在或不可访问校验 ID 与访问权限五、总结飞书 IM 域的建模看似简单一条消息、一个群但 lark-cli 通过身份映射 自动富化 分层书签/置顶三个维度把它变成了一套严谨的领域体系--as user/--as bot决定操作者身份与权限校验主体四个消息拉取 Shortcut 自动附加reactions/update_time并可选展开线程回复与下载资源同时以字段缺失 ≠ 拉取失败的契约保证输出稳定性Flag 与 Feed Shortcut 则分别作用于书签列表与侧边栏置顶两个不同的用户空间。对于 AI Agent 而言最关键的实践规则可以浓缩为三条读消息优先用四个带富化的 Shortcut别手动调batch_query、需要二进制一次到位用--download-resources默认关闭、涉及权限疑问时先想清楚当前身份是 user 还是 bot。更多细节请继续阅读 skills/lark-im/SKILL.md 及其references/目录下的各命令文档以及顶层模板 skill-template/master-skill-template.md 中关于认证与全局参数的说明。【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200 commands and 20 AI Agent Skills.项目地址: https://gitcode.com/gh_mirrors/cli414/cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考