Skip to content

CH 14 · Skill 与工作流

全文字数4736 字预估耗时约 25 分钟前置CH 08、CH 13难度可照做

本章目标

前面你让 Agent 干一件事,得每次把要求说清楚。可有些活步骤是固定的——像 CH 05 跑过的"总结一个仓库、落成文档",或写周报、整理资料这类日常任务,每次都从头把流程交代一遍,太浪费了。这类事值得做成"一张说明书":告诉 Agent"遇到这类活,就按这套步骤来"。这就是 Skill。这一章讲清楚 dsh 的 Skill 是什么、从哪来、模型怎么用它,然后装一个现成的 Skill 拿来即用——只要给 Agent 一句话,它自己会装——让它变成你专属的"可复用能力"。

一个关键事实:Skill 也是插件

跟 MCP、子代理一样,Skill 在 dsh 里不是独立入口,它又是一组插件的组合。看配置树,skill 能力族由四块拼成:

插件干什么对应角色
dsh-skill注册表:合并各来源的 skill 目录,按名称解析出"胜出"的那个仓库管理员
dsh-skill-filesystem从项目、用户目录里发现本地 skill,并监视文件变化采买员
dsh-tool-skill把可用 skill 列表展示给模型,提供 skill 加载工具前台
dsh-skill-badge随包附带的官方徽章 skill,默认禁用装饰

web 配置里这四件默认都装了——所以你现在就能用,不用装任何东西。这又是 CH 08 那句"一切皆插件":连"可复用能力"本身,也是由插件拼出来的。

Skill 是什么:写好的"怎么做一件事"

工具是 Agent 能"调用"的动作(读写文件、搜网页);Skill 是写给 Agent 的"说明书"——一组任务专项指令,告诉它"遇到这类任务,按这套步骤做"。

两者最大的区别在复用性:工具是系统提供的,Skill 是你自己攒的。你在某件事上摸索出一套好用的做法,写成一个 Skill,从此 Agent 遇到同类活,不用你再把要求重复一遍。而且 skill 跟着存放位置走:放在项目里的 .dsh/skills 是项目级,只对这个项目生效;放在用户目录 ~/.dsh/skills 是全局级,任何项目都能用——下一节"五个货架"会看到完整的层级。

那"工作流"呢:Skill 就是最简单的工作流

一句话先记住:一个 Skill 就是最简单的工作流。工作流的本质是"把人的经验固化成流程"——而一个 Skill 恰好就是这么干的:输入明确、输出明确、步骤固定,可以被单独复用。它就是一个被压缩到单个任务的小流程。

区别在粒度。Skill 管"单个任务怎么做"(一道菜的菜谱);Workflow 管"多个任务怎么按顺序串起来"(从买菜、洗菜到上桌的整条流水线,还要管分支、衔接、谁先谁后)。dsh 的 Standard 预设里,"技能"和"工作流"就是并列的两个工具——单步固定套路用 Skill 就够,多步串联才需要 Workflow。

把两者摆一起,差异更清楚:

维度SkillWorkflow
管什么单个任务"怎么做"多个任务"按什么顺序串"
粒度一步固定套路多步流水线
分支与衔接不负责负责(条件、衔接、谁先谁后)
复用方式单个独立复用需要时重新编排
类比一道菜的菜谱从买菜到上桌的整条流水线

所以当你只为一个固定任务写了一个 Skill,你其实已经搭好了"最简单的工作流"。

Skill 长什么样

一个 Skill 就是一个带 frontmatter 的 Markdown 文件,标准形态是一个目录 bundle:文件夹名就是 skill 名,里面必须有 SKILL.md——适合要带配套资源(脚本、参考文档、素材)的 skill。

名字必须是小写 kebab-case(^[a-z0-9]+(?:-[a-z0-9]+)*$),比如 code-reviewweekly-report

一个标准的目录 bundle 长这样:

