主题
SKILL 技能系统
本章目标:
- 理解 SKILL 是什么、为什么用"markdown + frontmatter"做技能而不是写代码插件
- 看懂
load_skills()扫描/解析/启用判定流程与 public/custom 分层- 知道 a-cdm 自研了哪些 custom skill,以及怎么写一个新 skill
TL;DR
SKILL 是一段带 YAML frontmatter 的 markdown,告诉 Agent "遇到某类任务该怎么做"。load_skills()(skills/loader.py:26)递归扫描 deer-flow/skills/{public,custom}/ 下的 SKILL.md,用 parser.py 解析 frontmatter(name/description/allowed-tools/dependency),从 extensions_config.json 读启用状态,启用的技能被注入 Agent 系统提示。a-cdm 自研了 11 个 custom skill(weekly-report、attendance-analysis、ba-analysis-pack、meeting-minutes-extractor 等),它们是 a-cdm 业务能力的载体。
Overview(为什么技能是"markdown"而不是"代码插件")
让 Agent 会做"周报""考勤分析""会议纪要抽取"这类专门任务,有两条路:写 Python 插件,或者写一段说明书让 LLM 自己照着做。deer-flow 选后者——SKILL = 给 LLM 看的 markdown 操作手册:
- 写技能不需要懂框架内部、不用改代码、不用重部署,产品/业务人员也能写;
- 技能内容是自然语言流程,LLM 直接理解执行,工具调用照
allowed-tools约束; - public(随仓提交)/custom(可 gitignore)分层,a-cdm 的业务技能放 custom。
这与 a-cdm "智能体成为同事"的愿景一致:同事的"专业能力"应该像 SOP 文档一样可读可改,而不是黑盒代码。skill_evolution(config.yaml:907)甚至允许 Agent 自主写 skill(a-cdm 默认关闭,需安全审查)。
Architecture:skills 包组成
| 文件 | 职责 | Source |
|---|---|---|
loader.py | 扫描 + 解析 + 启用判定 | deer-flow/backend/packages/harness/deerflow/skills/loader.py:26 |
parser.py | SKILL.md frontmatter → Skill 对象 | deer-flow/backend/packages/harness/deerflow/skills/parser.py |
types.py | Skill 数据类型 | deer-flow/backend/packages/harness/deerflow/skills/types.py |
manager.py | 技能管理(启用/禁用) | deer-flow/backend/packages/harness/deerflow/skills/manager.py |
installer.py | .skill 压缩包安装到 custom/ | deer-flow/backend/packages/harness/deerflow/skills/installer.py |
usage_tracker.py | 调用计数(配合 SkillUsageMiddleware) | deer-flow/backend/packages/harness/deerflow/skills/usage_tracker.py |
security_scanner.py | skill_evolution 时 LLM 安全扫描 | deer-flow/backend/packages/harness/deerflow/skills/security_scanner.py |
validation.py | frontmatter 校验 | deer-flow/backend/packages/harness/deerflow/skills/validation.py |
load_skills(skills_path, use_config, enabled_only)(loader.py:26-103):遍历 ["public","custom"] 两个 category(loader.py:62),递归找含 SKILL.md 的目录(loader.py:70-73),解析后从 extensions_config.is_skill_enabled(name, category) 更新 enabled(loader.py:93);配置加载失败则默认全启用(loader.py:98,容错);enabled_only=True 时过滤(loader.py:102-103)。
Components:public vs custom 技能
deer-flow/skills/ 两层:
| category | 性质 | 数量 | 代表 | Source |
|---|---|---|---|---|
public/ | 随仓提交,通用 | 21 | bootstrap、deep-research、ppt-generation、skill-creator、consulting-analysis | deer-flow/skills/public/ |
custom/ | a-cdm 自研业务技能 | 11 | weekly-report、attendance-analysis、ba-analysis-pack、meeting-minutes-extractor/generator、pmo-report、team-lead-report | deer-flow/skills/custom/ |
custom/ 是 a-cdm 业务能力的核心载体:
weekly-report/weekly-report-reviewer/monthly-report/pmo-report/team-lead-report:各类报告生成,与 pipeline 配合(config.yaml的skills.weekly-report.enabled: true)。meeting-minutes-extractor/meeting-minutes-generator/meeting-aggregator-realtime:会议纪要抽取与聚合,与会议域/洞察引擎对接。attendance-analysis:考勤分析,是allow_host_bash: true要支持的自研 skill 之一(见沙箱章)。ba-analysis-pack:BA 报告分析包。playwright-page-cleaner:配合 demoo_service 的录屏清洗。
SKILL.md 格式(deer-flow/skills/public/chart-visualization/SKILL.md:1-7):YAML frontmatter name/description/可选 dependency/allowed-tools,正文是 ## Workflow 等自然语言步骤。description 是 LLM 选技能的依据(写"This skill should be used when..."),正文是执行 SOP。
Data Flow:技能从加载到执行
技能注入点是 apply_prompt_template(Lead Agent 章):启用技能的 name + description + 容器路径(/mnt/skills/<name>)进系统提示,LLM 看到后按 description 判断是否用,用时通过文件工具读 /mnt/skills/<name>/SKILL.md 的正文照做。SkillUsageMiddleware(中间件链 #12)记调用次数。agents/__init__.py:5 的 prime_enabled_skills_cache 在 import 时预热缓存避免同步文件 IO。
单个 skill 的状态:
扩展指南:写一个新 skill
markdown
# deer-flow/skills/custom/my-skill/SKILL.md
---
name: my-skill
description: This skill should be used when the user wants to <触发场景>. <做什么的一句话>
allowed-tools: [read_file, write_file, bash] # 可选,限制此 skill 可用工具
dependency: # 可选
nodejs: ">=18.0.0"
---
# My Skill
## Workflow
1. 第一步……(自然语言 SOP,LLM 照着做)
2. 第二步……约束(从代码读出):
- 目录放
skills/custom/<name>/,文件名必须SKILL.md(loader.py:70-73只认这个名)。 - frontmatter 经
validation.py校验;name是唯一标识,description决定 LLM 何时选它(写清"when to use")。 - 启用状态在
extensions_config.json的skills段({"my-skill": {"enabled": true}}),配置缺失则默认启用(loader.py:98)。 .skill压缩包可经 GatewayPOST /api/skills/install安装(installer.py),会解压到custom/。- 想让 Agent 自主创建/改 skill 需开
skill_evolution.enabled(config.yaml:907,a-cdm 默认关,开了会过security_scannerLLM 安全扫描)。
Common Pitfalls / 实战 Tips
- description 决定能不能被选中:写得含糊 LLM 不会用它。参考 public 技能的 "This skill should be used when..." 句式。
- custom/ 可能 gitignore:a-cdm monorepo 模式下
deer-flow/skills/是 track 的(部署靠 cd-poll rsync skills/),但要确认目标 skill 已提交,否则生产没有。 - 配置加载失败默认全启用:
loader.py:98是容错设计,但意味着extensions_config.json坏掉时所有技能都开,不是"安全关闭"。 - allowed-tools 是约束不是赋能:不写 = 用 agent 全部工具;写了 = 只能用列出的。别指望写了它就能用没装配的工具。
References
deer-flow/backend/packages/harness/deerflow/skills/loader.py:26-103— 扫描/解析/启用判定(本章主源)deer-flow/backend/packages/harness/deerflow/skills/parser.py— SKILL.md frontmatter 解析deer-flow/skills/public/chart-visualization/SKILL.md:1-7— SKILL.md 格式样例deer-flow/skills/custom/— a-cdm 11 个自研业务技能deer-flow/config.yaml:802-811— skills 目录配置(host/容器路径)deer-flow/config.yaml:907-909— skill_evolution 自主进化开关
Related Pages
| Page | Relationship |
|---|---|
| deer-flow 引擎配置体系 | 本章启用状态在该章 extensions_config.json 配置 |
| Lead Agent 设计与图构建 | 本章技能由该章 apply_prompt_template 注入 |
| Agent 中间件链机制 | 本章 SkillUsageMiddleware 计数在该章链 #12 |
| 子代理委派与确定性 Pipeline | 本章 weekly-report 等技能配合该章 pipeline |
| 沙箱架构与文件工具 | 本章技能经该章 /mnt/skills 虚拟路径被读取 |