Feishu Contacts Sync
Problem
Feishu (Lark) DM messages only include the sender's open_id — no name. Group messages include Sender metadata with the name, but DMs don't. Without a lookup table, the agent will either:
- - Assume all DMs are from the person in USER.md (wrong)
- Fail to identify the sender entirely
Solution
Embed the full contacts table directly in USER.md. Since workspace files are injected into the system prompt at gateway startup, the agent can match open_id from inbound metadata against the table — zero tool calls needed.
Important: open_id is per-app
Feishu open_id is scoped to each app. The same person has different open_ids across different Feishu apps. Each OpenClaw instance using a different Feishu app must pull contacts with its own app credentials.
Setup
1. Ensure Feishu app has contacts permission
The app needs contact:user.employee_id:readonly or contact:user.base:readonly scope to list users via the contacts API.
2. Run the sync script
CODEBLOCK0
Example:
CODEBLOCK1
Arguments:
- -
openclaw_config_path: Path to your openclaw.json (contains Feishu app credentials) - INLINECODE7 : The account name under
channels.feishu.accounts in your config - INLINECODE9 : Path to your USER.md file
3. USER.md format
The script expects USER.md to contain a contacts section with this format:
CODEBLOCK2
On first run, if no contacts section exists, add the section header and description line manually, then run the script to populate the table.
4. Add sender identification to AGENTS.md
Add this to your startup sequence:
CODEBLOCK3
5. Set up periodic sync (optional)
Add a system crontab to keep contacts fresh (e.g., weekly Monday 7am):
CODEBLOCK4
Note: After sync updates USER.md, restart the gateway for changes to take effect (workspace files are cached at gateway startup).
Multi-user principle
USER.md should clearly state:
- - Who the "primary human" (主人) is
- That the agent serves multiple users and must not assume DM sender identity
- A communication preference to address people by their actual name
Privacy
- - The contacts table contains only names and openids (no emails, phone numbers, or other PII)
- openid is an opaque identifier meaningful only within your Feishu app
- The sync script reads app credentials from openclaw.json but never outputs them
飞书通讯录同步
问题
飞书(Lark)私聊消息仅包含发送者的 open_id,不包含姓名。群聊消息的 发送者元数据 中带有姓名,但私聊消息没有。如果没有查询对照表,智能体将出现以下情况:
- - 假设所有私聊消息都来自 USER.md 中记录的人(错误)
- 完全无法识别发送者身份
解决方案
将完整的通讯录表格直接嵌入 USER.md 中。由于工作区文件在网关启动时会被注入系统提示词,智能体可以直接将入站元数据中的 open_id 与表格进行匹配——无需任何工具调用。
重要提示:open_id 按应用区分
飞书 openid 的作用域限定在每个应用内。同一个人在不同飞书应用中拥有不同的 openid。每个使用不同飞书应用的 OpenClaw 实例必须使用自己的应用凭证拉取通讯录。
设置步骤
1. 确保飞书应用拥有通讯录权限
应用需要具备 contact:user.employee_id:readonly 或 contact:user.base:readonly 权限范围,才能通过通讯录 API 列出用户。
2. 运行同步脚本
bash
python3 scripts/syncfeishucontacts.py configpath> accountname> mdpath>
示例:
bash
python3 scripts/syncfeishucontacts.py ~/.openclaw/openclaw.json my_app ~/workspace/USER.md
参数说明:
- - openclawconfigpath:openclaw.json 的路径(包含飞书应用凭证)
- feishuaccountname:配置中 channels.feishu.accounts 下的账户名称
- usermdpath:USER.md 文件的路径
3. USER.md 格式要求
脚本期望 USER.md 中包含以下格式的通讯录章节:
markdown
飞书通讯录 (应用名称)
飞书私聊消息不携带发送者姓名。使用入站元数据中的 chat
id(格式 user:ouxxx)匹配下表识别发送者。
ou_def456 |
首次运行时,如果不存在通讯录章节,请手动添加章节标题和描述行,然后运行脚本填充表格。
4. 在 AGENTS.md 中添加发送者识别指令
在启动序列中添加以下内容:
识别消息发送者(必须执行):飞书私聊消息不携带发送者姓名,只有 openid(入站元数据的 chatid 格式 user:ouxxx)。提取 openid,在 USER.md 的飞书通讯录表格中匹配找到姓名。不要假设私聊对象就是主人——任何人都可能给你发送私聊消息。群聊消息自带发送者元数据可直接使用。
5. 设置定期同步(可选)
添加系统定时任务以保持通讯录更新(例如,每周一早上7点):
bash
0 7 1 python3 /path/to/scripts/syncfeishucontacts.py ~/.openclaw/openclaw.json my_app ~/workspace/USER.md
注意:同步更新 USER.md 后,需要重启网关才能使更改生效(工作区文件在网关启动时缓存)。
多用户原则
USER.md 应明确说明:
- - 谁是主要人类用户(主人)
- 智能体服务于多个用户,不得假设私聊发送者身份
- 建议使用真实姓名称呼他人的沟通偏好
隐私说明
- - 通讯录表格仅包含姓名和 openid(不含邮箱、电话号码或其他个人身份信息)
- openid 是一个不透明标识符,仅在您的飞书应用内有效
- 同步脚本会从 openclaw.json 读取应用凭证,但绝不会输出这些凭证