Feishu Room Booking 3.2.0
面向飞书用户的会议室查询、预订与配置技能,支持首次使用时识别公司、从飞书日程自动导入企业会议室 room_id、查询忙闲、按楼栋/楼层/容量筛选、创建或补订会议室、偏好管理、候补轮询与工区时间线。当用户提到“查会议室”“订会议室”“配置会议室”“导入会议室”“会议室偏好”“补订会议室”或首次安装配置时使用。
qiushibang
@qiushibang
Install
$ openclaw skills install @qiushibang/feishu-room-booking飞书会议室查询与预订
管理飞书会议室的忙闲查询、自动匹配、日程预订、偏好管理和候补轮询。
前置依赖
- 运行环境已提供
lark-cli,并以当前飞书用户身份完成授权 - 日历、参与人和忙闲命令统一使用
--as user - 飞书应用需具备日历读取、参与人读取、忙闲查询及日程写入权限
- 首次使用先运行
python3 scripts/room_setup.py --status --json;未配置时必须先询问用户所在公司 - 数据文件:内置目录
references/room-mapping.json、自定义目录references/custom-room-mapping.json、租户配置references/tenant-profile.json,以及偏好/候补/工区文件 - 脚本目录:
scripts/ - 建筑匹配使用索引查找,忙闲查询支持并行
工具脚本
所有会议室操作必须通过脚本,不要手写 bash 循环。
room_setup.py — 首次配置与会议室导入
每次查询配置状态:
python3 scripts/room_setup.py --status --json
返回 configured: false 时,先询问:“你所在的公司/组织名称是什么?”
- 用户属于字节跳动或 TikTok:运行
python3 scripts/room_setup.py --set-company "字节跳动",启用随技能提供的会议室目录。 - 其他公司:运行
python3 scripts/room_setup.py --set-company "公司名称",然后按下面步骤引导。不要要求用户编辑脚本或 JSON。
非字节租户配置步骤(逐步完成,不要一次抛出全部操作):
- 请用户在飞书日历中新建一个临时日程,标题建议为“会议室配置-楼栋名”。为降低影响,选择一个非工作时段并设置 5 分钟。
- 在日程的“会议室”中选择同一楼栋的全部会议室并保存。会议室数量超过单次上限时,拆成多个临时日程;不同楼栋分别创建。
- 请用户告诉 Agent 临时日程的标题/时间与楼栋名称。Agent 用
lark-cli calendar +search-event --as user或+agenda找到calendar_id和event_id。 - Agent 自动读取全部 resource 参与人并导入,无需用户复制 room_id:
python3 scripts/room_setup.py \
--calendar-id "<calendar_id>" --event-id "<event_id>" \
--building "总部A座" --aliases "总部,A座" --default-capacity 0
- 运行
python3 scripts/query_rooms.py --list-rooms -b "总部A座",把导入数量和样例会议室展示给用户核对。名称中的(8)/(8人)会自动识别为容量;无法识别时容量为--default-capacity,可按楼栋分批导入并指定默认容量。 - 导入确认后,请用户删除临时日程或移除其中的会议室,避免占用资源。Agent 不主动删除,除非用户明确要求。
- 继续处理下一栋楼,全部导入后再开始查询和预订。
若读取参与人返回权限错误,保留错误码、scope、console URL 和 hint,提示管理员开通日程参与人读取权限;不要让用户手工维护 room_id。
query_rooms.py — 会议室查询
# 列出所有楼栋
python3 scripts/query_rooms.py --list-buildings
# 列出指定楼栋的会议室
python3 scripts/query_rooms.py --list-rooms -b "丽金"
# 查询空闲会议室(表格输出,自动并行查询)
python3 scripts/query_rooms.py -b "丽金" \
-s "2026-04-20T14:00:00+08:00" \
-e "2026-04-20T15:00:00+08:00" -o table
# 按容量筛选
python3 scripts/query_rooms.py -b "丽金" \
-s "2026-04-20T14:00:00+08:00" \
-e "2026-04-20T15:00:00+08:00" \
--capacity-gte 8 -o table
# 调整并行度(默认 10 线程)
python3 scripts/query_rooms.py -b "丽金" \
-s "2026-04-20T14:00:00+08:00" \
-e "2026-04-20T15:00:00+08:00" \
--max-workers 20 -o table
manage_preferences.py — 偏好管理
# 设置偏好
python3 scripts/manage_preferences.py --set \
--user "ou_xxx" --building "丽金" --capacity-gte 8 \
--preferred-rooms "F11-07,F11-15" --note "偏好靠近电梯"
# 读取偏好
python3 scripts/manage_preferences.py --get --user "ou_xxx"
# 记录用户选择(自动学习)
python3 scripts/manage_preferences.py --learn \
--user "ou_xxx" --room "F11-15(8)" --building "丽金智地中心 B座"
# 列出所有偏好
python3 scripts/manage_preferences.py --list
watch_waitlist.py — 候补管理
# 查看候补状态
python3 scripts/watch_waitlist.py --status
# 执行一轮轮询
python3 scripts/watch_waitlist.py --poll
# 添加候补
python3 scripts/watch_waitlist.py --add \
--event-id "xxx" --summary "周会" \
--start "2026-04-20T14:00:00+08:00" --end "2026-04-20T15:00:00+08:00" \
--building "丽金" --capacity-gte 8
# 移除候补
python3 scripts/watch_waitlist.py --remove --event-id "xxx"
# 清理过期候补
python3 scripts/watch_waitlist.py --clean
workspace_manager.py — 工区时间线管理
# 查看当前工区和下周工区
python3 scripts/workspace_manager.py --get
# 设置当前工区(默认从今天到本周日)
python3 scripts/workspace_manager.py --set --workspace "丽金智地中心 B座"
# 设置指定日期范围的工区
python3 scripts/workspace_manager.py --set --workspace "紫金数码园4号楼" \
--from "2026-04-30" --to "2026-05-02"
# 设置下周工区
python3 scripts/workspace_manager.py --set-next --workspace "紫金数码园4号楼"
# 推荐下周工区 / 周五提醒检查 / 查看时间线
python3 scripts/workspace_manager.py --recommend
python3 scripts/workspace_manager.py --check-friday-reminder
python3 scripts/workspace_manager.py --timeline
数据文件
| 文件 | 用途 |
|---|---|
references/tenant-profile.json | 公司与当前会议室目录选择 |
references/room-mapping.json | 随技能提供的会议室目录 |
references/custom-room-mapping.json | 非内置租户通过配置日程自动生成的目录 |
references/user-preferences.json | 用户个人偏好 |
references/room-waitlist.json | 候补预订队列 |
references/weekly-workspace.json | 当前工区 / 下周工区时间线 |
核心流程
流程 A:查询空闲会议室
用户只想看哪些会议室有空。
- 解析意图 — 时间段、楼栋、容量需求
- 确定楼栋 —
- 用户明确指定 → 直接使用
- 用户未指定 → 先读取用户偏好获取默认楼栋(
manage_preferences.py --get) - 用户无偏好 → 读取当前工区 / 下周工区(
workspace_manager.py --get)作为默认楼栋 - 仍然无法确定 → ⚠️ 必须询问城市/楼栋,不要猜测。可提示"北京/上海/深圳/杭州/..."等热门城市
- 确定日期 — ⚠️ 严格验证星期几
- 执行查询 —
python3 scripts/query_rooms.py -u "ou_xxx" -s ... -e ... -o table- 用户已指定楼栋时仍优先传
-b - 未指定楼栋时,脚本会按“用户偏好 → 当前/下周工区”兜底
- 用户已指定楼栋时仍优先传
- 呈现结果 — 直接转发脚本输出
流程 B:创建会议并自动预订
用户要开会,需要创建日程 + 匹配会议室。
- 解析意图 — 标题、时间、楼栋、容量、参会人
- 确定日期 — ⚠️ 严格验证星期几
- 确定默认楼栋 —
- 优先读取用户偏好:
python3 scripts/manage_preferences.py --get --user "ou_xxx" - 无偏好时读取工区时间线:
python3 scripts/workspace_manager.py --get - 用户显式指定楼栋时覆盖默认值
- 优先读取用户偏好:
- 查询空闲会议室 — 用脚本查询,带上容量筛选
- 用户选择 — 把候选会议室列给用户确认
- 创建日程 —
lark-cli calendar +create --as user(或events create) - 添加会议室+参会人 —
lark-cli calendar event.attendees create --as user- ⚠️ 会议室是 resource:attendee type 为
"resource",会议室 ID 传omm_xxx - ⚠️ 日历操作统一用
--as user,不要用 bot 身份
- ⚠️ 会议室是 resource:attendee type 为
- Reflection 二次校验 — 等 5 秒后用
lark-cli calendar event.attendees list --as user查 RSVPconfirmed:resource 已 accept,才能对用户说"预订成功"pending:resource 已出现但状态未定,只能说"已提交,等待确认"failed:resource decline / 缺失,不能宣告成功
- Fallback —
failed时自动换下一个空闲会议室 - 记录选择 — 仅
confirmed后调用python3 scripts/manage_preferences.py --learn --user "ou_xxx" --room "F11-15(8)" --building "..."
流程 C:用户偏好管理
用户设置或修改会议室偏好,后续自动应用。
设置偏好:
- 用户说"我一般用丽金B座8人以上的会议室"
- 调用
--set写入偏好
自动学习:
- 每次流程 B 完成后,调用
--learn记录选择 - 连续 3 次选同一个会议室 → 自动标记为偏好会议室
- 最近 3 次选同一楼栋 → 自动设为默认楼栋
应用偏好:
- 流程 B 的 Step 3 自动读取偏好
- 偏好楼栋不匹配时,按偏好查;没空闲时追问是否换楼栋
- 容量需求自动带入查询
流程 D:扫描日程自动补订
自动检测用户日程中缺少会议室的会议并补订。
触发方式:
- 手动:用户说"帮我检查一下有没有缺会议室的日程"、"补订会议室"
- 自动:Heartbeat 定时任务
扫描步骤:
- 用
lark-cli calendar +agenda --as user或events search_event --as user获取用户近期日程(未来 24 小时),再用events get --need-attendee --as user补齐参与人详情,保存为 JSON 传给scan_events.py --events-file- 若飞书返回
194001 no permission to list event attendees等权限错误,在该事件中写入"attendee_details_complete": false;扫描器会将其标为待确认并跳过,避免因看不到已有资源而重复预订
- 若飞书返回
- 首轮检查当前用户是否已 accept:优先读事件级
self_rsvp_status,没有时再看 attendees 中当前用户的rsvp_status / status / response_status - 对 resource 参会人做 reflection 分类,而不是只看“是否存在 resource”
confirmed:已有已确认会议室,直接跳过pending:会议室状态待确认,先进入二次确认队列,不立即补订failed/missing:视为当前没有成功会议室,可继续补订
- 对首轮判定需要补订的事件,再做一次二次确认
- 二次确认后仍为
confirmed缺会议室的日程:- 先读取用户偏好确定默认楼栋和容量
- 无默认楼栋时回退到当前工区 / 下周工区
- 查询空闲会议室
- 有空闲 → 自动预订(跳过用户确认,因为是补订场景)
- 全满 → 加入候补队列
判断是否需要会议室的逻辑:
- ❌ 跳过:当前用户未 accept、已有
confirmed会议室、日期型全天事件 - ⏳ 待确认:当前用户状态缺失,或 resource 已存在但 RSVP 未稳定
- ✅ 补订:当前用户已 accept,且当前没有
confirmed会议室
流程 E:候补轮询
会议室满了时的自动候补机制。
添加候补:
- 流程 D 发现全满时,调用
watch_waitlist.py --add加入队列 - 候补项应写入已经确定好的楼栋;默认楼栋的决策仍遵循“用户偏好 → 当前/下周工区”
轮询检查:
- Heartbeat 或手动触发
watch_waitlist.py --poll - 对每个 waiting 状态的候补,查询当前时段空闲会议室
- 找到空闲 → 标记为
ready,通知 agent 执行预订 - agent 提交预订后进入
verification_pending,等待 5 秒后二次校验 - 仍然满 → 记录已尝试列表,等待下次轮询
预订成功后:
confirmed→ 从候补移除pending→ 保持verification_pendingfailed / decline→ 回到waiting,允许继续候补或 fallback
清理:
- 定期
--clean清理已过期的候补(开始时间超过 1 小时)
流程 F:工区时间线管理
用户需要声明当前工区、设置下周工区,或让系统给出默认工区建议。
支持动作:
python3 scripts/workspace_manager.py --get查看当前工区 / 下周工区python3 scripts/workspace_manager.py --set --workspace "丽金智地中心 B座"设置当前工区python3 scripts/workspace_manager.py --set-next --workspace "紫金数码园4号楼"设置下周工区python3 scripts/workspace_manager.py --recommend基于近期会议室选择推荐工区python3 scripts/workspace_manager.py --check-friday-reminder检查是否需要周五提醒python3 scripts/workspace_manager.py --timeline查看完整时间线
默认楼栋决策优先级:
- 用户本次明确指定楼栋
- 用户偏好中的
default_building - 当前工区 / 与查询日期匹配的下周工区
- 仍然无法确定时追问用户
交互规范
自然语言解析
| 用户说 | 解析 |
|---|---|
| "明天下午3点开会" | 明天 15:00,默认 1 小时。未指定楼栋时先查偏好,再查工区 |
| "找个会议室" | 读取偏好 → 用默认楼栋和容量。无偏好则读当前工区;仍无结果再问城市/楼栋 |
| "查一下丽金B座明天下午" | Flow A,匹配 "丽金B座" → 丽金智地中心 B座 |
| "帮我找丽金B座11楼的会议室" | Flow A,先匹配楼栋,再用楼层 11 缩小房间范围 |
| "查一下 F11-15 明天下午是否空闲" | Flow A,优先按房间号匹配楼栋,再按房间号缩小到单个候选 |
| "我这周在丽金B座" | 流程 F,设置当前工区时间线 |
| "下周回紫金" | 流程 F,设置下周工区 |
| "帮我设个偏好,丽金B座8人以上" | 流程 C,设置偏好 |
| "查一下我有没有缺会议室的会" | 流程 D,扫描日程 |
| "候补状态怎么样了" | 流程 E,查看候补 |
| "北京有哪些工区" | --list-buildings 筛选含"北京"的行 |
楼栋匹配提示
会议室目录支持随技能提供的内置数据,也支持用户所在飞书租户的自定义数据。agent 匹配楼栋时:
- 中文关键词("丽金"、"紫金"、"大钟寺")→ 自动模糊匹配
- 英文缩写("F4"、"F11")→ 自动匹配别名
- 楼层 / 房间号差异表达("11楼" / "11F" / "F11-15" / "11-15" / "DiscussionBooth A")→ 自动抽取并缩小候选
- 城市筛选:用户说"北京的会议室" → 先
--list-buildings再 grep "北京" - 匹配到多个结果时 → 列出来让用户选,不要默认猜一个
用户确认原则
- 流程 B(主动创建):必须确认时间、会议室、参会人
- 流程 D(自动补订):不需要确认,直接执行
- 流程 E(候补预订):不需要确认,直接执行
注意事项
- 并行查询:freebusy 查询自动 10 线程并行,大工区(200+ 间)可加
--max-workers 20 - 会议室是 resource:添加参会人时 attendee type 为
"resource",会议室 ID 传omm_xxx - 身份统一 user:所有日历、参与人和忙闲命令都用
--as user - 时区统一:
Asia/Shanghai(+08:00),ISO 8601 - 日期验证:涉及相对时间必须验证星期几
- 脚本优先:统一用 scripts/ 下的脚本
- 时间修改风险:patch 改时间后会议室可能 decline,必须重新验证
- 偏好自动学习:每次预订成功后调用
--learn记录 - 楼栋匹配:使用索引查找(O(1)),支持模糊匹配 name 和所有 alias
- 租户目录:首次使用必须先确认公司;内置目录之外的租户通过配置日程导入会议室,未指定楼栋时优先使用用户偏好,再回退到当前/下周工区
- 工区时间线:weekly-workspace.json 只负责当前工区 / 下周工区,不替代用户个人偏好和自动学习
Top skills in this category
Nano Banana Pro
@steipeteGenerate/edit images with Nano Banana Pro (Gemini 3 Pro Image). Use for image create/modify requests incl. edits. Supports text-to-image + image-to-image; 1K/2K/4K; use --input-image.
AdMapix
@fly0pantsAdMapix raw data layer for ad creatives, apps, rankings, downloads/revenue, and market metadata. Returns structured JSON from the AdMapix API; the calling ag...
YouTube Watcher
@michaelgatharaFetch and read transcripts from YouTube videos. Use when you need to summarize a video, answer questions about its content, or extract information from it.
SuperDesign
@mpociotExpert frontend design guidelines for creating beautiful, modern UIs. Use when building landing pages, dashboards, or any user interface.
Video Frames
@steipeteExtract frames or short clips from videos using ffmpeg.