先看一个典型场景。如果智能体已经有下面这些工具:
- 文件工具
- Shell
- 网页检索
- MCP(Model Context Protocol,模型上下文协议)
- 其他工具
但你希望它每次处理某类任务时,都按照一套稳定的方法和规则执行——这类需求很适合 skill(技能)。
先纠正一个叫法:技能不是一定要「安装」
本地 skill 最常见的使用方式是:在 DSH 能发现的位置创建 Markdown 文件。所以这篇教程的标题是「创建、发现与使用」,而不是「技能安装教程」。
例如项目级技能可以直接放到 .dsh/skills/ 目录下面。只要格式正确,当前本地 skill 提供方就可以发现它。
技能格式与基础字段
推荐使用目录形式组织一个技能:
.dsh/
└── skills/
└── seo-audit/
└── SKILL.md
其中 SKILL.md 可以先写成:
---
name: seo-audit
description: 检查网页或项目中的 SEO 基础问题,并按优先级输出修复建议。
---
# SEO Audit
执行 SEO 审计时:
1. 先确认页面目标搜索意图。
2. 检查 Title 和 Description。
3. 检查 H1 与正文结构。
4. 检查 canonical。
5. 检查内部链接。
6. 将问题分为 P0、P1、P2。
7. 不确定的事实明确标注待核验。
这里最重要的是三样东西:
namedescription- 正文指令
name 有什么要求?
当前 skill 名称要求 kebab-case(小写字母、数字加连字符的命名风格),也就是只使用小写字母、数字和连字符。
seo-audit
github-review
content-research
SEO Audit
seo_audit
SeoAudit
当前名称规则可以概括为:
^[a-z0-9]+(?:-[a-z0-9]+)*$
description 为什么很重要?
当前面向模型的 skill 目录只会把名称和 description 摘要展示给模型,不会一开始就把所有 SKILL.md 正文全部塞进模型上下文。所以模型初步判断「这个任务是不是应该加载某个 skill」时,主要依据就是 skill 名称和 description。
因此 description 不应该只写:
SEO 工具
更适合写:
检查网页或项目中的 SEO 基础问题,并按优先级输出修复建议。
因为它更清楚地说明了什么任务适合使用这个技能。
description 写得好,就一定会自动调用吗?
不能这样保证。当前 DSH 会把 skill 目录告诉模型,并在目录指引里要求:如果用户明确点名 skill,或者任务明显匹配某个 skill 的 description,应先调用 skill 工具加载完整指令。
但最终是否在一个自然语言任务中主动选择该 skill,仍然涉及模型判断。
技能正文什么时候进入模型上下文?
不是发现 skill 的时候。当前机制大致是:
这也是为什么后文验证技能时,要区分「被发现」和「正文被加载」两件事。
技能发现位置与优先级
当前本地提供方第一优先扫描 <projectRoot>/.dsh/skills。例如:
my-project/
├── .git/
├── .dsh/
│ └── skills/
│ └── seo-audit/
│ └── SKILL.md
└── src/
这种技能很适合只服务当前项目,例如:
- 当前仓库发布流程
- 当前项目代码规范
- 当前站点 SEO 审计规则
- 当前项目测试要求
.agents/skills 也支持吗?
支持。当前项目级第二个默认根是 <projectRoot>/.agents/skills,所以项目技能常见两个位置:
.dsh/skills
.agents/skills
如果同名 skill 同时存在,当前本地 rank(排序权重,数值越小越优先)中 .dsh/skills 的优先级高于 .agents/skills。
用户级技能放在哪里?
当前默认用户级 DSH skill 根是 $DSH_HOME/skills。默认 Harness home 通常是 ~/.dsh,因此常见路径是:
~/.dsh/skills
这种技能适合你希望多个项目都能使用的个人方法,例如通用内容研究、通用代码审查、通用写作规则和个人 GitHub 工作流。
当前技能发现优先级
当前本地提供方的 rank 如下:
| Rank | 来源 | 路径 |
|---|---|---|
| 100 | project-dsh | <projectRoot>/.dsh/skills |
| 200 | project-agents | <projectRoot>/.agents/skills |
| 300 | custom | 自定义 skill 目录 |
| 400 | user-dsh | $DSH_HOME/skills |
| 500 | user-agents | $DSH_AGENTS_HOME/skills |
| 600 | bundled | 配置的 bundled skill 目录 |
在同一层发生同名冲突时,更低的 rank 优先。所以项目自己的 .dsh/skills 通常可以覆盖用户级同名技能。
$DSH_AGENTS_HOME 是用户级 agents 技能目录;bundled 指随配置打包的技能目录。新手阶段只需要记住前两行。
项目根是怎么判断的?
当前本地 skill 提供方会向上寻找最近的 .git 目录,并把这个位置作为项目根;如果找不到 .git,则使用当前工作目录。
支持哪些文件形式?
当前本地 skill 支持两种文件形式。目录形式是 <name>/SKILL.md,例如:
seo-audit/
└── SKILL.md
平铺 Markdown 形式是单个 <name>.md 文件,例如 seo-audit.md。
会递归搜索所有 SKILL.md 吗?
不会。当前实现明确不支持任意嵌套的 **/SKILL.md 递归发现。所以下面这种结构不要假设一定能被发现:
.dsh/skills/
└── category/
└── subcategory/
└── seo-audit/
└── SKILL.md
更稳妥的做法是让 skill 直接位于 skill 根目录的第一层。
创建一个最小测试技能
为了验证 skill 机制,可以在项目中创建 .dsh/skills/dsh-skill-test/SKILL.md,写入:
---
name: dsh-skill-test
description: 用于验证 DeepSeek Harness skill 是否被正确发现和加载。
---
# DSH Skill Test
如果你正在执行这个技能:
只返回下面这一行,不要增加其他内容:
DSH-SKILL-VERIFY-8f2a71
这里故意放了一个独特、不可自然猜中的验证字符串。
为什么要使用独特验证字符串?
如果技能正文里只写「请回答你好」,模型回答「你好」,你无法判断它是不是实际加载了 skill。
但如果正文中存在 DSH-SKILL-VERIFY-8f2a71 这样的字符串,而提示词里不告诉模型这个值,最终正确返回这个值,就能更有力地证明正文已经被加载。
目录与正文生命周期
当前本地 skill 提供方内置 watcher(文件监视器),会监视 skill 目录的添加、删除、SKILL.md 的变化以及 frontmatter(文件顶部的元数据头)的变化,因此本地 skill 目录当前支持动态发现变化。
修改正文和修改 description 有什么区别?
当前 skill 系统把目录摘要和完整正文分成了两个生命周期。
修改 name 或 description 会影响模型看到的 skill 目录,当前 watcher 会让目录重新发现。
只修改正文不会改变目录 digest(内容指纹),但下一次真正执行 skill(name="...") 时,会重新读取当前正文。
显式调用与自动路由
这是最推荐的新手验证方式。如果 skill 允许用户调用,可以在用户消息中使用:
/dsh-skill-test
当前 DSH 会识别用户输入里的 /name 手势。如果对应 skill 可以由用户调用,会把完整 skill 内容直接注入当前步骤。这意味着不需要依赖模型自己判断「要不要调用」。
/name 和模型调用 skill 工具有什么区别?
/name 是用户显式调用:你明确告诉 DSH,这次就使用这个技能。
skill(name="...") 是模型调用技能 loader(加载器):模型先从目录发现 skill,再决定加载正文。
所以验证建议分两步:
显式 /name
↓
确认 skill 本身可用
自然语言任务
↓
观察模型是否会自动路由
为什么「自动没触发」不等于技能无效?
这是一个非常重要的判断。假设 /dsh-skill-test 显式调用成功,说明至少:skill 被发现、用户可调用、正文能加载、指令能进入模型上下文。
但如果你用自然语言说「帮我测试一下技能」,模型没有主动调用它,这更可能属于路由、description 或模型判断问题,不能直接得出「这个 skill 不能用」的结论。
如何让模型更容易判断应该使用?
优先改两处。一是名称要具体、可识别:seo-audit 比 helper 更清楚。
二是 description 要写清什么时候用、做什么:
审核网页或网站项目的 SEO 基础问题,包括 Title、Description、H1、canonical 和内链,并按优先级输出整改建议。
它比 SEO skill 这样的泛泛描述更有路由价值。
whenToUse 会直接给模型看吗?
当前本地 skill 可以解析 frontmatter 中的 whenToUse 字段,但面向模型的 skill 目录不会把 whenToUse 渲染进去,模型看到的目录主要是 name 和 description。
调用控制与资源
当前本地 skill 支持 disable-model-invocation: true 字段:
---
name: destructive-release
description: 执行内部正式发布流程。
disable-model-invocation: true
---这样这个 skill 不会出现在模型可调用的目录和 skill 工具接口中。它可以用于你不希望模型自己选择、只允许用户明确触发的流程。
怎么禁止用户用 /name 调用?
可以设置 user-invocable: false,这样它就不会通过用户显式 /name 入口调用。两个控制是相互独立的。
四种调用策略怎么理解?
| 配置 | 模型可调用 | 用户 /name |
|---|---|---|
| 默认 | 是 | 是 |
| disable-model-invocation: true | 否 | 是 |
| user-invocable: false | 是 | 否 |
| 两者同时限制 | 否 | 否 |
如果两个都关闭,普通模型和用户界面都不会直接使用它。
技能里的 scripts / references / assets 会自动全部加载吗?
不会。当前 skill 工具加载正文后,会提供资源基底指引,但资源是按需引用,不是自动把整个目录全部塞进上下文。例如:
seo-audit/
├── SKILL.md
├── references/
│ └── checklist.md
└── scripts/
└── audit.js
如果 SKILL.md 明确要求需要时读取 references/checklist.md,智能体可以按资源基底解析路径。
安全与工具边界
skill 通常是一份 Markdown 指令,但不要因此认为「只是文字,没有风险」。因为 skill 可以指示智能体:
- 执行 Shell 命令
- 修改文件
- 调用 MCP
- 使用高权限工具
- 请求外部系统操作
真正的风险取决于:技能指令加上当前智能体拥有的工具和权限。
技能会凭空获得它没有的工具吗?
不会。如果 skill 里写「查询 CRM」,但当前智能体没有 CRM MCP、CRM 插件,也没有 HTTP、Shell 等可用执行能力,仅仅写进 skill 并不会创造出一个 CRM 工具。
一个更真实的技能组合
以一个 DSHOPC 式的内容研究技能为例:
技能
→ 规定研究顺序、证据层级和输出格式
网页检索
→ 获取公开资料
GitHub 工具 / MCP
→ 查源码和 Issue
文件工具
→ 写入研究结果
skill 是方法层,其他工具是执行能力层。成熟智能体经常会把它们组合起来。
技能为什么会影响 token?
当前模型目录会把可调用 skill 的名称和 description 放进会话上下文,所以技能越多,目录本身就越长(token 是模型上下文长度和费用的计量单位)。而真正加载某个 skill 之后,完整正文也会进入后续模型上下文。
因此不是技能越多越好。如果几十上百个技能都名称模糊、description 很长、范围重叠,反而会:
- 增加目录 token
- 增加路由歧义
- 增加模型判断成本
项目级和用户级怎么选?
项目级放在 .dsh/skills,适合当前项目规则、当前仓库流程、当前产品领域知识和项目专属验证。
用户级放在 ~/.dsh/skills,适合跨项目通用方法、个人研究流程、通用写作规范和通用代码审查。
怎样验证一个技能真正成功?
建议做四层验证。
第一层:发现
确认技能已经进入当前可用目录,例如 /name 能被识别,或者相关工具目录能够看到它。
第二层:显式加载
使用 /dsh-skill-test 显式调用,确认正文真正进入上下文。
第三层:唯一值
确认模型返回 DSH-SKILL-VERIFY-8f2a71 这种只有 skill 正文中才有的值。
第四层:自然任务路由
去掉显式 /name,给一个明显符合 description 的任务,观察模型是否主动使用 skill 工具加载它。
排错
/name 完全识别不到
先依次检查:
- 路径是否正确
name是否合法- frontmatter 格式是否有效
- 是否设置了
user-invocable: false - 当前工作区和项目根是否符合预期
模型目录里没有
先检查:
- 是否设置了
disable-model-invocation: true - description 和 name 是否有效
- 当前 Agent 预设是否包含
skill工具
例如极简模式并没有标准模式中的完整 skill 工具组合,所以不要在没有 skill 工具的预设里误判 skill 本身坏了。
显式调用成功,但自动不触发
优先检查 name 是否模糊、description 是否清楚、当前任务是否真的明显匹配。
怎样算你学会技能了?
至少应该清楚下面这些判断:
- skill 是任务方法和指令,不是自动新增外部 API
- 项目级可以放
.dsh/skills - 用户级可以放
$DSH_HOME/skills - 支持
<name>/SKILL.md和<name>.md - skill 名称使用 kebab-case
- 模型目录主要看到 name + description
- description 影响路由,但不能保证自动调用
/name可以用于显式验证- 自动不触发不等于 skill 本身无效
disable-model-invocation和user-invocable是两种不同控制- 第三方技能仍需审查正文
- 技能不会凭空创造不存在的工具
如果这些都清楚,你已经具备 DeepSeek Harness 技能的基础创建和验证能力。
下一步
- 如果你现在缺外部工具,继续阅读《DeepSeek Harness MCP 教程》。
- 如果你需要更深的 DSH 原生能力,回到《DeepSeek Harness 插件教程》。
- 如果技能不被发现或无法调用,进入《DeepSeek Harness 常见问题与报错排查》。
以后如果 DSHOPC 对具体第三方技能项目做实际放置、版本兼容、自动路由成功率、token 影响和真实任务效果的实测,这些结论应该进入 Lab 板块,而不是在通用 Learn 教程里提前宣称「更好用」。