ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent Skills实战:用SKILL.md把AI工作流固化成可复用技能包

Agent Skills实战:用SKILL.md把AI工作流固化成可复用技能包 最近在 AI Agent 圈子里skills 从普通名词变成了技术热词。我第一次听到“Agent Skills”的时候以为又是提示词工程的变种——无非是给AI多背几段规矩。直到我把一份重复粘贴了三周的报表处理流程做成了一个技能文件夹才真正理解它的价值你用一份说明书和一两个脚本把AI干活的规矩固化下来下次它自己就能照章办事。这篇文章不绕弯子我按照“概念→结构→实操→调试→管理”五个部分讲透。适合两类人一类是天天跟AI协作、嫌重复劳动烦的开发者另一类是团队里想把AI工作流沉淀成标准资产的负责人。如果你目前只把AI当聊天窗口用看完这篇也能理解“给AI定义技能”为什么正在成为工作流里的基础操作。1. Skills不是提示词工程它到底改变了Agent的什么能力1.1 一个让我决定转用Skills的真实场景前一阵我在做报表自动化项目每周收到的PDF五花八门有扫描件、有导出文件字段命名还不统一。每次我把文件丢给Claude处理都得先介绍一遍这是什么类型的报表再贴一次字段映射规则再规定输出格式最后还要叮嘱一句数字单位别搞错。一开始觉得没什么多写两句而已。连续三周之后我发现同一套指令我在不同会话里粘贴了超过十次每次还要微调漏掉一句输出表格就少一列。后来我把整个流程做成一个Skill——一个带SKILL.md说明文档和Python脚本的文件夹放在约定的技能目录里。第二次再处理新报表我只说了一句“按报表提取技能处理这个PDF”它就自动读说明书、调脚本、按模板输出。那一刻我确定Skills解决的不是“多一个功能”而是“少一整套重复解释”。这也是我后来愿意花时间把工作流技能化的直接原因。1.2 Skills是什么一份能执行的岗位操作手册用大白话解释一个Skill就是三样东西的集合一个SKILL.md说明书一个放脚本和模板的资源目录以及一段写在说明书头部、负责触发技能的description。SKILL.md里写清楚“这个技能干什么、什么场景用、执行分几步、输出长什么样”资源目录里的脚本负责干机械活比如解析PDF、计算汇总、转换格式description则像是技能关键词索引Claude拿到用户请求后会先扫一遍所有可见技能的description语义匹配上了才打开那份说明书。这和传统提示词工程的差别在于一次性和可复用。Prompt是每次对话里临时发的指令换一个会话就要重新发一遍Skill是文件化的规则只要技能文件放在正确位置它就像肌肉记忆一样沉淀在Agent的运行环境里。Claude Code以及Claude应用端都在往这个方向走以后你维护的不只是“人话话术”而是一个个带说明书和代码的技能包。1.3 和MCP、子代理怎么区分不是二选一是搭伙干活我见过最多的问题就是“Skills和MCP不是一回事吗”。MCP解决的是“AI怎么连外部工具和数据”重点在通信协议相当于给Agent装插座Skills解决的是“取到数据之后按什么规矩干活”重点在指令和脚本相当于给Agent塞操作手册。一个典型配合是用MCP让Claude连上内部数据库或表格服务再用Skill教它取到数据后怎么清洗、怎么填报表、怎么处理异常。子代理也不一样。子代理解决的是分工相当于把一个完整任务拆给不同角色的人Skill解决的是能力相当于让同一个人学会更多手艺。你可以让一个担任“数据工程师”角色的子代理带上一组报表清洗、字段映射、格式校验的Skills去干活。把三者的边界整理成一张表方便对照名词本质解决的核心问题使用成本Prompt提示词每轮对话的指令结果不稳定、上下文重复低但需要每轮维护Skill可复用的说明书脚本包流程沉淀不下来中建一次长期复用MCP外部工具连接器AI连不上内部服务和数据源中高需要接口配置子代理独立角色/职责的工作单元复杂流程的角色和任务边界高适合复杂编排我的建议是别急着把所有东西都做成Skill。原则很简单同一个流程重复三次以上、规则清晰、结果能验收就固化成Skill一次性的探索性需求继续用普通对话处理。否则技能库很快就长出一堆没人维护的僵尸文件反而干扰Agent判断。2. 拆解SKILL.mdClaude靠这份说明书完成“自我安装”2.1 最小目录结构一个方案最少需要哪些文件一个技能的最简结构如下pdf-report-extractor/ ├── SKILL.md └── scripts/ ├── extract_pdf.py └── requirements.txtSKILL.md是唯一必须存在的文件脚本、模板、参考数据都是可选的。技能文件通常放在个人级目录~/.claude/skills/放在这里的所有技能对所有会话可见如果技能和某个项目强绑定可以放到项目根目录下的.claude/skills/这样只有在该项目里会加载。早期我不建议一上来就铺到个人目录先放在项目目录里试错等稳定了再提升到全局范围。2.2 frontmatter字段description写得好技能才容易被叫醒SKILL.md的开头必须有一段YAML frontmatter最少要有name和description两个字段--- name: pdf-report-extractor description: 当用户需要从PDF或扫描件中提取销售/库存报表的结构化数据包括金额、数量、日期、订单号等字段时使用。如果用户只是让阅读PDF并总结内容不要使用本技能。输出CSV文件。 ---name建议统一用小写连字符命名比如pdf-report-extractor不要用空格和特殊符号。description是一段给Agent看的关键词索引它决定Claude会不会把这个技能“叫醒”。我踩过最大的坑就是description写得太正经用户说“帮我把发票上的税额摘出来”而description里只有“发票信息提取”语义匹配度不够技能死活不触发。后来我的写法是把用户可能使用的自然语言问法、同义词、边界条件全部塞进去比如加上“税号、识别号、票面金额、报销单、金额、税额”这些词再加一条“如果只是总结PDF内容不要使用本技能”的负向描述。2.3 正文怎么写给Claude看步骤、模板、自检缺一不可正文不需要有华丽的修辞它是给语言模型读的SOP越像操作手册越好。我通常按四块来组织触发条件与边界、执行步骤、输出格式、注意事项或自检清单。下面是一个简化版的SKILL.md正文可以直接参考# PDF报表提取技能 当用户提供PDF或扫描版报表并要求输出结构化数据时使用。 不要对非报表类PDF使用此技能。 ## 执行步骤 1. 运行 scripts/extract_pdf.py 输入PDF路径 输出CSV路径。 2. 读取脚本输出的CSV检查列是否齐全date, region, order_id, amount, quantity, note。 3. 对明显缺失的字段填NULL不要自行编造数值。 4. 将最终CSV路径返回给用户。 ## 输出格式 CSV列顺序固定为 date,region,order_id,amount,quantity,note 示例行 2025-06-01,华东,SO-1001,1250.00,3,大客户订单 ## 注意事项 - 金额统一为数字格式不带货币符号和千分位逗号。 - 同一订单在同一页出现多次时只保留最后一次。 - 若脚本返回非零退出码先检查依赖和文件路径再向用户说明不要假装成功。 - 完成任务前按上面的示例格式做一次自检。这里面有几个容易被忽略的设计第一步骤用“运行…读取…检查…将…返回给用户”这样的动词开头把Agent要做的事从“理解”变成“执行序列”第二给出“某列缺失时填NULL”的兜底规则避免Claude自行编造第三给了“脚本失败怎么办”的自救路径否则Agent常常会假装任务成功第四最后要求做一次自检等于加了道质量闸门。2.4 一个没说透的细节SKILL.md也是上下文的一部分SKILL.md不是魔法文件Claude在调用技能时会把说明书内容读进上下文因此说明书越精准越省上下文也越不容易被中途语义带偏。一个实在的建议是SKILL.md正文控制在几KB以内能用列表和示例说明的就不要写长篇散文。如果某个技能的知识量特别大比如包含上百条公司内部规则不要全塞进一个文件可以拆成多个子文档在SKILL.md里写索引路径让Claude按需读取。这种“说明书只放目录、细节放子文档”的做法在技能变复杂之后非常实用。3. 从0到1实操做一个能直接用的“PDF报表提取”Skill3.1 目录和说明书先把骨架搭起来实操从建立技能目录开始在个人技能目录下创建文件夹mkdir -p ~/.claude/skills/pdf-report-extractor/scripts cd ~/.claude/skills/pdf-report-extractor接着把上面的SKILL.md写进去。这一小步要注意编码SKILL.md必须用UTF-8保存如果你的Skill面向英文内容内容也可以直接用英文写但description里的中文触发词要保留因为用户聊天时通常用中文描述需求。3.2 写辅助脚本让脚本干机械活把智能留给规则辅助脚本不是必须的但一旦处理真实文件脚本能把提取准确率大幅提高。以PDF表格提取为例可以用Python加上pdfplumber这类常见库# scripts/extract_pdf.py import sys import csv import pdfplumber def extract_tables(pdf_path, out_path): rows [] with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: for table in page.extract_tables(): for row in table: rows.append([ if cell is None else str(cell).strip() for cell in row]) with open(out_path, w, encodingutf-8, newline) as f: writer csv.writer(f) writer.writerow([date, region, order_id, amount, quantity, note]) writer.writerows(rows) if __name__ __main__: if len(sys.argv) ! 3: print(用法: python extract_pdf.py 输入PDF 输出CSV, filesys.stderr) sys.exit(2) extract_tables(sys.argv[1], sys.argv[2])我把PDF解析做成一个独立命令行脚本原因很简单它不依赖Claude的运行环境自己也能在终端里调试。这非常重要因为脚本一旦被Agent调用出错的排查成本会翻倍脚本自己能跑通是底线。如果你需要识别扫描件可以再叠加OCR能力如果你处理的不是PDF而是图片、Excel、JSON道理完全一样——技能外壳不变换脚本和规则就行。3.3 测试一轮先跑脚本再开Agent写完之后先自己在终端跑一次脚本cd ~/.claude/skills/pdf-report-extractor python scripts/extract_pdf.py sample.pdf output.csv先看CSV的列和内容是否合理。这一步不是在测Claude而是在测自己写的规则和脚本锁得够不够牢。然后你可以直接在对话中说“用pdf-report-extractor处理这个PDF”看Claude有没有读取技能、按步骤执行。如果它没触发八成是description的问题下一节会专门讲这条排查链路。3.4 依赖和安全技能包要自带运行说明脚本用到第三方库时skills目录里必须带上依赖清单至少一个requirements.txtpdfplumber0.11.0并且建议在SKILL.md的注意事项里写一句“如果脚本因为缺少依赖报错先阅读requirements.txt安装依赖”相当于给Agent一个恢复步骤。每次更新脚本后顺手测试一遍旧用例我吃过亏升级了库版本旧PDF的提取格式变了技能看着正常实际输出的列却对不齐。注意Skill里的脚本会在本地以当前用户权限执行所以不要运行来源不明、未审计过的技能包团队共享技能也要先审查再运行这条底线不能省。4. Skill不生效时的排查链路从“完全没触发”到“稳定跑通”4.1 第一步先判断是“没加载”还是“没触发”遇到问题不要急着改代码先判断卡在哪一环。如果Claude压根没有读取技能说明可能是加载链路断了SKILL.md没有放在正确的技能目录层级里或者文件名拼写不对或者新技能还没被重新加载。你先检查目录结构再重启会话或手动刷新技能列表。如果是项目级技能确认当前工作区确实在这个项目下跑错目录自然找不到。4.2 description语义不匹配最常见的“叫不醒”问题排在第二位的常见原因是description和用户问法对不上。Claude扫描技能就像搜索引擎检索文档关键词匹配越接近越容易命中。用户说“把这张发票的税额和公司抬头导出来”你的description只有“Invoice Data Extraction”触发率就很低。解法不是去写更多专业名词而是站在用户口语习惯上枚举触发词发票、票面、税额、税号、抬头、报销单、金额、汇总表最后加一句排除条件“如果用户只是要求阅读并总结发票内容不要使用本技能”。这样既能提高命中率又能避免误触发。4.3 触发了但步骤跳步把说明书改成“非做不可”“技能触发了但执行结果不完整”是另一类高频坑。通常是因为SKILL.md的步骤写得太像建议Claude把它当成了概要。我处理过一份报表提取技能它输出的时候经常漏掉“异常值标注”这一步后来我直接在步骤里改成“必须标注异常值否则任务失败”并且把验收样例放进输出格式。有效的SKILL.md写法是动作动词开头、明确输出物、给兜底规则、设自检清单。你可以理解为给Agent加质检工序。4.4 脚本跑挂了先定位环境再定位代码脚本报错时先别急着让Claude重跑。把脚本单独拿出来在终端执行看原始报错信息。最常踩的三个坑一是依赖没装缺库或版本不匹配二是脚本用了相对路径而Claude调用时的工作目录不是技能目录导致找不到文件三是没有考虑命令行参数的校验Agent传参方式和你预期不一致。我的习惯是脚本入口做严一点参数数量不对就打印用法并以非零码退出这样Claude会根据返回信息自己尝试修正。4.5 一个完整案例发票提取技能一周都没被触发我用一个真实案例把排查链路串起来。最开始写的发票提取Skill放在项目目录里description写的是“提取发票关键信息”自认为没问题但用户实际说的是“帮我把这张发票报销把金额和税号整理成表格”。连续一周Claude都直接普通回答不加载技能。我排查了目录、文件名、会话刷新都没问题。最后把description改成description: 处理发票或报销单据提取金额、税额、税号、公司抬头、日期等字段并生成报销汇总表格。用户提到发票、报销单、票面、税额、税号、报销、金额汇总时使用。如果只是让总结发票内容不要使用。当天再测触发率直接翻倍。另一个同时发现的坑是脚本输出路径写死成了output.csvClaude在不同工作目录里调用文件落到奇怪位置。改成把输出路径作为第二个命令行参数后问题才彻底解决。这两个问题都不深奥但暴露了Skills调试的本质你不是在给普通程序调bug而是在调整一份语言模型会“断章取义”的说明书所以每个环节都要留足明确的、低歧义的指令。5. 技能变多以后目录管理、版本更新与团队共享的实战经验5.1 给技能库定规矩一个技能只干一件事技能一旦超过十个最危险的是描述重叠导致的误触发。两个技能都说自己能处理“发票”Claude就会根据语义细节选一个选错时结果就乱套。我的办法是给每个技能定义强边界命名统一用动词-对象格式如pdf-report-extractor、invoice-field-mapper在description里同时写清楚“什么时候用我”和“什么时候别用我”。可以把description理解成SEO标题既要命中目标关键词又要避免和邻居技能抢词。5.2 把技能当代码管版本号、变更记录和回归验证Skill是由说明书和脚本组成的它和代码一样需要版本管理。我会把技能目录放进版本管理仓库每个技能目录下维护一个examples/目录里面放输入样例和预期输出。每次改SKILL.md或脚本就跑一遍旧样例确认没破坏已有行为。这个习惯帮我避免过一次事故我更新了提取脚本的列顺序没更新SKILL.md里的模板结果生成出来的CSV跟说明书对不上Agent还认为自己成功了。另外我建议在每个SKILL.md底部维护一段“变更记录”只加一行日期、改了什么、验证结果。技能库超过二十个之后你会非常需要这个记录。5.3 团队共享技能资产化之前的审查关卡团队共享时我推荐把技能目录做成独立仓库由专人维护审核成员定期拉取到自己的技能目录。共享技能最大的风险是脚本会本地执行所以任何人拿到一个新技能包第一件不是直接调用而是打开SKILL.md和脚本看一遍它要访问哪些路径、会不会删数据、有没有奇怪的网络请求。公司内部可以约定一个评审流程只有通过审查的技能才允许进入团队技能库。这个流程前期看着繁琐但能避免很多不可控结果。5.4 往前看一步Skill和MCP的配合会成为标配最后补一个趋势判断。Skill和MCP不是竞争关系而是互补关系MCP解决“连接”Skill解决“规范”。未来的Agent工作流大概率是这样跑的收到任务后先匹配项目里的Skills找到对应的操作规则和本地脚本执行遇到需要外部数据或工具的步骤再通过MCP去连。对团队来说MCP层可能是IT和平台团队在管Skill层则是业务和技术团队一起沉淀的核心资产。早点把技能库当成“数字岗位说明书”来维护后面会省很多事。最后说点我自己的使用体会。我现在每写一个Skill都会在底部加一小节变更记录每次更新只写一行日期、改了什么、验证结果。看起来是小事但等技能超过二十个以后你会回来谢这个习惯。另一个更实在的建议是别追求一次性写出完美技能。先接受60分的版本用一周根据实际触发情况和输出质量慢慢调description、步骤和脚本。Skills的珍贵之处不在于单份文件写得多么漂亮而在于你真的知道这套“数字岗位说明书”在哪些场景靠得住、哪些场景会翻车。边界摸熟了比多写十个技能都管用。
返回列表