首页 › Skills专栏 › 吴恩达 Skills 教程 › 第六章:创建自定义技能(Create | Skills)

第六章:创建自定义技能(Create | Skills)

​

飞书文档 - 图片

​

这一节的核心叙事是:我手里有一个“技能模板”,但不知道怎么填才能做得好​

•

然后我学会了命名的规矩、发现description才是触发的命门、理解了正文该怎么组织​

•

接着我亲手做了两个技能,拿出去跑了一圈,看它哪里好、哪里还能改​

•

最后我收获了一份“审查清单”,下次再做不会再踩坑。​

1、有一个模板,但不知道怎么命名Skills​

我们知道每个Skill需要一个SKILL.md文件,文件开头得放YAML前置元数据:​

​

代码块​

YAML

---​

name: analyzing-marketing-campaigndescription: Use when analyzing marketing campaign data, performing funnel analysis, and generating campaign performance reports.​

---​

​

只有两个字段是必填的:name和description。而且——强调一下——只有这两个字段在Agent启动时就加载进上下文,其余正文内容都是在技能触发后才加载的。​

所以description写得对不对,直接决定了Agent在茫茫多的技能中,会不会点开你这个技能来看。​

1.1、Skills的name“铁律”​

name不只是标识符,它还是触发机制的一部分。一个好的技能名应该清晰、准确地传达核心功能。图片里给出了analyzing-marketing-campaign/SKILL.md的例子,这正是name和description的标准写法。​

命名硬性规则(记不住没关系,每次对着清单查即可):​

​

#iLwcEUfgRtWs text { white-space: pre; }#iLwcEUfgRtWs .fb0 { stroke: var(--N900-FG, 0.15); }#iLwcEUfgRtWs .fb0 {stroke: rgba(31,35,41, 0.15)}#iLwcEUfgRtWs .fx0 { stroke-miterlimit: 10; }#iLwcEUfgRtWs .fx0 {stroke-miterlimit: 10}#iLwcEUfgRtWs .fa1 { fill: rgb(187, 191, 196); }#iLwcEUfgRtWs .fa1 {fill: rgb(187, 191, 196)}#iLwcEUfgRtWs .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#iLwcEUfgRtWs .fx1 {font-style: normal}#iLwcEUfgRtWs .fx2 { text-anchor: middle; }#iLwcEUfgRtWs .fx2 {text-anchor: middle}#iLwcEUfgRtWs .fx3 { dominant-baseline: central; }#iLwcEUfgRtWs .fx3 {dominant-baseline: central}#iLwcEUfgRtWs .fx4 { stroke: none; }#iLwcEUfgRtWs .fx4 {stroke: none}#iLwcEUfgRtWs .fc0 { fill: var(--text-caption); }#iLwcEUfgRtWs .fc0 {fill: #646a73}#iLwcEUfgRtWs .fa2 { fill: var(--text-link-disabled); }#iLwcEUfgRtWs .fa2 {fill: rgb(187, 191, 196)}#iLwcEUfgRtWs .fa3 { fill: rgb(143, 149, 158); }#iLwcEUfgRtWs .fa3 {fill: rgb(143, 149, 158)}#iLwcEUfgRtWs .fa4 { fill: rgb(217, 245, 214); }#iLwcEUfgRtWs .fa4 {fill: rgb(217, 245, 214)}#iLwcEUfgRtWs .fa5 { fill: rgb(250, 241, 209); }#iLwcEUfgRtWs .fa5 {fill: rgb(250, 241, 209)}#iLwcEUfgRtWs .fx5 { font: 700 16px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#iLwcEUfgRtWs .fx5 {font-style: normal}#iLwcEUfgRtWs .fx6 { text-anchor: start; }#iLwcEUfgRtWs .fx6 {text-anchor: start}#iLwcEUfgRtWs .fx7 { dominant-baseline: alphabetic; }#iLwcEUfgRtWs .fx7 {dominant-baseline: alphabetic}#iLwcEUfgRtWs .fc1 { fill: rgb(0, 0, 0); }#iLwcEUfgRtWs .fc1 {fill: rgb(0, 0, 0)}#iLwcEUfgRtWs .fx8 { font: 400 16px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#iLwcEUfgRtWs .fx8 {font-style: normal}#iLwcEUfgRtWs .fx9 { font: 400 13px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#iLwcEUfgRtWs .fx9 {font-style: normal}#iLwcEUfgRtWs .fb1 { fill: var(--N900-FG, 0.15); }#iLwcEUfgRtWs .fb1 {fill: rgba(31,35,41, 0.15)}#iLwcEUfgRtWs .fb2 { fill: rgba(255, 255, 255, 0.16); }#iLwcEUfgRtWs .fb2 {fill: rgba(255, 255, 255, 0.16)}#iLwcEUfgRtWs .fb3 { fill: rgba(255, 255, 255, 0.12); }#iLwcEUfgRtWs .fb3 {fill: rgba(255, 255, 255, 0.12)}#iLwcEUfgRtWs .fa6 { fill: var(--bg-body); }#iLwcEUfgRtWs .fa6 {fill: #fff}AB12345678约束示例1-64个字符仅小写字母+数字+连字符不以连字符开头或结尾父目录名与name一致不包含保留词推荐使用动词-ing形式连字符不连续(15个)✅;太长❌ ✅; ❌ ✅; ❌目录内,name必须完全匹配不能包含或 ✅; ❌ ❌processing-pdfsmy-skill-2My_Skillskill-name-skillanalyzing-marketing-campaign/claudeanthropicprocessing-pdfshelpermy--skill

