2026-03-27 · 实战
32
实战 · 2026-03-27

阿里开源钉钉 AI Skill 系统:一套给 AI Agent 的「钉钉操作手册」,到底藏了什么设计哲学?

TL;DR

🔧 阿里把钉钉全产品能力打包成了一套 AI Agent Skill——不是给人看的 API 文档,是给 AI 看的操作指南
🧠 核心设计:意图决策树 + 产品参考文档 + 批处理脚本,三层架构让 AI 精准理解「用户到底想干什么」
🔗 底层走 MCP 协议,所有响应结构化 JSON,AI 开箱即用
🛡️ 内建安全机制:危险操作必须人类确认,批量操作限 30 条
📦 12 个 Python 脚本覆盖考勤、日历、待办、通讯录等高频场景


这篇文章要聊什么

3 月下旬,阿里钉钉团队在 GitHub 上开源了 dingtalk-workspace-cli。一个 CLI 工具,用来操作钉钉工作台的所有功能。

CLI 工具本身不稀奇。真正值得拆解的是它附带的 skills/ 目录——这是阿里为 AI Agent 专门设计的一套 Skill 系统。

我花了几个小时把整个 skills 目录翻了个底朝天,发现一些有意思的设计模式。这些模式不只是「钉钉怎么接 AI」的问题,更是「怎么给 AI 写操作手册」的范式参考。


Skill 的目录结构

先看全景:

skills/
├── SKILL.md              # 主入口:AI 读这个文件就够了
├── references/
│   ├── products/          # 各产品的详细命令参考
│   │   ├── aitable.md     # AI 表格
│   │   ├── calendar.md    # 日历
│   │   ├── chat.md        # 群聊与机器人
│   │   ├── contact.md     # 通讯录
│   │   ├── todo.md        # 待办
│   │   ├── attendance.md  # 考勤
│   │   ├── report.md      # 日志
│   │   └── ...
│   ├── intent-guide.md    # 意图路由指南
│   ├── global-reference.md # 全局配置(认证/标志/输出)
│   ├── field-rules.md     # AI表格字段规则
│   └── error-codes.md     # 错误码 + 调试流程
├── scripts/               # Python 批处理脚本
│   ├── calendar_free_slot_finder.py
│   ├── todo_batch_create.py
│   ├── attendance_my_record.py
│   └── ...
├── LICENSE
└── NOTICE

这个结构本身就是一个设计决策。把它拆成三层看:

第一层:SKILL.md —— 单一入口真相源

AI Agent 只需要读这一个文件。它包含了「禁止做什么」「必须做什么」「产品总览表」「意图决策树」「核心流程」「错误处理」。这是整个 Skill 系统的索引。

第二层:references/ —— 按需加载的深度文档

SKILL.md 里不写具体命令参数。需要时通过文件引用指向 references/products/xxx.md。AI 判断出用户意图后,再去读对应产品文档。避免一次加载太多上下文。

第三层:scripts/ —— 可执行的自动化脚本

12 个 Python 脚本,处理那些需要多步编排的复杂场景。比如「查所有人的空闲时段找到可以开会的时间」——这种逻辑写在 SKILL.md 里太重了,抽成脚本更干净。


第一个亮点:意图决策树

SKILL.md 里最精彩的部分是意图判断决策树。它用关键词匹配的方式,帮 AI 快速定位用户需求:

用户提到"表格/多维表/AI表格/记录/数据"  → aitable
用户提到"审批/请假/报销/出差/加班"      → approval
用户提到"考勤/打卡/排班"              → attendance
用户提到"日程/日历/会议室/约会"         → calendar
用户提到"群聊/建群/群成员/机器人发消息"   → chat
用户提到"通讯录/同事/部门/组织架构"      → contact
用户提到"DING/紧急消息/电话提醒"       → ding
用户提到"日志/日报/周报"              → report
用户提到"待办/TODO/任务提醒"           → todo

看起来简单,实际上解决了 AI Agent 最头疼的问题——意图歧义

用户说「帮我建一个项目跟踪表」,是用 AI 表格还是待办?决策树给了明确答案:涉及结构化数据/行列操作 → aitable

用户说「帮我记一下明天要做的事」,个人待办提醒 → todo

钉钉团队还额外写了一份 intent-guide.md,专门处理易混淆场景。完整的对照表长这样:

用户说...
真实意图
应该用
不要用
理由

"帮我建一个项目跟踪表"
创建数据表格
aitable
todo
涉及结构化数据/行列操作

"帮我记一下明天要做的事"
创建待办
todo
aitable
个人待办提醒