text
code-review/
├── SKILL.md        # 必需:frontmatter + 指令正文
├── scripts/        # 可选:配套脚本(.py / .sh 等)
├── references/     # 可选:参考文档、检查清单模板
└── assets/         # 可选:素材、示例文件

SKILL.md 是唯一必需的文件,正文里可以用相对路径引用 bundle 里的脚本和参考文档。最小结构长这样:

markdown
---
name: code-review
description: 按统一清单审查一段代码,输出结构化评审意见
whenToUse: 用户要求"审查代码"或"code review"时
---

# 代码审查

按下面的顺序来:

1. 先读相关 README,弄清这段代码要解决的问题;
2. 列出公开的导出与主要函数,标注每个的作用;
3. 找明显的风险点:错误处理、边界条件、敏感信息;
4. 用表格输出:文件 / 问题 / 严重程度 / 建议。

frontmatter 里只有 namedescription 是必填的,其他字段都可选:

字段作用
nameSkill 的唯一名字(kebab-case,必填)
description一句话描述,模型靠它判断"这活跟我不对口"(必填)
whenToUse额外的使用时机提示(可选)
disable-model-invocation设为 true:只许用户用 /名字 调,模型不能自动加载(可选)
user-invocable设为 false:只许模型调,用户不能 /名字 调(可选)

两个开关:谁能调它

frontmatter 里两个字段管"谁能调":

组合效果
都不写模型和用户都能调(默认)
disable-model-invocation: true只许用户 /名字 调;模型目录和 skill 工具里看不到它——适合放敏感或高成本流程,防止模型随手触发
user-invocable: false只许模型调;用户 /名字 无效
两个都关只能被可信代码直接调用,模型和用户都碰不到

Skill 从哪来:五个"货架"

先分清两件事:这一节讲的是 dsh 从哪里读到 skill——即 skill 放在本地的哪个目录能被发现。dsh 用 dsh-skill-filesystem 这个插件按固定顺序扫几个根目录,把里面的 skill 收进注册表。"安装新 skill"是另一件事:去社区技能市场(比如腾讯的 SkillHub)或 dsh 插件市场,把别人写好的 SKILL.md 安装进这些货架目录——后面"装一个现成的 Skill"一节就是干这个。

dsh-skill-filesystem 会按固定顺序扫几个根目录,把里面的 skill 收进注册表。越靠上的优先级越高——同名 skill 出现在多个货架时,排前面的赢:

优先级目录谁放这
1<项目根>/.dsh/skills跟着项目走,随仓库一起分发
2<项目根>/.agents/skills兼容其他工具(如 Claude Code)的共享位置
3配置里的自定义目录 customSkillDirs你手动指定的其他位置
4<dshHome>/skills~/.dsh/skills用户级,所有工作区都能用
5<agentsHome>/skills~/.agents/skills与其他 Agent 工具共享的用户级目录

模型怎么"看见" Skill

Skill 是写给模型看的,它怎么知道有哪些?这套机制由 dsh-tool-skill 插件提供,web 配置默认装好(dsh --profile web --dump-config 里能看到它)。靠三个机制配合:

  1. 会话目录:会话开始、第一个请求之前,模型会收到一条持久消息,列出所有可用 skill 的名字和一句话描述,并被告知"动手前先加载匹配的 skill,不要凭摘要瞎猜"。
  2. skill 工具:模型判断某个 skill 对口时,用 skill({ name }) 加载完整指令正文——正文以 <skill_content> 块返回,作为工具结果留在历史里。下图是一张真实轨迹:模型先调 skill 工具加载 aihot 的完整指令,再调 pwsh 跑验证请求,两条工具调用在轨迹里一目了然。

aihot 安装与调用的会话轨迹:skill 工具加载 + pwsh 验证 3. 用户手势 /名字:你在输入框直接打 /code-review,该 skill 的指令会以用户消息的形式注入这一轮,模型照着做就行。注意:这个名字必须真实存在于工作区货架里、且允许用户调用——输入一个不存在的 skill 名,会被当成普通文字,没有任何反应。

