你有没有发现,现在的AI Agent项目越写越像一团乱麻?系统提示词从100行膨胀到2000行,工具函数堆了几十个,模型每次执行任务都要在一堆“可能有用”的选项里做选择——更头疼的是,换个项目,这套提示词和工具几乎没法平移,只能推倒重来。我一直觉得,Agent开发最大的瓶颈早就不是模型智商,而是能力怎么被组织、怎么被复用。Claude Skills官方指南发布之后,这个判断终于有了一个体面的解决方案:把Agent的能力从“提示词堆砌”切换到“能力模块”。
这篇文章我会从开发者的实际视角出发,拆解Skills到底改了什么、底层运行机制长什么样、怎么动手封装一个真实可用的技能,以及为什么说这标志着Agent开发进入了“能力模块时代”。不管你是刚开始接触Agent开发的新人,还是已经在用LangChain、LangGraph做过项目的熟手,这篇都值得花十分钟看完。
1. 从“提示词堆砌”到“能力模块”:Claude Skills到底改了什么
1.1 没有Skills之前,Agent开发的三座大山
聊Skills之前,先复盘一下过去Agent开发为什么这么难受。我拆解了大量项目之后发现,大家遇到的坑高度一致。
第一座大山是提示词膨胀。最初写Agent,谁都觉得自己在“调教模型”,system prompt从“你是一个助手”开始,不断追加业务规则、输出格式、示例对话、边界条件,最后变成一份几百上千行的巨型文档。问题是模型对上下文的注意力是有限的,规则越多,每条规则的权重就被稀释,经常出现“你明明写了不许瞎编,它还是给你编出个不存在的API”这种情况。
第二座大山是工具函数变成垃圾桶。为了覆盖所有可能的需求,开发者习惯把能想到的函数都注册成工具:查数据库、读文件、发请求、算时间……结果模型每次调用前都要做一轮“工具选择”,工具一多,选错的概率直线上升,而且上下文里塞满了几十个工具的JSON Schema定义,token消耗巨大。
第三座大山是复用几乎等于复制粘贴。这个项目里调好的提示词和工具,到了下个项目要么重写,要么靠开发者脑子里的“隐性知识”带过去。团队换个人,经验就断档了。更别提测试——提示词没法单元测试,只能靠人工反复试,改一行字都可能引发连锁回归。
1.2 Skills的核心理念:把“会做某件事”打包成文件
Claude Skills的做法,等于把上面三座大山一次性拆掉。它的核心逻辑非常朴素:把“如何做某件事”的完整知识——包括指令、流程、示例、可执行脚本——打包成一个目录,这个目录就是一个技能模块。
一个典型的Skill由两部分组成:一份SKILL.md文档,里面写清楚这个技能是干什么的、该怎么干、输出什么格式;再加上一个可选的scripts目录,存放真正执行任务的代码。模型在使用Agent时,会在项目启动阶段扫描本地的技能库,根据当前对话内容和技能的描述,动态决定加载哪个技能,然后把对应的SKILL.md内容注入到上下文里。
你可以把这个机制理解成给模型发了一本“职位说明书”。模型本身拥有强大的推理能力,但它不知道你们团队的代码规范、不知道你习惯的审查流程、不知道怎么调用你们内部平台。Skills解决的就是这个问题:把“这个岗位的做事方法”提前写成手册,模型需要时翻开就能用,用完就合上,不污染其他任务。
1.3 官方指南发布的三层信号
官方指南的发布,在我看来传递了三个明确信号。
第一,能力标准化。之前Agent开发是“八仙过海”,每个人有自己的一套提示词心法。官方指南直接给出了技能结构、编写规范、质量要求,等于把“能力模块”做成了一个有统一接口的工业标准,而不是某个人的独门绝技。
第二,上下文按需加载。这是Skills最实在的技术红利。旧模式里,所有指令和工具定义常驻系统提示词,占用上下文窗口;新模式里,技能描述只要几十个token常驻,真正的内容在需要时才会被注入。模型的“注意力预算”一下子宽裕了,任务完成质量自然会上升。
第三,生态化。当能力可以被标准化封装,它就能像软件包一样流通:个人开发者可以沉淀自己的常用技能,团队可以维护一套共享技能库,社区可以发布开箱即用的高质量Skills。这和我之前写那篇Agent并发问题的文章里判断的方向完全一致——Agent的能力正在从“每个项目内联”走向“模块复用”。
2. 一份SKILL.md是怎么被用起来的:运行机制拆解
2.1 最小目录结构与frontmatter
先看一个最小可用的Skill长什么样。我在项目里通常按下面这个结构组织:
code-review-skill/ ├── SKILL.md └── scripts/ └── review.py关键是SKILL.md,它的开头必须有一段YAML格式的frontmatter,至少包含两个字段:name和description。我给个实际例子:
--- name: code-review description: 对 Git diff 进行系统化代码审查,覆盖安全、性能、可维护性和测试充分性,按要求输出结构化审查报告。 --- 你是一位资深代码审查专家。收到审查请求后,严格按以下步骤执行: 1. 如果有 diff 内容,先自己通读一遍,理解变更意图。 2. 从安全、性能、可维护性、测试覆盖四个维度逐项分析。 3. 使用 `scripts/review.py` 对 diff 做基础扫描,结合脚本结果人工判断。 4. 最终输出 Markdown 格式报告,按“问题级别/规则名/问题说明/修复建议”的表格汇总。你会发现SKILL.md的正文本质上还是提示词,但它被结构化地放进了文件里,并且有了“身份信息”和“触发条件”,这就和挤在系统提示词里的一堆规则有了本质区别。
2.2 动态注入:模型什么时候“看见”你的Skill
理解Skills的触发机制,是避免“写了技能但不生效”的关键。启动Agent后,系统会扫描技能库目录,读取每个技能frontmatter里的name和description,但并不把正文全部读入上下文——那样的话上下文照样爆炸。
真正发生的是渐进式披露:模型在对话时拿到一份技能清单,每个技能只带几十个字的描述;当用户需求与某个技能的description匹配时,系统才把完整的SKILL.md正文注入到上下文里。这就像你办公室墙上贴着一张“各部门电话表”,你只会打给当前需要的部门,不会把所有部门的规章制度背下来。
日常写代码时我有个心得:description写得越具体,触发的精准度越高。你可以把常见场景、触发条件、甚至排除项都写进去。比如我那个代码审查技能,description里我会明确写“仅适用于Git仓库,不适合处理非代码文本审查”,避免模型看到包含代码的文档也去调用审查流程。
2.3 脚本层:不仅能给提示词,还能真正“干活”
如果Skills只是“外部化提示词”,那它还没跳出传统Prompt Engineering的范畴。官方指南真正往前走的一步,是把可执行代码纳入了技能模块。
脚本层的设计有一门学问。首先,脚本入口要接收清晰参数,尽量做“窄接口”,也就是只做一件事,不要一个脚本包罗万象。其次,输出必须是结构化内容,最好用JSON、Markdown表格这类模型容易解析的格式,因为脚本执行结果还要回流到模型那里参与推理。最后,超时控制一定要有,一个技能脚本如果跑几分钟没结果,整个Agent交互节奏都被拖垮。
我建议新手从“增强型技能”入手:不给模型单独执行脚本的能力,而是让模型先思考,再调用脚本做验证,最后结合脚本结果给结论。这样既发挥模型推理优势,又利用脚本做事实校验,出错率会低很多。
2.4 触发失败时:description写不好,Skill就永远沉睡
我见过太多人写了精美的SKILL.md,但实际使用率几乎为零,原因基本都是description质量差。描述写得过于宽泛,比如“帮助用户处理代码”,那模型加载它的概率就会很低,因为适配场景满天飞;描述写得过于狭窄,只覆盖某个冷门场景,那日常根本碰不到。
更常见的一个坑是:description里写的是“你能做什么”,而不是“用户在什么情况下需要你”。官方指南里特别强调从用户意图出发——与其写“能够分析代码质量”,不如写“当用户要求检查代码变更、找Bug或评估性能风险时使用”。前者是能力的自我描述,后者是触发条件,模型决策时看的是后者。
另外,同名冲突也要注意。如果你在全局技能库里有一个“代码审查”,项目技能库里又有一个同名技能,最终加载哪个取决于具体实现策略,但这类冲突会浪费一部分技能调试时间。我现在的习惯是:全局技能只放通用能力,项目技能一律加上项目名前缀,比如“shopifly-checkout-review”,降低混淆概率。
3. 动手封装一个真实可用的Skill:以代码审查助手为例
3.1 为什么选“代码审查”做第一个实战例子
理论讲一堆,不如亲手做一个。我选代码审查当例子,因为它有三个特点:需求高频、边界清晰、结果可量化。几乎所有开发团队都需要代码审查,而审查流程有明确的输入(diff)和输出(结构化报告),非常适合模块化封装。
在动手之前我先做了需求拆解。这个技能要解决的核心问题是:让模型用团队统一的审查标准检查代码变更,而不是每次带着不同偏好随意审查。拆解下来需要三个能力:理解变更、执行基础规则扫描、输出标准报告。
3.2 编写SKILL.md正文:规则优先还是流程优先
SKILL.md正文编写有个容易犯的错误:一上来就堆规则,什么“禁止使用eval”“不允许硬编码密钥”,模型确实记住了,但面对一个具体diff时,不知道该从哪头开始。我的做法是流程优先,规则嵌在流程里。
--- name: code-review description: 当用户要求检查代码变更、找Bug、评估合并风险或进行代码审查时使用此技能。适用于任何Git仓库。 --- # 代码审查执行流程 你是团队资深代码审查者,每次审查必须按下面四步走: ## 第一步:获取变更内容 调用 `scripts/review.py diff` 获取当前分支相对主分支的变更。 ## 第二步:逐项规则扫描 对照脚本输出的检查项逐条确认: - 安全类:硬编码密钥、SQL拼接、危险反序列化、路径穿越 - 性能类:N+1查询、循环内请求、大对象深拷贝 - 可维护性:魔法数字、重复代码、不合规范的命名 - 测试类:新增逻辑是否有对应单测,改动是否影响已有用例 ## 第三步:分类汇总 把问题按 P0(必须修复)、P1(应当修复)、P2(建议优化)分级。 ## 第四步:输出报告 最终必须使用以下 Markdown 模板,禁止跳过任何字段: | 优先级 | 规则名 | 文件位置 | 问题说明 | 修复建议 |这个结构的好处是:模型先有执行路径,再有质量标尺。而且模板限定了输出格式,下游可以直接解析,不会出现“自由发挥”的报告。
3.3 设计scripts/review.py:窄接口、结构化输出
脚本层我不贪多,只做模型不愿意做或容易做错的事:从Git里拿diff、针对几个确凿信号做静态扫描。一个最小可用的版本大概长这样:
#!/usr/bin/env python3 import json, subprocess, sys def get_diff(target="main"): result = subprocess.run( ["git", "diff", target + "...HEAD"], capture_output=True, text=True ) return result.stdout def scan(diff_text): findings = [] patterns = { "hardcoded-password": ["password\\s*=\\s*['\"][^'\"]+"], "eval-usage": ["\\beval\\("], "sql-concat": ["['\"]SELECT.+\\+"], "TODO-mark": ["TODO"], } for rule_name, regex_list in patterns.items(): for regex in regex_list: import re match = re.search(regex, diff_text, re.IGNORECASE) if match: findings.append({"rule": rule_name, "level": "warning"}) return findings if __name__ == "__main__": diff = get_diff() found = scan(diff) summary = { "diff_chars": len(diff), "findings": found, } json.dump(summary, sys.stdout, ensure_ascii=False, indent=2)实际项目中我还会加一个参数来控制对比分支,以及把扫描规则写成JSON配置,方便团队维护。核心原则没变:脚本接收明确的入参,返回结构化的JSON,绝不把业务规则糊死在脚本里。
3.4 实测中的三个意外:输出漂移、路径硬编码、中英文混杂
跑起来之后,我踩了几个非常典型的坑,值得单独拿出来说。
第一个是输出格式漂移。虽然SKILL.md里给了表格模板,但模型偶尔会在报告末尾追加“总结评价”“改进建议”这类多余段落。处理方式是在模板下面补了一行“输出规范:报告结束于表格最后一行,不要追加任何额外章节”,并且说明这是硬性要求。
第二个是脚本路径硬编码。我在脚本里写死了main分支名,结果团队有些项目主分支叫master,还有的用trunk。这个坑排查了很久才发现——模型并不知道你的默认分支叫什么,它只会傻傻地执行。后来我把分支名变成了配置项,默认main,同时允许在触发时传参。
第三个是中英文混杂。SKILL.md里中英混合,脚本输出是英文,模型生成的报告时而中文时而英文。团队做中文文档时很别扭。我的解法是在SKILL.md里显式声明“审查报告必须使用中文,规则名保留英文”,模型对这个约束的遵守度比我预期好得多。
3.5 从个人能用,到团队都能用:落地要点
开发完技能之后,我从个人使用扩展到团队使用,过程中发现了几件必须处理的事:版本管理、权限边界和效果度量。
技能目录应该进Git仓库,团队所有人都能共享,并且通过Pull Request来变更技能——审查技能的变更比审查普通代码变更更需要谨慎,因为影响面是全体使用者。权限方面,脚本里不能做危险操作,比如自动push、删除分支,只能做只读扫描。效果度量我推荐一个土办法:每次审查完让模型自己输出一条“本次审查发现有效问题数”,定期汇总,观察技能调整前后这个数字的变化,比任何花哨的仪表盘都直观。
4. 为什么说Agent开发进入“能力模块时代”
4.1 旧范式是把流程写死,新范式是把能力攒起来
很多从LangChain、LangGraph切入Agent开发的朋友会问:Skills和这些编排框架是什么关系?我的理解是,它们解决的是完全不同层次的问题。
LangGraph这类框架关注的是“流程编排”——定义节点、边、状态机,让模型在固定流程里流转。这种模式适合业务流程稳定、步骤明确的场景,比如订单处理、审批流。但问题也明显:流程一旦复杂,状态管理成本飙升,而且你编排的其实是“已知路径”,模型的能力边界被框死了。
Skills代表的是一种恰恰相反的哲学:不预设流程,只提供能力模块。模型拿到一组Skills之后,走哪条路、调哪个技能、按什么顺序组合,完全由它在对话中自主决定。这就像你给一个员工配齐全套工具,而不是画好只能走一条路的走廊。对Agent开发来说,这是从“写剧本”到“攒装备”的范式切换。
4.2 能力模块化的三个真实收益
从工程实践角度,我体感最强的收益有三个。
第一,上下文瘦身。这点前面提过,但怎么强调都不为过。以前工具定义和规则说明常驻上下文,现在换成几十个token的技能描述。我实测过,同等任务下,使用Skills后上下文占用下降40%到50%,模型注意力明显更集中。
第二,横向复用。同一个“需求梳理”技能,可以在客服Agent、项目管理Agent、文档助手之间复用;“数据库操作规范”技能,所有和数据打交道的Agent都能挂载。能力复用了,开发新Agent的速度会快得惊人。
第三,测试边界清晰。提示词没法单测的痛点,在Skills时代有了解法:因为技能是独立模块,你可以针对单个技能构造测试用例,检查输出格式、规则覆盖度、边界场景表现。我把技能测试用例放在仓库的tests/目录下,每次改动技能就跑一遍,回归成本远低于监测整个系统提示词。
4.3 与MCP的分工:大脑和器官各司其职
讨论Skills绕不开MCP。总有人问两者是不是重复造轮子,我的看法完全不是。MCP解决的是“模型怎么连接外部世界”——数据库、API、文件系统这些数据源和工具端点,它是“器官层”。Skills解决的是“模型怎样高效正确地做事”——把做事的方法论、规则、步骤封装成模块,它是“大脑的方法层”。
实际操作里两者经常配合使用:一个AGENT可以通过MCP连接到GitLab,但审查代码该怎么审、按什么标准、输出什么报告,这些规则来自Skills。MCP提供工具,Skills提供方法,一条链路非常清晰。
4.4 对团队协作模式的影响:每个角色都能沉淀自己的技能
能力模块化带来的另一个变化,是团队里非算法岗的人也开始参与Agent能力建设。前端可以把组件规范写成Skill,让Agent按照团队风格生成代码;测试可以写“测试用例设计”Skill,把评审多年的经验固化下来;运维可以把常见排障步骤封装成技能。
你可以这样想:以前“优化Agent”是少数写提示词工程师的工作,现在变成了整个团队知识资产沉淀的自然结果。让Agent学习团队经验这件事,不再发生在某个神秘的系统提示词文件里,而是发生在每个成员都能提交申请、评审、更新的技能仓库里。这种改变对团队协作的推动力非常值得期待。
5. 边界、踩坑与进阶建议:Skills不是什么万能药
5.1 这些场景不适合做成Skills
任何技术都有边界,Skills也不例外。至少三类场景我不建议硬套。
第一类是高频、长时、有状态的任务。比如“持续抓取某平台数据并同步”,这类任务需要常驻状态、频繁执行,适合独立服务而不是一次性技能。第二类是深度依赖特殊硬件或外部设备的功能,比如操纵机械臂、读取传感器,这些必须通过专用服务来做,Skills里的脚本做不到。第三类是强约束流程,比如金融交易里的严格审批链路,状态机比自由的技能组合更安全可靠。
判断标准其实就一条:这个能力是否需要“在某个工作场景里被重复调用,并且每次调用都是相对独立的一次性执行”。满足这个条件,Skills会很舒服;不满足,硬做只会给自己添乱。
5.2 踩坑实录:我踩过的三个典型坑
除了前面提到的那三个实战意外,还有三个更隐蔽的坑,值得所有工程团队警惕。
第一个坑是description过于宽泛导致的误触发。我给一个内部“发布检查”技能写了“当你需要上线或发布时使用”,结果Agent在帮人写技术方案时也莫名其妙地把发布检查的规则注入进来,输出了一堆渲染无关的内容。修复方式是给description加上排除项:“仅当用户明确表达‘准备发布’时使用,讨论发布方案或写发布文档不属于本技能范围。”
第二个坑是脚本输出缺少schema约束。早期我让脚本返回自由文本,模型解析时频繁出错。后来所有脚本统一改成JSON输出,并且在SKILL.md里附上JSON字段说明。模型那边就稳定了很多,相当于你给模型一个明确的“数据结构契约”。
第三个坑是全局Skill和项目Skill的优先级冲突。当两个技能互相矛盾,比如全局说“禁止输出英文报告”,项目技能里又没提语言,模型就会随机发挥。解决办法是我在项目技能里增加“本技能优先级高于全局通用规则”的声明,并且坚持同一语义的技能只保留一个版本,名称也尽量唯一。
5.3 关于性能和并发:静态加载带来的天然优势
“AI Agent怎么扛并发”是开发群里反复出现的问题,Skills在这方面有自己的独特优势。由于技能模块是静态文件,不涉及运行时动态注册,加载阶段消耗极低,多个Agent实例可以共享同一套技能库内存。最吃性能的反而是执行脚本和上下文处理,前者可以用外部服务横向扩容,后者靠合理控制技能注入量来优化。
我的建议是:技能里的脚本要当作“独立函数”来写,无状态、幂等、可重入,这样并发请求再多都不会互相干扰。绝对不要在技能脚本里写全局文件锁或者依赖本地缓存的逻辑,否则并发一上来就各种超时。这套经验在多个项目里实践下来都很稳定。
5.4 如果你今天想开始,我的建议路径
最后给想入坑的朋友一条务实路径。
第一步,先抄后改。官方示例里有现成的技能模板,不用自己从零发明,选一个高频场景,比如文档格式化、代码规范检查,把官方示例改成你团队的样子,跑通一个完整的“触发—加载—执行—输出”过程。
第二步,从“小技能”做起。不要一上来就搞一个包罗万象的大技能,而是把一个狭窄动作做透。比如“把任何英文技术文档翻译成中文术语统一的技术文档”,这种粒度足够小、效果立刻可见,能帮你快速建立信心。
第三步,维护自己的技能库。日常工作中发现重复劳动,就问自己一句:这个行为能沉淀成一个技能吗?把零散的规则不断写进SKILL.md,持续迭代。三个月后,你手里积累的技能库就是别人拿不走的团队资产。
我自己实践下来最深的体会是:Skills并不是什么新魔法,它只是把Agent开发的“能力组织方式”从临时状态变成了可管理状态。真正让它有价值的,是你在技能里沉淀的领域经验——那个东西永远是稀缺的。代码会过时,模型会升级,但一套好的“做事方法”模块,会跟着你的团队一直用下去。