Skip to content

SKILL 技能系统

本章目标:

  1. 理解 SKILL 是什么、为什么用"markdown + frontmatter"做技能而不是写代码插件
  2. 看懂 load_skills() 扫描/解析/启用判定流程与 public/custom 分层
  3. 知道 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.pySKILL.md frontmatter → Skill 对象deer-flow/backend/packages/harness/deerflow/skills/parser.py
types.pySkill 数据类型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.pyskill_evolution 时 LLM 安全扫描deer-flow/backend/packages/harness/deerflow/skills/security_scanner.py
validation.pyfrontmatter 校验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/随仓提交,通用21bootstrap、deep-research、ppt-generation、skill-creator、consulting-analysisdeer-flow/skills/public/
custom/a-cdm 自研业务技能11weekly-report、attendance-analysis、ba-analysis-pack、meeting-minutes-extractor/generator、pmo-report、team-lead-reportdeer-flow/skills/custom/

custom/ 是 a-cdm 业务能力的核心载体:

  • weekly-report / weekly-report-reviewer / monthly-report / pmo-report / team-lead-report:各类报告生成,与 pipeline 配合(config.yamlskills.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:5prime_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.jsonskills 段({"my-skill": {"enabled": true}}),配置缺失则默认启用(loader.py:98)。
  • .skill 压缩包可经 Gateway POST /api/skills/install 安装(installer.py),会解压到 custom/
  • 想让 Agent 自主创建/改 skill 需开 skill_evolution.enabled(config.yaml:907,a-cdm 默认关,开了会过 security_scanner LLM 安全扫描)。

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 自主进化开关
PageRelationship
deer-flow 引擎配置体系本章启用状态在该章 extensions_config.json 配置
Lead Agent 设计与图构建本章技能由该章 apply_prompt_template 注入
Agent 中间件链机制本章 SkillUsageMiddleware 计数在该章链 #12
子代理委派与确定性 Pipeline本章 weekly-report 等技能配合该章 pipeline
沙箱架构与文件工具本章技能经该章 /mnt/skills 虚拟路径被读取

公司内部参考 · 由 claude-wiki-gen 基于源码自动生成的二次分析