| name | employee-care |
| description | 员工关怀:读取飞书花名册里的员工入职日期与生日,检测当天是否有人过生日或入职周年,为其撰写结合岗位特点的个性化祝福(藏头诗或走心小短句),配一张庆祝主图,用固化的精美卡片构造器做成飞书互动消息卡片(可附礼物领取入口),先发给运行者预览、确认后私聊发给员工本人;首次运行时 skill 先自己搜索飞书资产核对字段、再带结论让用户确认数据源,搜不到则建议改走 CoreHR 直连,支持每天定时运行、多员工并列处理。当用户提到员工关怀、生日祝福、入职周年、花名册、给员工送祝福卡片、生日藏头诗、周年庆、领取生日礼物或要设置每日关怀提醒时使用。 |
员工关怀
能做什么
读飞书花名册(生日 + 入职日期),每天检测当天是否有员工过生日或入职周年;命中后为每人写一段结合其部门/岗位的个性化祝福(藏头诗 / 走心小短句),配一张庆祝主图,做成飞书互动卡片,先发给运行者本人预览、确认后再以用户本人账号私聊发给员工。支持定时每日运行、多员工并列处理。内置生产级保障:幂等去重(不重复打扰)、离职过滤、同天生日+周年合并双喜卡、多人同天合并花名卡(一眼看全今天有谁)、运行回执(发了谁/失败/跳过),并在安装时主动询问是否提前提醒直属领导。
首次运行时 skill 先自己搜索用户飞书资产、读表头核对关键字段,再带着结论让用户确认数据源——不反问「你有没有花名册」,搜不到就如实说明并建议改走 CoreHR 直连。卡片结构严格复刻飞书官方「个人生日祝福」参考案例(无 header、头图承载标题艺术字、60px 圆形头像、column_set 左右布局、hr 划分功能区),头像优先取员工真实飞书头像。生图失败或取不到头像时逐级降级,不阻塞主流程。
流程
Step 0 · 首次配置(先自己探明,再问用户)
铁律:能自己查清的事不要问用户。 数据源在不在、字段够不够,一次 drive +search 就有答案;
问用户「你有没有花名册」只会把失败推迟——用户以为有、实际没有,或者有但缺生日列,白绕一圈。
第一步:先搜,不问。 按 references/data-sources.md 搜一遍用户飞书资产(含近义词),命中的候选
读表头核对关键字段。这一步是静默执行的,不要先向用户提问。
第二步:按搜索结果给结论,只让用户做真正需要他决定的选择。
| 搜索结果 | 对用户说什么 |
|---|
| 找到 ≥1 个字段齐全的 | 带链接 + 字段核对结论,问「用这个吗,还是走 CoreHR」 |
| 找到但都缺生日/入职列 | 说明找到了什么、缺哪列,建议走 CoreHR;用户也可另给一个 |
| 一个都没找到 | 直接说「你飞书里没有可用花名册(已搜 XX 等关键词),建议走 CoreHR 直连」,不要反问「你有吗」 |
第三步:连同另外三项一起问清,一屏问完,别挤牙膏:
- 数据源 —— 按上表给出结论和建议,让用户确认走 A(花名册文件)还是 B(CoreHR 直连)。
- 生日历法 —— 花名册里的生日是公历还是农历?(默认公历;选农历则按农历月日匹配,入职日期始终公历)——花名册有「农历生日」列、或用户明确说员工记的是农历日期时选
lunar。
- 领导提醒 —— 要不要在员工生日/周年前一天私聊提醒其直属领导,让领导也送句祝福?
(可选提前天数,默认 1 天;开或不开都行)——见
references/leader-notify.md。
- 定时 —— 要不要每天自动跑?默认 10:30 Asia/Shanghai,可自选时间。
把四项选择记下来,作为之后每日循环的配置。
为什么只有这四项要问:数据源涉及用户判断(可能有 skill 搜不到的表),生日历法只有用户知道团队习惯,
领导提醒会惊动第三人,定时时间只有用户知道团队作息。其余一切能自己探明的都不要问。
Step 1 · 读取花名册(Step 0 已搜过,此处只做读取)
按 references/data-sources.md,数据源二选一(Step 0 的搜索结果已经决定了走哪条):
- 路径 A · 花名册文件:Step 0 已搜到并经用户确认的文件,按类型读取(bitable 用
lark-base、sheet 用 lark-sheets)。
- 路径 B · CoreHR 直连:
python3 scripts/extract_corehr.py(封装 people-cli 的 CoreHR employees/search,已实测可取到姓名/生日/入职日期/open_id/部门/状态)。需 corehr:employee:read + corehr:person.date_of_birth:read 权限。
两条路径都归一化成同一份 people 列表并写临时 JSON:
[{"name":"张三","open_id":"ou_xxx","department":"研发中台","role":"后端工程师","birthday":"1994-08-25","birthday_type":"solar","hire_date":"2021-08-25","status":"hired"}]
open_id 预览阶段可为空(路径 A 可用 lark-contact 按姓名+部门反查补齐;路径 B 直接带 open_id),发给员工前必须补齐。birthday_type 可选("solar" 默认 / "lunar" 农历)——花名册有农历列时设 lunar,match_today.py 自动转农历比对;入职日期始终公历。
Step 2 · 检测当天命中(含离职过滤、双喜合并)
python3 scripts/match_today.py --roster <tmp.json> --tz Asia/Shanghai
返回 celebrations(一人一条,kind 为 birthday/anniversary/both)、inactive(离职/停用,已过滤不发)、skipped(无可用日期)。脚本已处理:闰年 Feb-29→Feb-28、农历生日匹配(birthday_type: "lunar" 时把今天转农历比对,闰月不匹配)、入职当天不算周年、未知出生年份 age=null、同天生日+周年合并为 both(发一张双喜卡,不发两张)、按 status 列过滤离职/停用(长假不自动过滤,但回显 status 供人工把关)。celebrations 为空则当天无人,安静结束。
Step 3 · 幂等去重
python3 scripts/match_today.py ... | python3 scripts/run_state.py filter --date <today> --source <花名册标识>
过滤掉今天已成功发过的人(防定时重复触发 / 手动+自动重复发)。取返回的 todo 列表继续。
Step 4 · 写个性化祝福
按 references/blessing.md,为 todo 里每个人分别生成(藏头诗默认;或走心小短句),结合部门/岗位意象。both 双喜的人一段话同时点到生日与周年。多人时避免雷同句式。真诚克制,不喊口号、不堆 emoji,直接给成品文案。
Step 5 · 生成图片资产 + 做卡片 + 预览发送 + 记账
卡片架构已固化在 scripts/build_card.py,每次都用它生成,不手写 JSON。架构不是自创的,是严格复刻飞书官方参考案例(卡片搭建工具 → 参考案例库 → 个人生日祝福)。动手前先读 references/card.md 的「Card 2.0 架构铁律」——十条都是实测踩出来的,凭直觉改必然变丑。最关键三条:不要 header(标题印在头图里)、body.padding 全 0(间距由各 column_set 的 margin 管)、禁止居中(全部 text_align: left,靠 column_set 分栏建立对齐)。
每张卡需要两个 img_key:头图(带标题艺术字)+ 60px 圆形头像。用 scripts/upload_image.py 拿:
python3 scripts/upload_image.py upload --url "<生图URL>" --self <self ou_...>
python3 scripts/upload_image.py avatar --user-id <user_id> --self <self ou_...>
头像降级顺序:员工真实飞书头像 → 生成的通用庆祝头像 → 不传 --avatar-key(信息区变单列)。取不到就降级,不阻塞、不臆造。
python3 scripts/build_card.py --kind birthday --name 张三 \
--date-label "08-25" --birth-md "08-25" \
--wish $'张灯结彩逢生辰,\n三载耕耘链路深。' \
--img-key img_v3_xxx --avatar-key img_v3_yyy \
[--gift-url https://... --gift-info $'地点:15楼行政中心\n时间:9:00-18:00'] \
[--wishers "王凡、刘子涵...给你送祝福啦~" --wish-url https://...]
--kind 支持 birthday/anniversary/both(双喜卡);--years N 让周年/双喜标题带上年数;--birth-md MM-DD 自动推导标题里的星座 emoji(复刻官方格式 张三 同学生日快乐 (08-25 ♍️))。礼物区、祝福区都是有数据才出,没传就整区省略。发送前按 references/card.md 末尾的自查清单逐条对。
卡片以用户本人账号发送(默认身份,豆包企业版/飞书自动关联当前用户租户的 CLI 代发;勿写死 bot 或固定 open_id)。发送用 lark-cli im +messages-send,卡片写文件后用 --content "$(cat file)" 传入(--content 不支持 @file;勿用 echo 中转,会损坏 JSON)。先发给运行者本人预览:
python3 scripts/build_card.py --kind birthday --name 张三 ... > /tmp/card.json
lark-cli im +messages-send --user-id <self ou_...> --msg-type interactive --content "$(cat /tmp/card.json)" --dry-run
lark-cli im +messages-send --user-id <self ou_...> --msg-type interactive --content "$(cat /tmp/card.json)"
用户确认后,再逐一发给员工本人的 open_id。每发一人立即记账,成功/失败都记:
python3 scripts/run_state.py mark --date <today> --source <花名册标识> --open-id <ou_...> --status sent --name 张三
多人同天:除每人各自的个性化卡外,用 --roundup 出一张合并花名卡(一眼看全今天有谁、按生日/周年/双喜分标签),默认发给运行者做总览预览;用户同意后也可发到团队群做公开庆祝。
python3 scripts/match_today.py --roster <tmp.json> | python3 scripts/build_card.py --roundup \
--date-label "08-25" --img-key img_v3_xxx --avatar-key img_v3_yyy > /tmp/roundup.json
批量跑完 run_state.py report --date <today> --source <...> 出一份回执(发了谁 / 谁失败 / 原因),连同 inactive、skipped 一并汇报给运营者。详见 references/card.md。
Step 6 · 提前提醒直属领导(按 Step 0 的选择)
若 Step 0 用户选了开启,按 references/leader-notify.md:提前 N 天(默认 1 天)解析将过生日/周年员工的直属领导,私聊提醒领导送祝福。缺 scope/查不到领导则跳过、如实告知,不影响本人祝福卡。Step 0 没问或用户选了不开,则不提醒。
Step 7 · 定时运行(可选)
用户要“每天自动跑”时,按 references/scheduling.md 调用宿主 automation 工具创建每日循环任务(默认 10:30 Asia/Shanghai,用户可自选)并回读确认;宿主无法唤起推理时如实告知需手动触发。
铁律
- 先探明再提问:能自己查清的事不要问用户。数据源在不在、字段够不够,先
drive +search 搜一遍再给结论;不要反问「你有没有花名册」——用户以为有、实际没有,白绕一圈。只有涉及用户判断(可能有搜不到的表)、只有用户知道的信息(团队习惯决定的生日历法、团队作息决定的定时时间)、会惊动第三人(领导提醒)才值得问。
- 先预览后发送:默认所有祝福卡片先发给运行者本人,用户明确确认后才发给员工。
- 不重复打扰:发送前用
run_state.py filter 去重,同一员工当天不发第二张;每发一人立即 mark 记账。
- 不给离职员工发:按
status 过滤离职/停用;inactive 与无 open_id 的人在预览/回执里显式列出,交人工把关。
- 一人一卡、逐条个性化:不同员工不复用同一段文案;同天生日+周年合并为一张双喜卡。
- 隐私与租户隔离:只读最小必要字段,不落盘员工敏感信息(台账只存 open_id+状态,可弃);发卡前确认
lark-cli profile 指向正确租户,公司与个人飞书严格隔离。
- 不臆造:读不到日期/open_id 就如实告知,不编造;生图失败或取不到头像就逐级降级,不编 img_key;礼物领取链接与领取信息(地点/时间)由用户提供,没给就整区不出,不编 URL、不编地点。
- 卡片结构照抄官方案例:
references/card.md 的十条架构铁律是实测结论,不是风格偏好。不要凭直觉加 header、居中文本、改 padding 或删掉圆形头像——这些都试过,结果是卡片显廉价。改结构前先读铁律。
- 认边界:500 人以上、要完全无人值守的大规模场景,建议改用飞书多维表格「定时分批获取记录」自动化,如实告知用户。
- 可移植(开源要求):面向所有豆包企业版用户与任意 Agent(Codex/Claude Code/Cursor 等)。不写死任何本机特例——不硬编码 open_id / app_id / profile 名 / bot 身份 / 已授权 scope;身份用环境默认(用户本人账号),文件路径、租户、花名册来源都在运行时发现或由用户确认。缺 scope 时按 CLI 提示引导授权,不假设已授权。
资源
scripts/match_today.py — 当天命中检测:一人一条、both 双喜合并、离职过滤、闰年与年数计算、农历生日匹配(birthday_type: "lunar")。
scripts/lunar.py — 农历辅助模块(依赖 zhdate 包):公历↔农历转换、农历月日匹配。match_today.py 自动调用,无需单独执行。
scripts/extract_corehr.py — 用 people-cli 直连 CoreHR 抽取在职员工并归一化(路径 B 数据源)。
scripts/build_card.py — 固化的卡片构造器:复刻飞书官方「个人生日祝福」结构,产出 Card 2.0 JSON。支持生日/周年/双喜、头图+圆形头像、星座推导、礼物区、祝福区、批量输出、多人合并花名卡(--roundup)。
scripts/upload_image.py — 图片资产链路:公网 URL → img_key(upload),以及按 user_id 取员工真实飞书头像并转 key(avatar)。
scripts/run_state.py — 幂等去重台账 + 运行汇报(filter/mark/report)。
references/data-sources.md — 花名册关键字段 schema、搜索飞书资产定位、字段核对确认、读取与归一化。
references/blessing.md — 藏头诗 / 小短句的写作要求与示例。
references/card.md — Card 2.0 十条架构铁律(实测结论)、完整骨架、build_card.py 用法、生图 prompt、头像获取与上传链路、发送前自查清单。
references/leader-notify.md — (可选)提前提醒直属领导。
references/scheduling.md — 每日定时运行的开启与循环任务体。