1. 从“写了50个Skill”到“前30个都白写”的真相我大概是在去年年底开始密集写 Claude Code Skill 的。那会儿刚把 Claude Code 装到 Ubuntu 和 Windows 两套环境里跑通觉得这东西太顺手了——终端里直接对话能读文件、能跑命令、能改代码比在 IDE 里来回切窗口舒服太多。于是我开始琢磨既然它支持自定义 Skill那我是不是可以把日常重复的活儿全封装成 Skill这个念头一开就收不住了。头一个月我写了差不多 30 个 Skill覆盖代码审查、接口文档生成、Spring Boot 监控配置、数据库迁移脚本、日志分析、单元测试补全……每个 Skill 我都认真写了SKILL.md定义了触发条件、输入输出、执行步骤。当时自我感觉良好觉得这套东西以后就是我的“自动化军火库”。结果用了两个月我发现自己真正高频调用的 Skill 不超过 5 个。剩下那 25 个要么触发条件写得太宽泛导致误触发要么步骤设计得太理想化、实际执行时到处报错要么就是我把一个本来用一条命令就能搞定的事硬生生拆成了七八步让模型去“理解”。更讽刺的是我后来重新写的第 31 到第 50 个 Skill数量少了但每一个的调用频率和稳定性都远超前面那 30 个。所以这篇东西不是教你“怎么写 Skill”的入门教程——那种内容网上已经很多了。我想聊的是为什么前 30 个会白写以及第 31 个之后我到底改了什么思路。如果你也在用 Claude Code、Codex、或者任何支持 Skill/MCP 的 Agent 工具正在兴冲冲地批量生产 Skill那这篇大概率能帮你省下至少一个月的无效劳动。先给个结论性的判断Skill 的价值不在于“能做什么”而在于“什么时候该被触发”以及“触发后能不能稳定收敛”。前 30 个我全在解决“能做什么”后 20 个我才开始认真对待“触发”和“收敛”。这个认知转变是整件事的分水岭。2. 前30个Skill到底错在哪四个反复踩中的坑2.1 把Skill当函数写忽略了它是“意图识别器”我最早写 Skill 的思路完全是后端开发的惯性定义一个输入定义一段处理逻辑定义输出。比如我写过一个“生成 Spring Boot Actuator 监控配置”的 SkillSKILL.md里列了十几个参数端口、暴露端点、健康检查路径、指标前缀……写得像一份 API 文档。问题在于Claude Code 调用 Skill 不是“传参调用”而是“根据你的自然语言描述判断该不该用这个 Skill然后从上下文里抽取参数”。我那个监控配置 Skill触发描述写的是“当用户需要配置 Spring Boot 监控时使用”。听起来没问题但实际上用户说“帮我看看这个服务的健康检查怎么加”“actuator 端点能不能只暴露 health”的时候模型不一定能稳定命中这个 Skill——因为我的触发描述太“正式”了跟真实对话里的口语表达对不上。后来我改成把触发描述写成“用户提到 actuator、健康检查、监控端点、metrics、health 等关键词或要求为 Spring Boot 服务添加运行时状态查看能力时”命中率立刻上来了。Skill 的第一性原理不是“功能封装”而是“意图匹配”。你得站在“用户会怎么随口说”的角度去写触发条件而不是站在“这个功能叫什么”的角度。2.2 步骤写得越细执行时崩得越惨第二个坑更隐蔽。我写过一个“数据库迁移脚本生成”的 Skill步骤列了 9 步读现有 schema、对比目标 schema、生成 diff、检查索引冲突、生成 up/down 脚本、加事务包裹、加回滚注释、输出到指定目录、提示人工复核。每一步我都写得清清楚楚。实际跑的时候第 3 步“生成 diff”就经常出问题——因为模型在不同上下文里对“diff”的理解不一致有时候它去调git diff有时候它自己脑补一个差异有时候它直接跳过。第 5 步“生成 up/down”又依赖第 3 步的结果一旦第 3 步跑偏后面全歪。我后来才明白Skill 的步骤不是给“执行器”看的是给“模型”看的。模型不是确定性的函数它每一步都在做概率判断。你步骤写得越细它需要做的判断越多累积误差越大。正确的做法是把步骤收敛到 3 到 5 步每步都是一个“高确定性的原子动作”中间不要留太多需要模型自由发挥的空间。比如那个迁移脚本 Skill我后来砍成 3 步第一步让模型读取当前 schema 文件并原样输出第二步让模型读取目标 schema 文件并原样输出第三步把两份内容一起交给一个专门的 diff 提示词处理。前两步是纯读取几乎不会错第三步虽然复杂但它是独立的一次模型调用失败了可以单独重试不会污染前面。2.3 没有“退出条件”Skill 会自己绕圈这是最要命的一个坑。我写过一个“日志分析”Skill目标是让模型读日志文件、找出异常模式、给出可能原因。触发描述没问题步骤也还算合理。但它经常陷入一种状态读一段日志说“这里可能有异常”然后去读更多日志又说“需要更多上下文”再读……最后要么超时要么输出一堆模棱两可的猜测。根因是我没定义退出条件。Skill 的SKILL.md里我只写了“做什么”没写“做到什么程度算完”。模型没有“够了”的概念它会一直尝试“更全面”。后来我在每个 Skill 里都强制加一段“终止条件”比如“当已识别出至少 3 类异常模式或已读取日志文件的前 500 行或连续两次读取未发现新异常时停止分析并输出结论”。这个改动看起来很小但效果立竿见影。没有退出条件的 Skill就像一个没有 base case 的递归函数迟早栈溢出。2.4 把MCP能做的事硬塞给Skill我早期还写过一个“查询本地数据库表结构”的 Skill让模型去执行mysql命令、解析输出、整理成表格。跑是能跑但极不稳定——数据库连接串变了要改 Skill输出格式变了要改 Skill权限不够了还要改 Skill。后来我把它换成了 MCP。MCP 协议本身就是为“工具调用”设计的数据库查询这种确定性操作交给 MCP Server 去做Skill 只负责“决定什么时候调用这个 MCP 工具”。职责一分开两边都稳了。这里有个判断标准我后来总结出来了任务性质该用 Skill 还是 MCP需要理解自然语言意图、做判断Skill确定性数据读写、命令执行MCP多步骤流程编排Skill 调 MCP单一原子操作MCP需要跨会话保持状态都不适合用外部存储前 30 个 Skill 里至少有 8 个是“本该是 MCP 却写成了 Skill”这是白写的重灾区。3. 第31个Skill开始的转向先想“触发”再想“功能”3.1 触发描述要写成“用户会说的话”不是“功能说明书”我现在的习惯是写任何 Skill 之前先不写功能先写 10 句“用户可能会怎么说”。比如我要写一个“接口文档生成”Skill我会先列“帮我把这个 Controller 的接口整理成文档”“这些 API 能不能生成一份 markdown”“我要给前端一份接口说明”“把这个类的请求参数和返回值列出来”“生成 swagger 那种文档”……然后我把这些句子里的共同关键词和表达模式提炼出来写进触发描述。这样写出来的触发条件命中率比“当用户需要生成接口文档时”高出一个量级。核心心法触发描述是“召回策略”不是“定义”。你要的是尽可能召回真实意图而不是精确描述功能边界。宁可稍微宽一点后面再用“排除条件”收窄也不要写得太窄导致该触发时不触发。3.2 一个Skill只解决一个“意图”不要贪多我早期特别喜欢写“全能型” Skill一个 Skill 里塞进“读代码、分析、生成文档、顺便检查规范”。结果就是触发条件模糊、步骤冗长、退出条件难定义。后 20 个我严格遵循“一个 Skill 一个意图”。比如“接口文档生成”和“接口规范检查”是两个 Skill哪怕它们都要读同一个 Controller。分开之后每个 Skill 的触发描述可以写得很精准步骤可以很短退出条件也很清晰。代价是有时候用户一句话会同时命中两个 Skill但那没关系——Claude Code 会依次调用或者你可以用一个“编排型” Skill 去串联它们。编排是编排执行是执行不要混在一个 Skill 里。3.3 用“反例”来校准触发边界这是我后来学到的一个很实用的技巧在SKILL.md里显式写出“什么情况下不要用这个 Skill”。比如“接口文档生成”Skill 里我会写“当用户只是询问某个接口的参数含义而不是要求生成完整文档时不要触发本 Skill。”这条反例一加误触发率明显下降。模型对“否定条件”的敏感度其实很高你给它一个明确的反例它就能更好地理解边界。这比你把触发描述写得更窄要有效得多因为写窄了会漏召回写反例则是在保持召回的同时提高精度。4. 让Skill真正跑起来的三个工程化细节4.1 SKILL.md 的结构我现在的固定模板踩了那么多坑之后我现在的SKILL.md基本固定成这么几块# Skill 名称 ## 触发条件 - 用户表达意图 A 时触发 - 用户提到关键词 B、C、D 时触发 - 反例当用户只是……时不要触发 ## 前置检查 - 确认当前工作目录存在 xxx 文件 - 确认 xxx 命令可用 - 若不满足提示用户并终止 ## 执行步骤 1. 原子动作一高确定性 2. 原子动作二高确定性 3. 复杂处理可独立重试 ## 终止条件 - 满足条件 X 时停止 - 连续 N 次无新发现时停止 - 超过 M 步未收敛时停止并输出当前结果 ## 输出格式 - 固定输出为 markdown 表格 / JSON / 纯文本 - 必须包含字段xxx、yyy ## 失败处理 - 步骤 1 失败提示用户检查 xxx - 步骤 3 失败回退到步骤 2 的结果并输出这个模板不是拍脑袋来的每一块都对应我之前踩过的一个坑。触发条件对应“意图匹配”前置检查对应“环境假设”终止条件对应“绕圈”失败处理对应“崩了之后没法恢复”。4.2 参数不要“传”要“抽”前面提过Skill 不是函数调用。但很多人包括早期的我还是习惯在SKILL.md里定义一堆参数让用户填。这是错的。正确做法是在步骤里写清楚“从上下文抽取什么信息”。比如步骤 1从用户当前对话或最近打开的文件中抽取目标 Controller 类名。若无法确定询问用户。这样模型会自己去上下文里找而不是傻等用户传参。实测下来这种“抽取式”写法比“参数式”写法的成功率高出很多因为用户根本不会按你定义的参数格式说话。4.3 测试Skill的正确方式构造“脏输入”我早期测试 Skill都是拿“标准输入”测——比如规规矩矩地说“请为 UserController 生成接口文档”。测出来都通过一上真实场景就崩。后来我改成专门构造“脏输入”来测口语化输入“那个用户接口的文档帮我搞一下”带错别字输入“生成 user controler 的接口文档”混合意图输入“帮我看看 UserController 有没有问题顺便生成个文档”缺上下文输入“生成接口文档”不说哪个类只有这些“脏输入”能稳定通过Skill 才算真正可用。标准输入通过只说明“理想情况下能用”脏输入通过才说明“真实场景下能用”。5. 那些“白写”的Skill后来怎么处理的5.1 直接删掉的约12个前 30 个里有大约 12 个我最后直接删了。删掉的标准很简单连续一个月没有被自然触发过或者触发后我每次都手动中断。这些 Skill 的共同特征是解决的是一个“我臆想出来的需求”而不是“我真实高频遇到的需求”。比如我写过一个“自动生成 CHANGELOG”的 Skill但实际上我项目的 CHANGELOG 是手动维护的根本不需要自动化。写它纯粹是因为“觉得这个功能很酷”。这件事给我的教训是Skill 的需求应该来自“我重复做了三次以上的事”而不是“我觉得这件事可以自动化”。前者是真实需求后者是自我感动。5.2 拆成MCP的约8个前面提过有 8 个左右是“确定性操作”被硬写成了 Skill。这些我后来都改成了 MCP ServerSkill 只保留一个“什么时候调用”的薄壳。拆完之后最大的感受是稳定性提升了一个数量级。因为 MCP 是真正的代码执行不受模型概率判断影响而 Skill 只负责“决定调不调”这个判断即使偶尔出错代价也很小。5.3 合并重写的约10个还有 10 个左右是“意图太碎”或者“步骤重叠”的我把它们合并成了 4 个新 Skill。比如原来有“读 Controller”“分析参数”“生成文档”“检查规范”四个 Skill后来合并成“接口文档生成”和“接口规范检查”两个。合并的原则是如果两个 Skill 的触发场景高度重叠且执行步骤有 50% 以上重合就该合并。分开写只会增加维护成本和误触发概率。6. 如果你现在要写第一个Skill我的建议顺序6.1 先别写先记录一周我的建议是在写任何 Skill 之前先花一周时间记录你每天在 Claude Code 里重复输入的命令或提示词。不用很正式就记在备忘录里。一周后你回看哪些模式出现了 3 次以上那些才是值得写成 Skill 的。我后来第 31 到 50 个 Skill全部来自这种“真实重复记录”没有一个是我拍脑袋想出来的。这也是为什么它们的使用率远高于前 30 个。6.2 从“只读型”Skill 开始如果你刚开始写我强烈建议从“只读型” Skill 入手——就是那些只读取信息、不修改任何东西的 Skill。比如“分析日志”“读取配置并解释”“列出接口清单”。原因很简单只读型 Skill 即使触发错了、执行歪了也不会造成破坏。你可以放心地观察它的行为慢慢调触发条件和步骤。等你对 Skill 的行为模式有感觉了再去写“写入型”的。我前 30 个里有一半是写入型结果就是每次出错都要手动回滚调试成本极高。后 20 个我从只读型重新起步学习曲线平缓了很多。6.3 给每个Skill设一个“观察期”新写的 Skill 不要立刻当成正式工具用先给它两周观察期。这两周里每次它被触发你都记录一下触发得对不对、步骤跑得顺不顺、输出有没有用。两周后如果触发准确率低于 80%或者你手动中断超过 3 次就回去改触发描述或步骤。改完再观察两周。一个 Skill 从写完到稳定通常需要 2 到 3 轮这样的迭代。前 30 个我都是写完就用从不回看所以一直不稳定。7. 关于MCP和Skill的边界再说几句实在的现在网上关于 MCP 和 Skill 的讨论很多但很多都停留在概念层面。我说几个我实际用下来的判断标准第一看操作是否“可枚举”。如果一个操作的输入输出可以完全枚举清楚比如“查询某张表的某几列”那它适合 MCP。如果输入输出依赖自然语言理解比如“分析这段代码有没有坏味道”那它适合 Skill。第二看失败代价。MCP 失败通常是明确的报错容易定位Skill 失败往往是“输出了一段看起来对但实际不对的内容”隐蔽性强。所以高风险操作尽量走 MCP让失败显性化。第三看复用范围。MCP Server 可以被多个 Skill、多个工具复用Skill 通常是绑定在特定 Agent 上的。如果你发现某个能力会被反复用到把它下沉成 MCP 更划算。我现在的项目里MCP 负责“手脚”Skill 负责“大脑”。手脚要稳大脑要灵活。两者职责分清之后整个系统的可靠性比早期“全塞进 Skill”高太多了。8. 最后分享几个我压箱底的小技巧第一个技巧在 Skill 的触发描述里加入“时间/频率”维度。比如“当用户在同一会话中第三次提到某个接口时触发”。这个技巧对“整理类” Skill 特别有用能避免用户只是随口一提就被触发。第二个技巧给 Skill 加一个“干跑模式”。在SKILL.md里写“若用户说‘先看看’‘模拟一下’则只输出将要执行的步骤不实际执行”。这个模式在调试新 Skill 时极其好用也方便你向别人演示。第三个技巧把常用的 Skill 组合成一个“元 Skill”。比如我有“接口文档生成”“接口规范检查”“接口测试用例生成”三个 Skill我又写了一个“接口全流程处理”的元 Skill依次调用它们。这样用户一句话就能跑完整个流程不用分别触发。第四个技巧定期清理。我现在的习惯是每个月回看一次所有 Skill 的调用记录把连续一个月没被触发的标记出来连续两个月没被触发的直接删。Skill 库跟代码库一样不清理就会腐化。写 Skill 这件事说到底是在跟“模型的概率性”打交道。你越想让它精确它越容易在你没预料到的地方跑偏。前 30 个我一直在对抗这种概率性后 20 个我学会了顺着它设计——把不确定性收拢到少数几个可控的环节其余部分尽量做成确定性的原子动作。这个思路转变之后Skill 才真正从“玩具”变成了“工具”。如果你现在正写到第 10 个、第 20 个感觉越写越累、越写越不好用别急着怀疑自己。很可能你只是还没到那个“该转向”的点。我是在第 30 个之后才想明白的希望你能比我早一点。
企业数字化 ERP 产品动态
相关推荐
AST解析技术逆向Akamai动态参数生成实战 1. 项目概述:Akamai动态参数逆向与AST解析实战在Web安全与爬虫对抗领域,Akamai的防护机制一直以复杂多变著称。最近在分析某电商平台时,发现其前端接口调用包含三个关键动态参数(ver、din、ajr),这些参数由… · 2026/11/3 13:37:33
openWakeWord实战:本地语音助手唤醒词检测原理与部署指南 做本地语音助手的朋友,大概率都卡在“唤醒词”这一关。我一开始做声控灯光原型,图省事用了云端的语音识别SDK,结果每次都得先把音频传出去,等云端返回结果,那个延迟直接让人想砸键盘。后来换成了开源组件openWakeWord&… · 2026/11/3 2:54:09
Linux Qt 摄像机 SDK + FFmpeg 低延迟解码上屏链路拆解 简介:面向Linux平台多媒体开发者的Qt、大华摄像机SDK与ffmpeg整合工程包,适合已具备C与Qt基础、需要打通设备取流到界面显示链路的中高级开发者参考。压缩包共2000个文件,以C源码、头文件、o目标文件、d依赖文件和Makefile/mak构建脚本为主体… · 2026/11/3 13:36:30
EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析 1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被… · 2026/11/5 16:49:35
Rust原来很简单二:所有权系统 Part 2 核心篇 —— 所有权系统
本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理
6… · 2026/11/5 16:26:08
基于Hadoop+Spark的民宿智能推荐系统设计与实现 1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享… · 2026/11/5 14:59:25
ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配RS485,解决远距离温度监控难题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07
多智能体协作系统架构设计与实践优化 1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39
大模型系统性入门实战指南:从原理到部署微调的全链路路线 提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39
鸿蒙文件系统沙箱机制解析与开发实践 1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07