Skill 的流转:货架 → 注册表 → 会话目录 → 模型或用户

一个细节:用户 /名字 注入后,模型不会再用 skill 工具重复加载一次——避免同一个指令被塞两遍、白烧 token。

如果问模型"你现在有哪些 skill"它报不出来,先确认 web 配置里有 @deepseek-ai/dsh-tool-skill 这个插件(dsh --profile web --dump-config 一看便知)。

动手:装一个现成的 Skill(拿来用)

装现成 skill 的本质,就是把别人写好的 SKILL.md 放进 dsh 的"货架"目录(通常是项目级 .dsh/skills)——社区里已经有一大批写好的 skill 可以直接拿。

这里以 aihot 为例:它是由知名 AI 科技博主"数字生命卡兹克"出品的检索类 skill,擅长抓取每日 AI 新闻与行业动态。

第 1 步:给 Agent 一句话,让它帮你装

不用自己找文件、建目录。回到对话,直接说:

请安装 AIHOT Skill:https://aihot.virxact.com/aihot-skill/README.md 装完告诉我是否需要开启新会话。 安装器支持时请追加:--actor 你的Actor ID

--actor 后面的 ID 是 AIHOT 平台注册后分配给你的,装完会写进本地的 .aihot-actor-id,Agent 请求时会带上做身份标识。

Agent 会自己动手:去官网把 AIHOT 的 SKILL.md 和配套文件下载下来,放进 DSH 的标准发现位置(~/.agents/skills/aihot/),逐一做 SHA-256 完整性校验、写入 actor 配置、生成 .gitignore,装完把结果报告给你。装完后不需要新开会话——它已经出现在当前会话的 <available_skills> 目录里,直接就能用。

AIHOT Skill 安装完成:安装位置、完整性校验、Actor 与生效确认

第 2 步:让模型报出新 Skill

回到对话,问:

你现在有哪些 skill?aihot 这个 skill 是干什么的?

模型会把它报出来——你一行代码没写,就多了一个可复用能力。它还会顺带告诉你这个 skill 具体能干什么(aihot 通过 AIHOT 的匿名只读 API 查询当下真实的中文 AI 资讯,而不是用训练记忆"编"新闻)。

对话里模型报出 aihot:可用列表 + 功能说明

第 3 步(可选):让模型用它

直接说"用 aihot 抓一下今天有哪些 AI 新闻",模型会加载这个 skill 去抓取。别人沉淀好的检索流程,现在变成了你的能力——这就是"拿来用"。

用 aihot 抓取今日 AI 新闻:模型给出"过去 24 小时 AI 圈重点"

常见坑

怎么避开
忘了 description必填字段缺失,整个 skill 会被警告后丢弃
目录层级放错只认 <根>/<名字>/SKILL.md<根>/<名字>.md 一层,别往深层嵌套
模型不主动用description 写清楚"什么时候用它"(whenToUse 也有帮助);实在不放心就用 /名字 直接注入
改了正文但模型没反应正文改动不影响目录摘要,要让模型"重新加载"一次;改 description 这种摘要字段才会立刻反映到目录

这一章你学到了什么

能自己完成下面几条,就算过关:

  • [ ] 说出 Skill 是"写给 Agent 的可复用指令",与工具的区别在复用性
  • [ ] 知道 Skill 在 dsh 里也是插件(skill 注册表 + 文件系统发现 + 工具消费方)
  • [ ] 能说出一个 Skill 的结构(frontmatter 里 name / description 必填,whenToUse 可选)
  • [ ] 知道五个货架的优先级(项目 .dsh/skills 最优先,用户目录次之,可跨项目使用)
  • [ ] 跑通过一次"给 Agent 一句话 → 它装好 skill → 模型报出 → 模型加载使用"
  • [ ] 分清 disable-model-invocationuser-invocable 两个开关

Open Source · MIT · Community Driven