Skip to content

钉钉组织架构识别

清海接入多燕瘦钉钉环境的第一步:通过钉钉通讯录 API 认识公司每个人,为后续销售管理场景提供身份基础。 角色维度的会话旅程见 角色场景,能力定义见 Skill 清单


背景与现状

多燕瘦使用钉钉作为主要协同工具,清海需要通过钉钉通讯录建立组织感知能力。与飞书版本的核心差异在于:钉钉支持实时事件订阅,人员变动可实时推送而无需依赖定时轮询;同时钉钉的用户 ID 体系(userid 为企业内主键)与飞书(open_id 为主键)有所不同。

维度说明
数据源钉钉通讯录 API(新旧版并用,优先旧版字段完整性)
团队规模多燕瘦销售团队,10-100 人,多层级部门
部门结构公司 → 部门(销售部/运营部/产品部…)→ 销售小组
通道钉钉企业内部应用机器人
用户识别机器人消息携带 senderStaffId(即 userid),企业内唯一
同步策略每日全量同步一次 + 实时事件订阅补偿(人员变动即时更新)
存储MongoDB unified_users 集合 + PersonIndex 内存索引 + 本地缓存 data/cache/dingtalk_contacts.json

钉钉 API 版本选择

版本HostToken 传递用户主键推荐场景
旧版oapi.dingtalk.comURL 参数 ?access_token=userid通讯录读取(字段最完整,文档成熟)
新版api.dingtalk.comHeader x-acs-dingtalk-access-tokenunionId新功能、OAuth 场景

本方案通讯录部分优先使用旧版 APImanager_userid(直属上级)、leader_in_dept(是否部门主管)等关键字段仅旧版完整返回。

已实现 vs 待实现

能力状态说明
钉钉通讯录同步⬜ 待实现需新建 DingTalkSync.sync_contacts()
PersonIndex 内存索引✅ 复用已有实现,扩展 channels.dingtalk 即可
PersonContextResolver✅ 复用已有实现
身份自动识别⬜ 待实现需适配 senderStaffIduserid 匹配
search_contacts 工具✅ 复用底层 PersonIndex 相同,无需改动
别名学习 / 平台绑定✅ 复用save_contact_alias + link_platform_identity
事件订阅接收端点⬜ 待实现钉钉特有,飞书版本无对应
人员变动实时更新⬜ 待实现基于事件订阅,优于飞书轮询方式
权限过滤⬜ 待实现与飞书版本一致,按角色分层

当前设计方式

本场景组织架构识别在系统层自动完成,AI 通过通用工具 search_contacts 查询人员信息。

钉钉消息进来

avatar_core.identify_user()

PersonContextResolver.resolve_by_channel("dingtalk", userid)  ← 从 unified_users 读组织信息

system prompt Block 1: "你正在和张三对话,他是销售一组的销售经理"  ← 身份注入

AI 对话(如果用户问组织问题)

AI 调用 search_contacts(query="销售部", department=...)  ← 组织查询工具

PersonIndex.search() → 返回结果

场景与能力总览

钉钉组织架构识别覆盖 4 大会话场景

场景 → 能力映射表

场景触发方式需要的能力钉钉 API
身份自动识别收到任意消息时自动触发通讯录同步 + PersonIndex + userid 解析POST /topapi/v2/user/get(按 userid 查详情)
组织架构查询用户主动询问PersonIndex 部门查询POST /topapi/v2/department/listsub
人员信息查询用户主动询问PersonIndex 人员查找 + PersonContextPOST /topapi/v2/user/list
人员变动感知钉钉事件推送(实时)+ 每日全量同步兜底事件订阅 + 通讯录同步事件:user_add_org / user_leave_org / user_modify_org

能力触发机制

钉钉消息进来 → 身份自动识别(每条消息必经,avatar_core 自动完成)
             → AI 判断用户意图涉及组织查询
             → 调用 search_contacts / query_org_structure 工具
             → PersonIndex.search() → 整理结果 → 回复用户

钉钉事件推送 → 事件接收端点(HTTP 回调)
             → 解析 user_add_org / user_leave_org / user_modify_org
             → 更新 unified_users + 重建 PersonIndex

场景一:身份自动识别

核心价值:员工在钉钉发消息时,清海自动知道对方是谁,带入身份认知。

识别流程

钉钉机器人消息 ID 字段

字段类型说明
senderStaffIduserid(企业内唯一)主键,企业内部机器人必有此字段
senderUnionIdunionId(全局唯一)新版消息有,可与旧版 userid 互转
senderId加密 openId格式 $:LWCP_v1:$xxx,通常不用

实践建议:直接用 senderStaffId(即 userid)匹配 unified_users.channels.dingtalk.userid,无需转换。