"帮我看看收到的日报"
日志收件箱
report
todo
钉钉日志系统

"让机器人在群里发通知"
机器人群发
send-by-bot
send-by-webhook
企业内部机器人

"通过 Webhook 发告警到群里"
Webhook 告警
send-by-webhook
send-by-bot
自定义机器人

这种设计的本质是:不要让 AI 猜,直接告诉它边界在哪


第二个亮点:四步核心流程

SKILL.md 规定了 AI 处理用户请求的四步流程:

1. 意图分类 —— 判断用户指令的核心动词/动作属于哪一类
2. 歧义处理 —— 如果指令模糊或包含多个产品关键字,禁止猜测,必须追问
3. 精准映射 —— 意图清晰后,参考产品总览和决策树选择产品
4. 执行操作 —— 阅读产品参考文件,编写代码或直接调用指令

注意第 2 步:禁止猜测,必须追问

这是非常重要的设计原则。大部分 AI Agent 的问题不是「不够聪明」,而是「太自信」——用户说了一句模糊的话,AI 直接按自己理解执行,结果删错了数据。

钉钉的做法是强制 AI 在不确定时停下来问人。先把架势做足,确认清楚了再动手。


第三个亮点:严格的安全红线

SKILL.md 开头就列了两个清单:

严格禁止(NEVER DO):
- 不要用 dws 命令以外的方式操作(禁止 curl、HTTP API、浏览器)
- 不要编造 UUID、ID 等标识符,必须从命令返回中提取
- 不要猜测字段名/参数值,操作前必须先查询确认

严格要求(MUST DO):
- 所有命令必须加 --format json 以获取可解析输出
- 危险操作必须先向用户确认,用户同意后才加 --yes 执行
- 单次批量操作不超过 30 条记录

危险操作有明确的清单:

产品
命令
说明

aitable
base delete
删除整个 AI 表格

aitable
record delete
删除记录(支持批量)

calendar
event delete
删除日程

chat
group members remove
移除群成员

todo
task delete
删除待办

执行流程也固定死了:

Step 1 → 展示操作摘要(操作类型 + 目标对象 + 影响范围)
Step 2 → 用户明确回复确认
Step 3 → 加 --yes 执行命令

这套机制的设计哲学:AI 可以帮你做很多事,但删除操作永远需要人类拍板


第四个亮点:上下文传递表

每个产品参考文档里都有一个「上下文传递表」。以 AI 表格为例:

操作
从返回中提取
用于

base list/search
baseId
所有后续命令的 --base-id

base get
tables[].tableId
--table-id

table get
fields[].fieldId
record 操作的 cells key

record query
recordId
record update/delete

这解决了 AI Agent 的另一个核心难题:多步操作之间的数据流转

一个典型的工作流——「在 AI 表格里搜索项目,找到某张表,查字段结构,然后新增一条记录」——需要 4 次 API 调用,每次调用的参数依赖上一次的返回值。

上下文传递表把这条链路画清楚了。AI 只需要按表取值、传值就行。


第五个亮点:跨产品工作流

intent-guide.md 里还定义了跨产品编排模式。比如「约张三明天下午开会」:

# 1. 从通讯录搜索同事 userId
dws contact user search --query "张三" --format json

# 2. 创建日历日程
dws calendar event create --title "会议" \
  --start "2026-03-15T14:00:00+08:00" \
  --end "2026-03-15T15:00:00+08:00" --format json

# 3. 添加参与者(用 step 1 的 userId 和 step 2 的 eventId)
dws calendar participant add --event <EVENT_ID> \
  --users <USER_ID> --format json

三个不同的产品(contact → calendar → calendar participant),通过 ID 传递串联成一个完整的业务流程。

再比如「给张三建个待办」:

# 1. 搜索同事
dws contact user search --query "张三" --format json

# 2. 创建待办(用 step 1 的 userId)
dws todo task create --title "任务内容" \
  --executors <USER_ID> --format json

这种模式的抽象很漂亮:每个产品是独立的原子操作,跨产品编排通过 ID 粘合


脚本层:12 个 Python 批处理脚本

scripts 目录里有 12 个 Python 脚本,处理更复杂的场景。我挑一个最有代表性的来看——calendar_free_slot_finder.py,查找多人共同空闲时段。

# 用法
python calendar_free_slot_finder.py \
    --users userId1,userId2,userId3 \
    --date 2026-03-15 \
    --duration 60