​

​

🔥 为什么推荐动词-ing形式?因为Agent在扫描技能列表时,processing-pdfs比pdf-helper更能直观传达“这个技能是用来做什么的”。图片里举的反面例子helper、utils、tools,就是太模糊、Agent不知道该不该用的典型。​

​

2、description的“命门”​

description的写法决定了技能会不会被触发。如果写得太笼统,Agent永远猜不到什么时候该用它;写得太具体但漏了关键词,同样会被跳过。​

从课程和官方规范中可以提炼出这样一个原则:​

•

不要写:Helper for data processing(太模糊)​

•

要写:Use when analyzing time series data, identifying trends and seasonality, or forecasting future values based on historical patterns(清晰写出触发场景和关键词)​

这里的关键是:把触发条件写得具体,让Agent在看到相关任务描述时能想起“这个技能能用上”。​

3、正文怎么写——让事情“说得清楚也做得出来”​

SKILL.md的正文是技能触发后加载的内容,这里才写具体怎么干活。​

两条核心原则:​

•

“生成优先,澄清在后”:先让模型产出初稿,再根据反馈迭代修正,而不是在写指令时就把所有分支情况穷举完。​

•

500行红线:正文控制在500行以内,超长内容拆入references/文件夹,并在正文中告诉Agent“如果需要具体信息,去读取references/中的文件”。​

正文的组织建议:​

​

#PNJhklTLdeiB text { white-space: pre; }#PNJhklTLdeiB .fb0 { stroke: var(--N900-FG, 0.15); }#PNJhklTLdeiB .fb0 {stroke: rgba(31,35,41, 0.15)}#PNJhklTLdeiB .fx0 { stroke-miterlimit: 10; }#PNJhklTLdeiB .fx0 {stroke-miterlimit: 10}#PNJhklTLdeiB .fa1 { fill: rgb(187, 191, 196); }#PNJhklTLdeiB .fa1 {fill: rgb(187, 191, 196)}#PNJhklTLdeiB .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#PNJhklTLdeiB .fx1 {font-style: normal}#PNJhklTLdeiB .fx2 { text-anchor: middle; }#PNJhklTLdeiB .fx2 {text-anchor: middle}#PNJhklTLdeiB .fx3 { dominant-baseline: central; }#PNJhklTLdeiB .fx3 {dominant-baseline: central}#PNJhklTLdeiB .fx4 { stroke: none; }#PNJhklTLdeiB .fx4 {stroke: none}#PNJhklTLdeiB .fc0 { fill: var(--text-caption); }#PNJhklTLdeiB .fc0 {fill: #646a73}#PNJhklTLdeiB .fa2 { fill: var(--text-link-disabled); }#PNJhklTLdeiB .fa2 {fill: rgb(187, 191, 196)}#PNJhklTLdeiB .fa3 { fill: rgb(225, 234, 255); }#PNJhklTLdeiB .fa3 {fill: rgb(225, 234, 255)}#PNJhklTLdeiB .fa4 { fill: rgb(222, 224, 227); }#PNJhklTLdeiB .fa4 {fill: rgb(222, 224, 227)}#PNJhklTLdeiB .fx5 { font: 400 16px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#PNJhklTLdeiB .fx5 {font-style: normal}#PNJhklTLdeiB .fx6 { text-anchor: start; }#PNJhklTLdeiB .fx6 {text-anchor: start}#PNJhklTLdeiB .fx7 { dominant-baseline: alphabetic; }#PNJhklTLdeiB .fx7 {dominant-baseline: alphabetic}#PNJhklTLdeiB .fc1 { fill: rgb(0, 0, 0); }#PNJhklTLdeiB .fc1 {fill: rgb(0, 0, 0)}#PNJhklTLdeiB .fb1 { fill: var(--N900-FG, 0.15); }#PNJhklTLdeiB .fb1 {fill: rgba(31,35,41, 0.15)}#PNJhklTLdeiB .fb2 { fill: rgba(255, 255, 255, 0.16); }#PNJhklTLdeiB .fb2 {fill: rgba(255, 255, 255, 0.16)}#PNJhklTLdeiB .fb3 { fill: rgba(255, 255, 255, 0.12); }#PNJhklTLdeiB .fb3 {fill: rgba(255, 255, 255, 0.12)}#PNJhklTLdeiB .fa5 { fill: var(--bg-body); }#PNJhklTLdeiB .fa5 {fill: #fff}AB12345建议包含的内容工作流程说明约束条件和边界使用示例最佳实践示例“Step 1: 加载数据 → Step 2: 质量检查 → Step 3: 生成报告”“仅处理时间序列数据,缺失值填充采用线性插值”输入样例、输出样例“分类变量应进行独热编码”

