
先说结论Anthropic 官方在 2025 年正式把“Agent Skills”这个概念放到台前之后整个 Claude 生态里关于 skill 的讨论一下子多了起来。它解决的问题很朴素但也很硬核——大模型本身并不知道你团队内部的做事方法而你想把“一个熟练员工怎么处理某类任务”沉淀成一份可复用、可加载的能力包。Skill 就是干这个的。这篇文章我会从什么是 SKILL 讲起结合官方给出的最佳实践原则拆解一个优秀 SKILL 的目录结构、元数据写作要点和执行流程设计最后聊几个我自己实测踩过的坑。适合两类人看一类是正在用 Claude Agent SDK 或 Claude Code 搭自动化流程的开发者另一类是希望把团队经验转成标准化资产的产品和运营同学——只要你愿意写 Markdown 和简单脚本都能上手。1. SKILL 到底是什么定位、结构与分类1.1 按需加载的“技能包”到底长什么样最朴素的定义是SKILL 是 Claude 的一种可复用能力封装形式上就是一个目录目录里至少有一个SKILL.md作为入口文件其余空间放辅助资产——可以是 Markdown 文档、Python 脚本、模板文件、配置文件甚至可以是一整个命令行工具。当用户的请求与某个 skill 的 description 相匹配时Claude 会把该 skill 的内容注入到当前任务的上下文里然后按里面的步骤和方法完成任务。这里最关键的一个设计是“按需加载”。并不是说本地装了多少个技能、上下文里就会全部塞满多少技能而是模型在收到任务后先扫描技能目录中各个SKILL.md的元数据判断“这个任务需不需要这门技能”再决定是否把对应的文件加载进来。这个机制和人脑的运作方式非常像你是 Python 开发但你在写周报的时候并不会自动调用所有算法细节只有当任务变成“优化这段递归函数”时相应的知识才会被唤醒。模型在运行时先读技能说明、确认适用性然后才加载具体资源这样上下文窗口就不会被一堆无关内容白白占掉。为什么官方把这件事叫作“技能”而不是“插件”我倾向于这样理解插件隐含“连接到某个外部系统”的意思而技能更像“操作手册 工具箱”的组合它既包含做事的知识know-how也包含做事的工具script。官方对技能的划分也印证了这一点知识型技能主要提供 Prompt、规范、方法论代码型技能提供可执行的脚本或工具复合型技能两者兼有。比如说“生成符合公司格式的周报”是知识型“清洗 CSV 为统一格式”是代码型“先分析日志再输出诊断报告”就是复合型。1.2 SKILL 与 MCP 的分工两张截然不同的“能力图”很多人第一次听到 skill第一反应是“这不就是 MCP 吗”。两者确实都算是模型能力的扩展机制但底层逻辑完全不同。MCP 是一个连接协议解决的是“Claude 如何访问外部实时数据与业务系统”——查数据库、调 CRM 接口、读私有知识库本质上是给模型开一扇通往外部世界的窗户。SKILL 解决的是“Claude 如何按照特定方法论完成一类任务”它的知识是内置在技能包里的不依赖网络也不需要外部服务实时响应。我用一个类比来解释MCP 像是给员工开通了外部系统的登录权限SKILL 像是给员工发了一本内部 SOP 手册外加一套定制好的 Excel 宏。前者强调连接后者强调方法论。实际项目里两者常常配合使用——skill 文档里完全可以写明“这个任务需要先通过 MCP 拉取某个 API 的数据再按下面的规则做处理”同时allowed-tools字段也可以把相关的 MCP 工具放开给这个技能使用。这个区分对实践非常重要。你写 skill 之前先问自己一句“我要沉淀的是知识、连接还是混合体”如果团队里有一批需要实时查询的内部数据那是 MCP 的活如果团队里有一套“从原始数据到最终报告”的固定流程那是 skill 的活。角色搞反了要么把 skill 写成了一个没有生命力的 API 封装要么把 MCP 当成了文档仓库最后两头都不讨好。对比维度SKILLMCP核心定位内置知识与执行方法论外部系统连接协议数据来源技能包内的静态文档/脚本实时 API、数据库、业务系统是否需要网络不需要通常需要适用场景固定流程、专业规范、专属工具链实时查询、第三方服务、系统集成上下文消耗按需加载后注入通过工具调用按需获取2. 官方最佳实践中最核心的三条原则2.1 “一次看完”原则技能文档不要写成大部头官方给出的第一条建议概括起来就是一个 skill 的全部核心内容应该能够在模型的“一次上下文读取”中被理解不要搞成几十页的大部头。你可以把它理解成电梯演讲——如果模型需要翻很多次才能找到关键步骤中间丢失信息、产生无效推理的概率会大幅上升。我自己实际操作时会把SKILL.md控制在 200 到 500 行之间正文里只写主流程和判断标准细节内容拆到子文件里。比如一个“数据清洗”技能SKILL.md 里只写清洗规则的总纲、三个阶段之间的交接物具体的字段标准放reference/field_standards.md执行脚本放scripts/下。这样模型在“决定是否使用该技能”和“执行主流程”两个阶段读到的都是紧凑而可用的信息只有真正需要时才去翻细节。还有一个容易被忽略的细节目录结构本身就是一种知识表达。模型通过文件名和路径能快速理解“这个技能包里有哪些资产”所以文件名要写清楚用途别用data1.py、utils2.py这种模糊命名。官方示例里你常常能看到像pdf_inpaint、typography这样一眼能看出语义的目录名这其实就是给目录做了一次隐式说明。2.2 “单一职责”原则窄而明确的技能才有高命中率官方在多个场合都强调好的技能应该聚焦一个明确的任务域。不要试图写一个“万能办公助理”技能它听起来强大实际执行时反而会让模型陷入两难既不好判断“现在到底该不该加载它”加载之后也不清楚该先做哪件事。单一职责的技能更符合模型的匹配逻辑也更容易写出高质量的 description。我自己有个判断标准如果某个技能的主流程里出现了大量“如果任务是 A 就走 XX 步骤如果任务是 B 就走 YY 步骤”这类强分支那大概率是把两个技能揉在了一起。不是说技能内部完全不能有条件判断而是这种强分支本身就说明“适用场景”并不一致。拆成两个独立技能之后各自的 description 更清晰模型的调用准确率也会明显提高。但话说回来技能也不是拆得越细越好。太碎了会带来两个问题一是技能数量爆炸模型在匹配时反而容易混淆二是每个技能都太薄没什么可沉淀的知识。比较合适的粒度是“重复发生、需要固定处理的完整任务”。举个例子现有的“把 Markdown 文章转换成符合公众号发布规范的排版”就是一个好粒度它既不是“加粗所有标题”这种细碎动作也不是“处理所有内容运营任务”这种无边界的宽泛定义。2.3 description 决定一切写触发条件的提效技巧如果要在全文划一个最重要的知识点我一定选这一条SKILL 的 description 决定了模型“什么时候调用这个技能”它就是技能的招聘标题。模型在处理用户请求时会扫描可用技能的描述来匹配当前任务描述写得含糊技能内容写得再好也等于不存在。最常见的毛病是空泛比如“用于处理数据”——它没讲清楚处理什么数据、什么场景下用、产出是什么模型根本没法把这个技能和具体任务对应起来。一个更可用的写法应该包含输入物、应用场景、执行方式和产出物必要的时候还要写“什么情况下不该调用”。比如我写一个简历解析技能description 大致是这样的解析 PDF 或 DOCX 格式的简历文件提取候选人姓名、联系方式、工作经历、教育背景输出结构化 JSON。适用于招聘流程中的简历初筛。如果输入内容不是简历不要调用本技能。最后那句“如果输入内容不是简历不要调用本技能”就是典型的反向条件。它的作用在于模型在判定任务时不但会因为正向条件命中而决定调用也会因为反向条件命中而明确拒绝调用误用率会明显下降。这个细节我实测下来是提升技能命中率“性价比”最高的一招强烈建议每个人都在自己的技能描述里用上。3. 手把手写一个优秀 SKILL从目录规划到可运行3.1 目录规划与 metadata 设置理论讲完了接下来我们走一遍完整流程。用我最常用的示例来说明——做一个“CSV 数据清洗”技能目标是把各种来源、各种脏格式的表格文件清洗成统一结构并输出一份质量报告。第一步规划目录结构。一个清晰的技能包大概长这样clean-csv/ ├── SKILL.md ├── scripts/ │ ├── clean_csv.py │ └── validate.py └── reference/ └── field_standards.mdSKILL.md是整个技能的入口开头的 YAML frontmatter 承载元数据里面最关键的是name、description和可选的allowed-tools。官方要求name必须是 ASCII 小写字母加连字符不允许出现中文、空格和特殊字符description里的引号必须是直引号不能用弯引号否则解析阶段就会报错这个坑后面单独说。allowed-tools是用来限制该技能可以用哪些工具进行操作的。它的实际价值在于防止模型执行某个技能时顺手调用了一堆无关工具造成不可控的副作用。比如我这个清洗技能原则上只需要读文件、写文件、跑脚本那我就会在元数据里限定工具集合让模型不要想去调浏览器或者发 HTTP 请求。不同宿主环境下工具名会有差异但思路是一致的——给技能划定一个明确的“活动范围”。3.2 SKILL.md 正文把执行流程写成“人话指令”元数据写完之后正文部分是给模型看的执行指令。官方建议用第二人称、现在时态、直陈命令来写。因为你是在给一个“随时可能接手任务的执行代理”写操作手册而不是在给人类同事写百科词条。一个常见的思维转换误区是写技能时还在按文档思维写“本功能用于……”真正有效的写法是“你需要先读取输入文件然后……”。我一般会把正文组织成几个固定的模块适用场景、执行步骤、输出要求、注意事项。下面是一个简化版的例子--- name: clean-csv description: 读取 CSV 文件并识别常见数据质量问题缺失值、重复行、类型不一致、异常值生成清洗报告并输出清洗后的 CSV 文件。适用于用户需要对表格数据做预处理和标准化时。如果输入不是表格数据不要调用本技能。 allowed-tools: Read, Write, Edit, Bash --- # CSV 数据清洗 ## 适用场景 该技能用于处理 CSV 表格的清洗和标准化包括 - 缺失值处理 - 去重 - 字段类型校正 - 异常值标记 ## 执行步骤 1. 使用 Read 工具读取目标 CSV 文件确认编码和分隔符必要时查看前 20 行结构。 2. 加载 reference/field_standards.md根据字段标准逐列检查类型和取值范围。 3. 运行 scripts/clean_csv.py传入输入路径和输出路径参数。 4. 运行 scripts/validate.py生成清洗后的质量报告。 5. 用 Write 工具输出清洗后的 CSV 和质量报告报告需包含每一类问题的数量和处理方式。 ## 输出要求 - 清洗后的 CSV 文件编码统一为 UTF-8。 - 质量报告使用 Markdown 格式第一行为文件总行数、清洗前后行数变化。 - 如果输入文件不存在或无法读取直接向用户说明不执行后续步骤。这段内容其实就是把“一个熟练的数据工程师接到清洗任务后会做的判断和操作”写成了可执行的指令序列。它不玄乎但恰恰是这种平实的、带判断标准的写法模型执行起来最稳定。我在正文里还专门写了“如果输入文件不存在或无法读取”的处理方式这相当于给代理加了一道异常保护避免它在文件缺失时自己瞎猜。3.3 辅助脚本该承担什么角色辅助脚本在技能里的角色是“把需要精确计算或大量重复的工作从模型手中接走”。模型擅长的是理解和规划遇到像“逐行判断 10 万行 CSV 里的日期格式是否合法”这种活儿它做起来又慢又容易出错这时候就应该把确定性的逻辑写进脚本里由技能调用脚本完成。clean_csv.py的核心逻辑并不复杂但有几个点值得注意。第一脚本必须自带说明能从--help参数或注释里快速读懂输入输出。第二路径不能写死脚本的输入和输出路径由模型在执行步骤中通过参数传入。第三脚本遇到异常时要返回清晰的错误信息而不是静默失败。我把一个最小可用的示例写在这里方便你参照import argparse import csv from pathlib import Path def main(): parser argparse.ArgumentParser(descriptionClean a CSV file) parser.add_argument(input, typePath, helpinput CSV path) parser.add_argument(output, typePath, helpoutput CSV path) args parser.parse_args() if not args.input.exists(): raise SystemExit(fInput file not found: {args.input}) with args.input.open(r, encodingutf-8-sig) as f: reader csv.DictReader(f) rows list(reader) cleaned [] seen set() for row in rows: key tuple(row.values()) if key in seen: continue seen.add(key) # 这里可以继续按字段标准补全缺失值、校正类型 cleaned.append(row) with args.output.open(w, encodingutf-8, newline) as f: writer csv.DictWriter(f, fieldnamesreader.fieldnames) writer.writeheader() writer.writerows(cleaned) print(fCleaned {len(rows)} rows to {len(cleaned)} rows) if __name__ __main__: main()这里有个很容易踩的坑脚本里用了utf-8-sig去读文件是为了兼容带 BOM 头的 CSV输出时用标准utf-8是为了让下游工具处理方便。这些细节在 SKILL.md 的注意事项里都要点明否则模型会默认为“所有 CSV 都是规范的 UTF-8”。3.4 测试怎么验证一个技能真的“好用”写完之后不要急着用先做一套简单的测试流程。我会准备三个测试文件一个正常文件、一个脏数据文件、一个损坏文件。正常文件用来验证主流程通畅脏数据文件用来验证清洗逻辑真的生效损坏文件用来验证异常处理是否可靠。跑的时候注意观察模型有没有正确加载技能、判断调用时机、按 SKILL.md 里的步骤执行。我在实测中会特别关注一个现象“模型有没有跳过 SKILL.md 里某个步骤”。如果它跳过了通常不是模型不听话而是那个步骤写得不够明确或者与前后步骤的衔接缺少判断依据。这时候就去补 SKILL.md 中的描述而不是抱怨模型。经过两三轮这样的测试和修改技能基本上就能达到稳定可用的状态了。4. 实战中常见的坑与排查实录4.1 UTF-8 编码陷阱非 ASCII 字符引发的“离奇报错”先讲一个最莫名其妙、也最浪费我时间的坑。第一次按官方模板写技能时我在description里用了中文标点和较长的破折号结果加载时报了一串编码错误看起来像“expected a gateway model route instead”那种完全不搭边的信息。排查了半天才发现问题不在模型路由而在元数据的字符编码。name和description字段要求 ASCII 字符name里不要出现中英文之外的特殊字符description里要用直引号而不是弯引号也要避免使用中文全角标点。这个要求其实不是为了限制你而是因为技能元数据在加载时会按 ASCII 解析一旦混入非 ASCII 字符解析顺序就会错乱报错信息通常还非常抽象。解决办法很简单写完元数据后检查一遍凡是看到弯引号、全角冒号、中文括号全部替换成 ASCII 写法。顺带说一句正文 Markdown 部分反而没有这个限制可以放心用中文。4.2 description 冗余引发调用混乱另一个常见问题是 description 写得过长把执行步骤全部塞了进去。我最初也曾犯过这个错误为了让模型“充分理解”把清洗规则、字段标准、甚至脚本参数都写进了 description。结果模型确实每次都会尝试调用这个技能但因为它从 description 里拿到的是“残缺版的步骤说明”执行的时候反而忽略了 SKILL.md 正文走了错误的流程。正确的做法是description 里只放“触发信息”正文里才放“执行信息”。描述越精简模型的匹配越精准。我自己定了一个小规则description 不超过三句话每句话只负责一个信息层面——输入是什么、处理方式是什么、产出是什么、什么时候不调用。多一个字都不写。4.3 allowed-tools 限制过度技能“有劲使不出”allowed-tools本意是限制活动范围但限制过度也会出问题。之前我给一个技能只放了Read和Write结果模型在执行过程中连运行脚本的权限都没有每次到脚本环节就愣在原地。后来我把Bash也加了进去整个流程才顺畅。这个教训是allowed-tools要认真分析技能的完整执行链路把每一步可能用到的工具都列出来。你可以先按 SKILL.md 里的步骤逐个标注需要用到的工具再统一汇总到元数据里。宁可稍微放宽也不要因为缺工具导致技能中断。4.4 脚本缺少“防御式处理”代理容易自说自话还有一个我经常在别人技能里见到的毛病脚本对异常输入处理得太草率模型拿到的结果便不可信。比如读取一个空文件、遇到字段缺失、路径不存在脚本如果不给明确报错模型就会发挥想象力“脑补”一个结果然后把错误结果写进报告里。这类问题最好的解法就是在脚本里增加显式校验并在 SKILL.md 的注意事项中写明任何异常情况都要停止后续步骤并向用户说明原因。我见过一个不错的做法脚本里把每一个 error 都写成raise SystemExit(具体原因)模型看到明确的错误信息后会老老实实停下来向用户反馈而不是继续硬编。5. 从单个技能到技能资产库进一步延伸5.1 知识型、代码型、复合型技能的写法取舍当你开始积累第二个、第三个技能时你会发现不同类型技能的写作重心差异很大。知识型技能比如“公司文案风格检查”几乎没有脚本核心是把隐性的判断标准显性化写法上可以大量使用清单和对照表让模型逐项打钩确认。代码型技能比如“批量压缩图片”的核心在脚本质量SKILL.md 反而很短只需要讲清楚参数和数据流。复合型技能比如“周报自动生成”要同时在正文里平衡“流程描述”和“脚本调用”写作时最容易犯的错是流程描述太详细、导致模型频繁访问脚本而没有时间思考。我的建议是写新技能前先给技能分类然后按类别找参考写法不要所有技能都用同一套模板。知识型技能突出规则可执行性代码型技能突出接口稳定复合型技能突出分段清晰。5.2 技能库的命名、版本与团队协作技能一旦变多工程化管理问题就会浮出水面。命名上我建议所有目录名采用动作领域-对象类型的格式比如clean-csv、parse-resume、generate-report一眼能看出用途。版本管理可以直接挂在 Git 仓库里每个技能目录就是一次提交单元方便回溯和评审。最值得投入的是团队约定description 的写作规范、脚本的异常处理规范、reference 文档的组织规范这些约定会让整个技能库的可维护性大大提升。最后分享一个个人体会技能写作这件事表面上是写文档实际上是做知识提炼。你把自己在一个领域里的判断依据、操作步骤、异常处理全部梳理出来变成模型可执行的指令这个过程中你对那件事的理解反而会变得更清晰。所以哪怕你暂时不做 Agent 项目也建议拿一个最熟悉的小任务练手写一次技能。我第一次写过技能之后再去回顾自己平时处理数据的方式明显能看出哪些步骤是无效的、哪些判断是模糊的。这种反向的“技能化思考”恐怕是这个工具带给我最大的意外收获。