飞书组织架构识别
清海 AI 的第一个场景:通过飞书通讯录认识公司每个人,为后续所有业务场景提供身份基础。 角色维度的会话旅程见 角色场景,能力定义见 Skill 清单。
背景与现状
清海的基础通道已通(飞书 Bot + AI 对话 + 记忆 + 通知),但需要组织感知能力。本方案通过飞书通讯录同步,让清海"认识"每个人——知道对方是谁、什么部门、汇报给谁,从而实现千人千面的沟通。
| 维度 | 现状 |
|---|---|
| 数据源 | 飞书通讯录 API v3(GET /contact/v3/departments、GET /contact/v3/users/find_by_department) |
| 团队规模 | 10-50 人,多层级部门结构 |
| 部门结构 | 公司 → 部门(开发/运营/产品…)→ 小组(前端组/后端组…) |
| 通道 | 飞书 Bot(通过 open_id 直接识别用户身份) |
| 同步频率 | 每 30 分钟定时同步(FeishuSync.sync_contacts()) |
| 存储 | MongoDB unified_users 集合 + PersonIndex 内存索引 + 本地缓存 data/cache/contacts.json |
当前实现方式
本场景没有使用 Skill 渐进式加载,组织架构识别在系统层自动完成,AI 通过一个通用工具
search_contacts查询人员信息。
飞书消息进来
↓
avatar_core.identify_user()
↓
PersonContextResolver.resolve_by_channel("feishu", open_id) ← 从 unified_users 读组织信息
↓
system prompt Block 1: "你正在和王五对话,他是产品部的产品经理" ← 身份注入
↓
AI 对话(如果用户问组织问题)
↓
AI 调用 search_contacts(query="产品部", department=...) ← 当前唯一的组织查询工具
↓
PersonIndex.search() → 返回结果已实现 vs 待实现
| 能力 | 状态 | 说明 |
|---|---|---|
| 飞书通讯录同步 | ✅ 已实现 | FeishuSync.sync_contacts() 每 30 分钟同步 |
| PersonIndex 内存索引 | ✅ 已实现 | 启动时从 unified_users 全量加载 |
| PersonContextResolver | ✅ 已实现 | 分层档案 + 按场景切片输出 |
| 身份自动识别 | ✅ 已实现 | open_id → unified_users 自动匹配 |
| search_contacts 工具 | ✅ 已实现 | 按姓名/部门查询,返回姓名+职位+部门+open_id+手机号 |
| 别名学习 / 平台绑定 | ✅ 已实现 | save_contact_alias + link_platform_identity |
| 专用组织查询工具 | ⬜ 待封装 | PersonIndex 有方法但未封装为独立 tool |
| org-query SKILL.md | ⬜ 待实现 | 无 Skill 定义,AI 靠 search_contacts + 身份注入回答 |
| 权限过滤 | ⬜ 待实现 | 无角色维度的数据过滤 |
| 数据质量自检 + 通知 | ⬜ 待实现 | 同步后无自动检测 |
场景与能力总览
飞书组织架构识别覆盖 4 大会话场景,每个场景需要特定的查询能力组合:
场景 → 能力映射表
| 场景 | 触发词示例 | 需要的能力 | 飞书 API |
|---|---|---|---|
| 身份自动识别 | (收到任意消息时自动触发) | 通讯录同步 + PersonIndex + 身份解析 | GET /contact/v3/users/{open_id}?user_id_type=open_id |
| 组织架构查询 | "公司有哪些部门"、"产品部有谁" | PersonIndex 部门查询 + 权限判断 | GET /contact/v3/departments?parent_department_id=0&fetch_child=true |
| 人员信息查询 | "张三是什么部门的"、"张三的上级是谁" | PersonIndex 人员查找 + PersonContext 档案 | GET /contact/v3/users/find_by_department?department_id=... |
| 人员变动感知 | "最近有新同事吗"、"谁离职了" | 通讯录同步差异检测 | 同步时对比 status.is_activated / status.is_resigned 字段 |
能力触发机制
飞书消息进来 → 身份自动识别(每条消息必经,avatar_core 自动完成)
→ AI 判断用户意图涉及组织查询
→ 调用 search_contacts 工具(当前唯一路径)
→ PersonIndex.search() → 整理结果 → 回复用户场景一:身份自动识别
核心价值:员工在飞书发消息时,清海自动知道对方是谁,后续对话自然带入身份认知。
识别流程
飞书 API 数据字段
身份识别依赖 unified_users.channels.feishu 中的以下字段(来自 GET /contact/v3/users):
| 飞书 API 字段 | 存储位置 | 用途 |
|---|---|---|
open_id | channels.feishu.open_id | 消息身份匹配主键 |
name | display_name | 显示名称 |
department_ids | channels.feishu.department_ids | 所属部门(关联部门树) |
job_title | channels.feishu.job_title | 职位 |
status.is_activated | is_active | 在职/离职判断 |
status.is_resigned | is_active | 离职判断 |
关键约束
- 飞书
open_id(以ou_开头)是一对一确定映射,识别准确率 100% - 离职员工由
is_active=False标记,FeishuSync每次同步时通过status.is_resigned/status.is_activated检测 - 身份识别在
avatar_core.identify_user()中自动完成,AI 无需感知
场景二:组织架构查询
核心价值:用自然语言查询公司组织结构,不用打开飞书通讯录。
典型对话
| 用户问法 | 清海应答 | 当前实现路径 |
|---|---|---|
| "公司有哪些部门" | 列出所有部门(名称 + 人数) | search_contacts 无法直接支持,依赖 PersonIndex 内存数据 |
| "产品部有谁" | 列出产品部全部成员(姓名 + 职位) | search_contacts(department="产品部") |
| "开发部门下面有几个组" | 列出子部门/小组结构 | PersonIndex 部门树查询(未封装为 tool) |
| "研发组几个人" | 返回人数 + 成员列表 | search_contacts(department="研发组") |
飞书 API 数据来源
| 查询类型 | 飞书 API | 关键参数 |
|---|---|---|
| 部门列表 | GET /contact/v3/departments | parent_department_id(默认 "0" 为根)、fetch_child=true |
| 部门成员 | GET /contact/v3/users/find_by_department | department_id、department_id_type="open_department_id"、page_size=50 |
| 部门返回字段 | — | open_department_id(od- 开头)、name、member_count |
| 成员返回字段 | — | open_id、name、job_title、department_ids、mobile |
关键约束
- 部门名支持模糊匹配:「产品」→「产品部」
- 兼职/多部门人员以
department_ids[0]主部门为准,在非主部门查询中标注「兼」 - 权限过滤:⬜ 待实现(当前所有人可查所有数据)
场景三:人员信息查询
核心价值:快速了解某人的部门、职位、上下级关系,无需翻飞书通讯录。
典型对话
| 用户问法 | 清海应答 | 当前实现路径 |
|---|---|---|
| "张三是什么部门的" | 张三的部门 + 职位 | search_contacts(query="张三") |
| "张三的上级是谁" | 张三的直属上级 | PersonIndex.get_person_leader()(未封装为 tool) |
| "李四管哪些人" | 李四的直属下属列表 | PersonIndex.get_team_members()(未封装为 tool) |
| "小明是谁" | 模糊匹配结果(可能多个) | search_contacts(query="小明") |
关键约束
- 人名模糊匹配:
PersonIndex.search()支持部分名、别名匹配 - 多结果时列出选项让用户确认("小张"→ 张三、张四)
- 查不到时友好提示:「没找到叫王六的同事,要不要换个名字试试?」
- 敏感信息(薪资、考勤等)受权限限制,非本场景范围
场景四:人员变动感知
核心价值:自动感知入职、离职、调岗等人员变动,保持组织数据实时准确。
变动类型与处理
| 变动类型 | 飞书数据源 | 检测方式 | 清海处理 |
|---|---|---|---|
| 新员工入职 | GET /contact/v3/users/find_by_department 新增记录 | 同步时发现新 open_id | 自动创建 unified_users 记录 + 更新 PersonIndex |
| 员工离职 | status.is_resigned=true 或 status.is_activated=false | 同步时检测状态变更 | is_active=False + 静默不回复 |
| 人员调岗 | department_ids 变更 | 同步时对比字段 | 自动更新部门/上级 + PersonIndex 重建 |
| 信息补全 | job_title 等字段更新 | 同步时对比字段 | 同步更新到 unified_users |
数据流转
关键约束
- 飞书通讯录数据为权威源(
authoritative_sync),覆盖推断和观察数据 - 同步时保留
aliases、GitLab 绑定等非飞书来源数据 - 离职处理 MVP:即时静默。后续增加 7 天交接期
- 飞书 API 不可用时使用上次同步的
data/cache/contacts.json继续服务
角色权限与场景覆盖
不同角色在各场景中的可见范围不同,详见 角色场景。
角色 × 场景矩阵
| 场景 | 老板 | 组长 | 员工 |
|---|---|---|---|
| 身份自动识别 | 全员信息 | 全员信息 | 仅自己(系统自动) |
| 组织架构查询 | 全公司架构 + 人员明细 | 全公司架构 + 本组人员明细 | 全公司架构(公开信息) |
| 人员信息查询 | 全员详细信息 | 本组个人信息 + 其他组公开信息 | 仅自己的信息 |
| 人员变动感知 | 全公司变动 | 本组变动 | 仅自己相关 |
⚠️ 当前状态:权限过滤尚未实现,所有用户可查所有数据。
越权查询引导
复用能力与全局约束
复用的现有能力、全局约束详见 Skill 清单 — 复用的现有能力 和 Skill 清单 — 全局约束。