​

自由度匹配原则:​

​

#peuLKZiMAzcu text { white-space: pre; }#peuLKZiMAzcu .fb0 { stroke: var(--N900-FG, 0.15); }#peuLKZiMAzcu .fb0 {stroke: rgba(31,35,41, 0.15)}#peuLKZiMAzcu .fx0 { stroke-miterlimit: 10; }#peuLKZiMAzcu .fx0 {stroke-miterlimit: 10}#peuLKZiMAzcu .fa1 { fill: rgb(187, 191, 196); }#peuLKZiMAzcu .fa1 {fill: rgb(187, 191, 196)}#peuLKZiMAzcu .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#peuLKZiMAzcu .fx1 {font-style: normal}#peuLKZiMAzcu .fx2 { text-anchor: middle; }#peuLKZiMAzcu .fx2 {text-anchor: middle}#peuLKZiMAzcu .fx3 { dominant-baseline: central; }#peuLKZiMAzcu .fx3 {dominant-baseline: central}#peuLKZiMAzcu .fx4 { stroke: none; }#peuLKZiMAzcu .fx4 {stroke: none}#peuLKZiMAzcu .fc0 { fill: var(--text-caption); }#peuLKZiMAzcu .fc0 {fill: #646a73}#peuLKZiMAzcu .fa2 { fill: var(--text-link-disabled); }#peuLKZiMAzcu .fa2 {fill: rgb(187, 191, 196)}#peuLKZiMAzcu .fa3 { fill: rgb(225, 234, 255); }#peuLKZiMAzcu .fa3 {fill: rgb(225, 234, 255)}#peuLKZiMAzcu .fa4 { fill: rgb(46, 161, 33); }#peuLKZiMAzcu .fa4 {fill: rgb(46, 161, 33)}#peuLKZiMAzcu .fa5 { fill: rgb(142, 224, 133); }#peuLKZiMAzcu .fa5 {fill: rgb(142, 224, 133)}#peuLKZiMAzcu .fa6 { fill: rgb(217, 245, 214); }#peuLKZiMAzcu .fa6 {fill: rgb(217, 245, 214)}#peuLKZiMAzcu .fx5 { font: 400 16px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#peuLKZiMAzcu .fx5 {font-style: normal}#peuLKZiMAzcu .fx6 { text-anchor: start; }#peuLKZiMAzcu .fx6 {text-anchor: start}#peuLKZiMAzcu .fx7 { dominant-baseline: alphabetic; }#peuLKZiMAzcu .fx7 {dominant-baseline: alphabetic}#peuLKZiMAzcu .fc1 { fill: rgb(0, 0, 0); }#peuLKZiMAzcu .fc1 {fill: rgb(0, 0, 0)}#peuLKZiMAzcu .fx8 { font: 400 13px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#peuLKZiMAzcu .fx8 {font-style: normal}#peuLKZiMAzcu .fb1 { fill: var(--N900-FG, 0.15); }#peuLKZiMAzcu .fb1 {fill: rgba(31,35,41, 0.15)}#peuLKZiMAzcu .fb2 { fill: rgba(255, 255, 255, 0.16); }#peuLKZiMAzcu .fb2 {fill: rgba(255, 255, 255, 0.16)}#peuLKZiMAzcu .fb3 { fill: rgba(255, 255, 255, 0.12); }#peuLKZiMAzcu .fb3 {fill: rgba(255, 255, 255, 0.12)}#peuLKZiMAzcu .fa7 { fill: var(--bg-body); }#peuLKZiMAzcu .fa7 {fill: #fff}ABC1234自由度高中低适用场景多种方案均可有偏好模式必须精确执行怎么写文字指引、原则性描述伪代码、带参数的模板确定性脚本放里scripts/