存储字段(unified_users.channels.dingtalk

来自 POST https://oapi.dingtalk.com/topapi/v2/user/get

钉钉 API 字段存储位置用途
useridchannels.dingtalk.userid消息身份匹配主键(= senderStaffId
unionidchannels.dingtalk.unionid全局唯一标识,备用
namedisplay_name显示名称
dept_id_listchannels.dingtalk.dept_id_list所属部门(关联部门树)
titlechannels.dingtalk.job_title职位
manager_useridchannels.dingtalk.manager_userid直属上级 userid
leader_in_deptchannels.dingtalk.is_manager是否是部门主管
bosschannels.dingtalk.is_boss是否是企业 Boss
hired_datechannels.dingtalk.hired_date入职时间
mobilechannels.dingtalk.mobile手机号(需申请权限)

关键约束

  • senderStaffId 在企业内唯一且稳定,识别准确率 100%
  • 员工离职后通过事件 user_leave_org 实时将 is_active 设为 False
  • 离职员工消息触达静默处理(不回复)
  • senderStaffId 为空(自定义机器人场景),降级使用 senderUnionId 查询

场景二:组织架构查询

核心价值:自然语言查询公司组织结构,不用打开钉钉通讯录。

典型对话

用户问法清海应答需要的能力
"公司有哪些部门"列出所有部门(名称 + 人数)部门列表查询
"销售部有谁"列出销售部全部成员(姓名 + 职位)部门成员查询
"销售部下面有几个组"列出子部门结构部门树递归
"一组几个人"返回人数 + 成员列表部门成员查询

钉钉 API 数据来源

查询类型钉钉 API关键参数
子部门列表POST /topapi/v2/department/listsubdept_id(根部门为 1,仅返回一级,需递归)
全量部门列表POST /topapi/department/list一次返回所有部门(旧版,同步用)
部门成员列表POST /topapi/v2/user/listdept_idcursor(游标分页)、size(每页最多 100)
部门返回字段dept_idnameparent_id
成员返回字段useridnametitledept_id_listmanager_userid

关键约束

  • 钉钉根部门 dept_id = 1(飞书是 "0"),递归时注意
  • 部门名支持模糊匹配:「一组」→「销售一组」
  • 兼职/多部门人员以 dept_id_list[0] 主部门为准
  • 分页用游标:cursor 从 0 开始,has_more=true 时继续翻页

场景三:人员信息查询

核心价值:快速了解某人的部门、职位、上下级,无需翻钉钉通讯录。

典型对话

用户问法清海应答需要的能力
"张三是什么部门的"张三的部门 + 职位search_contacts(query="张三")
"张三的上级是谁"张三的直属上级(manager_userid 关联查询)query_person_relations
"李四管哪些人"李四的直属下属列表query_person_relations(relation_type="members")
"小明是谁"模糊匹配结果(可能多个)search_contacts(query="小明")

上级关系查询流

关键约束

  • 人名模糊匹配:PersonIndex 支持部分名、别名
  • manager_userid 直接存储了上级 userid,无需额外 API 调用(同步时已关联)
  • leader_in_dept 字段标识该用户是否是某部门的主管(可能同时是多部门主管)
  • 多结果时列出选项让用户确认

场景四:人员变动感知

核心价值:实时感知入职、离职、调岗,保持组织数据准确。 与飞书版本的关键差异:钉钉支持事件订阅推送,无需单纯依赖轮询

变动类型与处理

变动类型钉钉事件检测方式清海处理
新员工入职user_add_org事件推送(实时)自动创建 unified_users 记录 + 更新 PersonIndex
员工激活账号user_active_org事件推送(实时)更新 is_active=True
员工信息变更user_modify_org事件推送(实时)更新字段,保留别名等非钉钉数据
员工离职user_leave_org事件推送(实时)is_active=False + 消息静默
新增部门org_dept_create事件推送(实时)自动触发该部门成员同步
部门信息变更org_dept_modify事件推送(实时)更新部门名/层级 + 重建索引
部门删除org_dept_remove事件推送(实时)将该部门成员设为无部门,等待下次全量同步

双重保障策略

事件订阅配置

在钉钉开发者后台:应用 → 事件与回调 → 订阅以下事件类型,配置公网可访问的回调地址。

订阅事件含义
user_add_org新员工加入企业
user_active_org员工激活账号
user_modify_org员工信息变更
user_leave_org员工离职
org_dept_create部门新增
org_dept_modify部门信息变更
org_dept_remove部门删除

关键约束

  • 钉钉通讯录数据为权威源(authoritative_sync),覆盖推断和观察数据
  • 同步时保留 aliases、平台绑定等非钉钉来源数据
  • 事件推送网络异常时,下次全量同步自动补偿
  • 事件 payload 中仅含 userid,需调 API 获取最新用户详情

角色权限与场景覆盖

不同角色在各场景中的可见范围不同,详见 角色场景

角色 × 场景矩阵

场景老板 / 总监销售经理销售员工
身份自动识别全员信息全员信息仅自己(系统自动)
组织架构查询全公司架构 + 人员明细全公司架构 + 本组人员明细全公司架构(公开信息)
人员信息查询全员详细信息本组个人信息 + 其他组公开信息仅自己的信息
人员变动感知全公司变动本组变动仅自己相关

⚠️ 当前状态:权限过滤尚未实现,所有用户可查所有数据。

越权查询引导


与飞书版本的核心差异

维度飞书版本钉钉版本
用户主键open_idou_ 开头)useridsenderStaffId
Bot 消息 ID 字段open_idsenderStaffId
同步策略定时轮询(30 分钟)事件订阅(实时)+ 每日全量兜底
上级关系通讯录 API 返回 leader_user_idmanager_userid 字段直接返回
离职检测轮询时检测 status.is_resigned事件 user_leave_org 实时推送
部门根节点parent_department_id=0dept_id=1
部门 ID 字段open_department_idod- 开头)dept_id(整数)
通道前缀channels.feishuchannels.dingtalk

复用能力与全局约束

复用的现有能力、全局约束详见 Skill 清单 — 复用的现有能力Skill 清单 — 全局约束

Boss-AGI · 超级 AI 企业助理