这个脚本做了什么:

  1. 调用 dws calendar busy search 查询所有人的忙碌时段
  2. 合并重叠的忙碌区间(区间合并算法)
  3. 从工作时间(默认 9:00-18:00)中扣除忙碌区间
  4. 找到满足会议时长要求的空闲窗口
  5. 按时间排序输出,第一个标记为「⭐ 推荐」

输出长这样:

🕐 空闲时段查询 (2026-03-15)
   参与人: 3 人
   会议时长: 60 分钟
   工作时间: 9:00 ~ 18:00
==================================================

✅ 找到 2 个可用时段:

  ⭐ 推荐  10:00 ~ 12:00  (120分钟)
     备选1  15:30 ~ 18:00  (150分钟)

它还支持 --dry-run 模式,只打印要执行的 dws 命令但不真正调用。整个脚本不到 200 行。

其他脚本覆盖的场景包括:

脚本
功能

todo_batch_create.py
批量创建待办

todo_daily_summary.py
待办每日摘要

todo_overdue_check.py
逾期待办检查

attendance_my_record.py
个人考勤记录

attendance_team_shift.py
团队排班查询

calendar_schedule_meeting.py
预约会议

calendar_today_agenda.py
今日日程

contact_dept_members.py
部门成员查询

report_inbox_today.py
今日收到的日志

import_records.py
批量导入记录

bulk_add_fields.py
批量添加字段

upload_attachment.py
上传附件


底层架构:发现驱动的管道

DWS CLI 本身的架构也值得说一嘴。它不硬编码任何产品命令,而是用「发现驱动管道」动态注册:

Market Registry ──► Discovery ──► IR ──► CLI (Cobra) ──► Transport (MCP JSON-RPC)
      │                  │
      ▼                  ▼
mcp.dingtalk.com    缓存(TTL + 过期降级)

五个阶段:

  1. Market —— 从 mcp.dingtalk.com 获取 MCP 服务注册表
  2. Discovery —— 解析运行时能力,支持磁盘缓存和离线降级
  3. IR(中间表示) —— 规范化为统一的产品/工具目录
  4. CLI —— 挂载到 Cobra 命令树,映射 flag 到 MCP 输入参数
  5. Transport —— 执行 MCP JSON-RPC 调用,支持重试和认证注入

这意味着钉钉后端新增了一个产品,CLI 不需要改代码。只要 MCP 注册表里加了服务描述,dws 自动发现并生成对应的命令行接口。


对我们的启示:怎么给自己的项目写 Skill

把钉钉的 Skill 设计拆解完,几个可以直接借鉴的模式:

1. 单一入口 + 按需加载

SKILL.md 是唯一入口。AI 读完它就知道有哪些能力、怎么选择。详细参数放在子文件里,需要时再读。这比把所有内容塞进一个巨大的 prompt 要高效得多。

2. 意图决策树先行

不要直接列命令。先回答"用户说了什么 → 应该用哪个工具"的映射关系。特别是要把易混淆的场景显式列出来。

3. 上下文传递表是必须的

多步操作的每一步,输入从哪来、输出传给谁,用表格画清楚。AI 不需要理解业务逻辑,只需要按表索骥。

4. 安全红线写在最前面

NEVER DO 和 MUST DO 放在文档最开头。让 AI 先知道不能做什么,再知道能做什么。

5. 危险操作走确认流程

任何删除、修改操作,强制走「展示摘要 → 用户确认 → 执行」三步。不要相信 AI 的判断力。

6. 复杂逻辑抽脚本

SKILL.md 里写流程描述,Python 脚本里写实现逻辑。AI 判断意图后直接调脚本,不用自己生成代码。


安装和使用

想把钉钉 Skill 装到自己的 AI Agent 项目里,一行命令:

# 安装到当前项目
curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install-skills.sh | sh

装完之后在 ./.agents/skills/dws/ 目录下就能看到完整的 SKILL.md 和参考文件。

注意,当前项目还在灰度共创阶段。需要企业管理员授权,加入钉钉 DWS 共创群提供 Client ID 完成白名单配置。


最后

钉钉这套 Skill 系统最值得学习的不是「钉钉 API 怎么调」,而是「怎么用文档驱动 AI Agent 的行为」

意图决策树解决了 AI「听不懂」的问题。上下文传递表解决了 AI「接不上」的问题。安全确认机制解决了 AI「管不住」的问题。

三个问题解决了,AI Agent 就从「聊天机器人」变成了「数字员工」。

全部代码开源在 GitHub:dingtalk-workspace-cli/skills

目录 最新
← 左侧翻上一屏 · 右侧翻下一屏 · 中间唤出菜单