​

​

这一点特别重要:低自由度的任务(比如“旋转PDF”这种结果必须唯一确定)如果只写文字指引,每次执行时AI都会重新“思考”怎么做,既慢又不稳定。写成确定性脚本,效率剧增。​

​

4、实战·技能一——基于讲义生成练习题​

回顾一下流程:拿到Lecture Notes,自动生成练习题和答案解析。​

技能的业务逻辑:​

text​

用户上传讲义PDF/Markdown ↓步骤1:抽取关键知识点(重点章节、定义、公式) ↓步骤2:设计题目类型(选择题、填空题、简答题) ↓步骤3:生成题目正文 ↓步骤4:生成答案和解析 ↓步骤5:提供难度分级(简单/中等/困难)​

这个Skill的文件夹结构(根据课程的设计思路推测):​

text​

quiz-generator/├── SKILL.md # 定义题型规则、输出格式、难度分级逻辑├── references/ # 存放题目类型模板库、知识点抽取指南└── ../assets/ # 输出报告模板​

这个技能教会了我们什么?​

•

如何让AI从非结构化文本(讲义)中提取结构化知识点​

•

如何设计明确的输出格式(为什么要有标准格式?因为后续可能要加载到习题系统)​

•

如何将“难度分级”这种主观判断用文字指引转化为可执行的规则​

5、实战·技能二——时间序列数据特征分析​

这是一个典型的数据分析类技能。用户丢进来一个时间序列数据文件,让AI自动完成数据质量检查和特征分析。​

技能的业务逻辑(这也是课程里实际演示的流程):​

text​

用户上传CSV文件(带时间戳和数值列) ↓步骤1:载入时间戳列和数值列 ↓步骤2:数据质量检查 ├── 总记录数 ├── 缺失值统计 └── 异常跳变检测 ↓步骤3:数据特征分析 ├── 趋势识别(长期上升/下降/平稳) ├── 季节性识别(年度/季度/月度周期) └── 周期性模式 ↓步骤4:输出数据质量报告 + 特征分析报告​

Skill结构要点(根据课程设计逻辑推测):​

text​

time-series-analyzer/├── SKILL.md # 定义分析流程:质量检查→异常检测→趋势识别→季节分析├── scripts/ # Python脚本:数据质量检查、异常检测、特征提取└── references/ # 参数调优指南(不同季节周期长度、异常阈值说明)​

关键观察:这个技能在scripts/里放置确定性脚本(数据质量检查等步骤),既提升了执行效率,又确保了结果的一致性。这正是“低自由度任务下沉到脚本”原则的典型实践。​

6、把两个技能拿去“考试”​

课程设计了一个关键的反馈闭环:创建完两个技能后,用Claude API实际运行它们,同时借助skill-creator生成技能质量反馈。​

这个过程揭示了一个重要逻辑:SKILL.md的正文写得再漂亮,真正的检验标准是——Agent能不能稳定地按预期工作。​

7、审查清单——下次再做,不会踩坑​

做完两个技能并跑通后,你应该能回答这些问题。把它们变成下次开发前的“手写检查卡”:​

•

name格式正确吗? 64字符以内?全小写+连字符?不以连字符开头或结尾?不包含claude/anthropic?​

•

name推荐动词-ing形式了吗? 能让Agent一眼看懂这是“做什么的”吗?​

•

description能驱动触发吗? 是否包含足够的关键触发词?Agent看到什么任务会“想起”这个技能?​

•

正文保持在500行以内了吗? 超长的拆进references/了吗?​

•

自由度是否与场景匹配? 低自由度任务是不是应该写成确定性脚本放scripts/里?​

•

是否配置了测试用例? 让Claude在真实场景中验证技能效果了吗?​

8、一句话收尾​

​

“模板人人有,但把技能做得'稳定可靠、触发精准',才是分水岭。”​

​

​