
有人说提示词就是AI的灵魂。我做了几年AI应用落地愈发觉得这句话只对了一半。给大模型写出一个“请你扮演数据分析师”的提示和给Agent配置一份真正能跑起来的“数据分析技能包”中间差的不是措辞而是整套流程、资源、脚本和边界条件的组织方式。Skills这个词最近在各家Agent平台里反复出现它的目标很直接把散落的提示词、工具配置、执行步骤封装成可复用、可共享、可升级的技能模块让大模型从“会聊天”变成“会干活”。这篇文章我会从技能包的结构讲起手把手带你搭一个能用的Skill再把过程中踩过的坑一并列出来。1. Skills到底是什么从提示词到可复用技能包1.1 AI技能不是插件也不是普通提示词很多人第一次接触Skills这个概念会把它类比成浏览器的插件或者微信小程序。这个类比有一定道理但并不准确。浏览器插件是在渲染引擎之外扩展功能而AI技能是直接嵌入模型使用流程的“语言脚本”混合体。它的核心不是一段代码而是一套说明书告诉模型在什么条件下激活什么能力、按什么顺序执行、输出什么格式同时附带完成该工作所需要的模板、脚本和参考数据。普通提示词解决的是“单次交互的引导”问题。你把需求描述清楚模型根据自己的预训练知识来回答。问题在于这种能力是临时的、不稳定的。下一次换个环境重新部署提示词可能要重新调任务稍微复杂一点比如要从数据库导出数据、按Excel模板生成报告、再把结果推送到某个内部系统单靠提示词就撑不住了。这时候就需要一个带有“手脚”的技能包它包含可执行的脚本也包含模型可以按步骤调用的指令集。它更像一个岗位的“工作手册工具箱”而不是一句简单的口头交代。如果你做过一段时间的Agent开发应该会有一个很深的感受模型在对话里表现得像一个聪明但没有经验的实习生你告诉它目标它能给你思路但真让它去执行多步操作它常常会漏步骤、跳逻辑、甚至自己编一个不存在的命令。Skills机制的出现本质上是把这个“实习生”变成“熟练工”。1.2 Skills的核心价值让Agent从“会聊天”变成“会干活”我见过不少团队做AI客服、AI文档助手前期demo演示非常惊艳一到生产环境就哑火。原因往往只有一个模型不知道该从哪里开始也不知道用什么工具更不知道做完之后要对结果做什么校验。Skills的设计目标就是解决这三个“不知道”。第一它把隐性流程显性化。一份SKILL.md里会写明这个技能的目标、触发条件、执行步骤、输入输出规范和校验方式。模型在运行时读取这份说明书相当于一个新员工入职第一天拿到SOP照着做就行。第二它把高频操作模块化。比如“生成周报”这个动作会涉及读取散落的项目文件、汇总任务、计算工时、套用模板、输出指定格式。把这一整套封装成一个Skill之后以后只需要说“帮所有项目成员生成上周的周报”Agent就能自动找到对应技能并执行不再需要每次把步骤重复一遍。第三它把个人经验沉淀化。你费了很大力气调好的分析流程、精心设计的输出模板、踩坑之后补充的校验规则都可以写进技能包里。这意味着经验不再停留在某个人的脑子里而是变成可以被团队共享、被AI自动继承的资产。这三条价值里最后一条常常被忽略但在我看来它最值钱。单人使用Agent时能力上限取决于你写提示词的水平团队共享技能库时能力上限取决于团队里最懂业务的那个人能不能把经验结构化成技能文件。技能包本质上是一种知识管理的载体只不过它的读者不仅有同事还有AI。1.3 适用场景与受众所以到底谁需要认真研究Skills我总结下来有三类人。第一类AI应用开发者和产品经理。你正在做Agent类产品需要让AI稳定地执行多步任务而不是每次都靠临场发挥。Skill机制可以帮你把业务规则和技术实现解耦产品经理写说明书工程师提供脚本各司其职。第二类重度AI工具使用者。你可能不是程序员但每天都在用ChatGPT、Claude这类工具处理文本、数据、邮件。这时候一套写好的技能包能极大减少重复劳动你只需要学会“装技能”和“调用技能”就能享受到自动化红利。第三类企业内部效能岗位。人事、行政、运营、财务这些部门往往有大量固定格式、固定流程的重复工作。把它们一个个做成技能包等于给团队配了几个不吃不喝不抱怨的数字化助理。2. 技能包的内部结构与设计思路2.1 一个标准的Skill目录长什么样虽然不同平台上Skill的封装格式略有差异但主流方案已经收敛到一个比较接近的结构。我这里用一个我实际在用的目录示例来说明weekly-report-skill/ ├── SKILL.md ├── assets/ │ ├── weekly_report_template.md │ └── output_example.md ├── scripts/ │ ├── collect_data.py │ └── render_report.py └── requirements.txtSKILL.md是技能包的核心入口一般放在根目录。它通常包含一段YAML格式的frontmatter记录技能的名称、描述、适用场景以及模型在什么情况下应该调用它。frontmatter下面则是正文用Markdown写清楚执行步骤和注意事项。assets目录存放文档类资源比如模板、参考示例、规则说明scripts目录存放可执行脚本Python也好Shell也好Node.js也好只要是运行时能解释执行的都行requirements.txt则是Python依赖列表如果是Node.js技能也可以放package.json。这个结构并不复杂但它在设计上的讲究值得专门说。2.2 SKILL.md人机共读的说明书很多人把SKILL.md当成给大模型看的说明书这个理解没错但不够完整。它实际上是一份人机共读的文档。人要看因为技能包需要维护、review、交接模型也要看因为它需要在有限的窗口里快速理解技能目标并开始行动。那么SKILL.md应该怎么写模型才容易懂我总结了几条实操原则。名称必须唯一且具描述性。不要让“报告生成”这样模糊的词出现在技能列表里要有区分度比如“周报聚合生成器”。模型在任务识别时主要依赖description字段description里要写清楚“何时使用、何时不用”甚至最好直接给出触发示例。执行步骤要编号并且逐步细化。模型在执行复杂任务时容易跳步如果你在文档里写“整理数据并生成报告”它可能真的会把两个动作揉在一起。你要写“第1步运行scripts/collect_data.py检查输出文件与项目路径是否一致第2步若数据缺失从XXX补充第3步运行render_report.py生成报告并逐条核对模板中必填项”。步骤越像飞行检查单模型执行得越稳定。明确输入输出格式。比如输出文件统一用UTF-8编码、日期用YYYY-MM-DD格式、金额保留两位小数。模型对这些约束的遵守程度完全取决于你有没有写清楚。不要指望模型自己去推断它推断出来的格式大概率不是你想要的。2.3 资源文件、脚本与依赖的组织逻辑SKILL.md解决的是“模型知不知道怎么做”的问题脚本解决的是“模型有没有手做”的问题。资源文件和脚本的组织逻辑本质上是对不确定边界的切割。凡是纯文本、模板、规则表这类内容直接放进assets目录让模型自己读取、内化、套用。凡是需要计算、网络请求、文件格式转换、数据库读写这类逻辑尽量封装成脚本让模型通过调用脚本完成。为什么要这样切因为模型最擅长的是语言理解和生成最不擅长的是精确计算和稳定操作。比如“统计每个人本周工时总和”你用提示词让模型自己算模型可能算错但你让模型运行一段Python脚本去算结果就是确定性的。依赖管理同样不能忽视。requirements.txt里写清楚版本甚至可以锁定具体版本号。技能包跑不起来90%的原因是依赖环境和预期不符。你本地Python3.9能用生产环境是Python3.11可能一个函数废弃了整个技能就挂了。脚本尽量用标准库实在不行就把依赖写死到锁文件。2.4 为什么这样设计状态与上下文的取舍有人可能会问既然模型那么强为什么不把所有内容都写在提示词里省得搞目录结构答案是上下文窗口的性价比问题。一个技能包如果包含了多份文档、多个脚本、大量示例全量塞进提示词可能会让模型立刻被海量信息淹没。更重要的是模型在任何时刻并不需要全部信息它只需要知道入口在哪、什么阶段读什么文件。SKILL.md相当于一个索引文件让模型先掌握技能地图等执行到某个环节再调用具体资源。这种按需加载的思路既节省了上下文token也避免了信息过载导致的幻觉。另一个设计考量是状态管理。Agent执行一步操作之后中间结果放在哪怎么传递给下一步最简单的方法是把中间结果落盘成临时文件然后在SKILL.md里约定好文件名和存放路径。脚本读取上一步的输出处理完写入下一步的输入。这个流程虽然朴素但在没有复杂状态机的情况下是最好调试、最好追溯的方案。3. 从零搭建一个可复用的技能包周报自动生成实战3.1 目标拆解与流程设计光讲概念不讲实操不是我的风格。接下来我们动手做一个真正能用的技能包场景选“周报自动生成”。这个场景特别典型因为它同时涉及数据收集、模板套用、格式生成和结果校验四类动作几乎能把Skill机制的每个关键点都覆盖到。目标需求用户对Agent说一句“帮我把本周的项目周报生成出来”Agent应该自动完成以下四个步骤扫描指定目录下的所有项目记录文件读取本周的数据。汇总各个项目的进度、风险和明日计划。用统一的周报模板将汇总结果渲染成Markdown文件。校验输出文件是否包含所有必填项并给出校验结果。为了让流程可控我们约定所有项目记录文件都是JSON格式放在input/目录下字段包括project、owner、status、progress、risk、next_plan、date。周报模板放在assets/weekly_report_template.md中用占位符接受动态数据。真实业务里input目录中的JSON可能是从项目管理工具导出的也可能是团队里某个脚本自动同步的。技能包不关心数据从哪来只关心格式对不对。所以你可以在SKILL.md里明确写一句“input目录由外部系统维护Agent不要修改其中的原始文件”避免模型自作主张清洗数据。3.2 创建目录与核心文件开始动手之前先在终端创建目录结构mkdir -p weekly-report-skill/{assets,scripts,input,output} cd weekly-report-skill touch SKILL.md我建议在你的项目工作区中直接维护这个目录方便后续用Git进行版本管理。input目录放模拟数据output目录放生成的报告assets和scripts分别是模板和脚本。目录建好之后先在input目录下放一份模拟数据文件命名为2025-W22.json内容类似[ { project: 数据平台迁移, owner: 张三, status: 进行中, progress: 已完成60%, risk: 依赖的基础服务接口延迟, next_plan: 本周完成数据校验脚本开发, date: 2025-05-27 }, { project: 用户增长分析, owner: 李四, status: 已完成, progress: 全部完成, risk: 无, next_plan: 下周开始复盘报告, date: 2025-05-30 } ]这份数据足够用来测试技能包的核心流程。实际使用时你只需要让数据生产方按照约定格式输出到这个目录即可。3.3 编写SKILL.md与执行脚本SKILL.md是技能包的大脑。我建议先把frontmatter写清楚--- name: weekly-report-generator description: 根据input目录中的项目记录JSON文件自动汇总并生成周报Markdown。适用于每周五或周一生成周期性周报的场景。当用户要求生成周报、汇总项目进度时使用。 ---description写“何时使用”很关键。模型选择技能时主要靠它写得太泛就会导致该用的时候不用不该用的时候乱用。接下来写正文# 周报生成技能 ## 执行步骤 1. 检查input目录下是否存在本周日期前缀的JSON文件如2025-W22.json。若不存在列出已找到的文件并请用户确认。 2. 运行 python3 scripts/collect_data.py --input input/2025-W22.json --output output/summary.json该脚本负责校验JSON格式并生成汇总数据。 3. 读取 output/summary.json如果status字段为“error”则根据错误信息提示用户修正数据。 4. 运行 python3 scripts/render_report.py --summary output/summary.json --template assets/weekly_report_template.md --output output/weekly_report_2025-W22.md生成周报。 5. 检查生成的Markdown是否包含各项目的“项目名、负责人、状态、进度、风险、后续计划”。如有缺失通过脚本自动标记并提示。 6. 将最终报告路径告知用户。 ## 注意事项 - 所有日期统一使用YYYY-MM-DD格式。 - 不要修改input目录下的原始文件。 - 生成的Markdown中不要包含调试信息。注意第2步和第4步的命令都是明确的。这一步设计非常重要。模型对具体命令的执行能力远强于对宽泛指令的解释能力。你让它“用脚本处理数据”它可能会自由发挥你让它“运行某一段命令”它会老实照做。接下来写两个脚本。collect_data.py做的事情很简单读JSON、检查必填字段、按项目汇总输出一个新的汇总JSON。import argparse import json from datetime import datetime REQUIRED_FIELDS [project, owner, status, progress, risk, next_plan] def main(): parser argparse.ArgumentParser() parser.add_argument(--input, requiredTrue) parser.add_argument(--output, requiredTrue) args parser.parse_args() try: with open(args.input, r, encodingutf-8) as f: records json.load(f) except Exception as e: write_error(args.output, f读取输入文件失败: {e}) return if not isinstance(records, list): write_error(args.output, 输入文件必须为JSON数组) return for idx, record in enumerate(records): missing [field for field in REQUIRED_FIELDS if field not in record] if missing: write_error(args.output, f第{idx}条记录缺少字段: {, .join(missing)}) return summary { generated_at: datetime.now().strftime(%Y-%m-%d %H:%M:%S), project_count: len(records), projects: records, status: ok } with open(args.output, w, encodingutf-8) as f: json.dump(summary, f, ensure_asciiFalse, indent2) print(f汇总完成共{len(records)}个项目) def write_error(output, message): with open(output, w, encodingutf-8) as f: json.dump({status: error, message: message}, f, ensure_asciiFalse, indent2) if __name__ __main__: main()接着是render_report.py。它读取summary.json用模板生成Markdown。import argparse import json from pathlib import Path def main(): parser argparse.ArgumentParser() parser.add_argument(--summary, requiredTrue) parser.add_argument(--template, requiredTrue) parser.add_argument(--output, requiredTrue) args parser.parse_args() with open(args.summary, r, encodingutf-8) as f: summary json.load(f) if summary.get(status) error: print(上游数据错误终止渲染) return template Path(args.template).read_text(encodingutf-8) sections [] for project in summary[projects]: section template.replace({{project}}, project[project]) section section.replace({{owner}}, project[owner]) section section.replace({{status}}, project[status]) section section.replace({{progress}}, project[progress]) section section.replace({{risk}}, project[risk]) section section.replace({{next_plan}}, project[next_plan]) sections.append(section) content # 周报 summary[generated_at] \n\n content 共汇总 {} 个项目\n\n.format(summary[project_count]) content \n---\n.join(sections) Path(args.output).parent.mkdir(parentsTrue, exist_okTrue) Path(args.output).write_text(content, encodingutf-8) print(f报告已生成: {args.output})模板文件assets/weekly_report_template.md内容可以简单设计## 项目{{project}} - 负责人{{owner}} - 状态{{status}} - 进度{{progress}} - 风险{{risk}} - 后续计划{{next_plan}}用字符串替换而不是让模型直接生成报告是为了保证格式100%可控。模型看完数据自己写的Markdown很可能漏项或跑偏用脚本渲染就是确定性产物。这一步就是把“模型擅长理解”和“脚本擅长执行”结合起来的关键。3.4 挂载技能并测试目录、文件都准备好了接下来把技能装进Agent平台。不同平台的操作路径不一样以我常用的方式为例在Agent的配置界面里找到“Skills”入口选择“添加本地技能”把weekly-report-skill这个目录传上去即可。平台会读取SKILL.md中的name和description把技能注册到模型可识别的技能列表里。挂载完之后做一次端到端测试。我习惯用一句非常口语化的指令来触发“本周的项目周报帮我整理一下。”正常情况下模型应该主动选择weekly-report-generator技能然后依次执行读取、汇总、渲染、校验四步。如果模型没走技能直接徒手写了一份周报那就是description写得不够明确需要回炉修改。测试时建议分两层第一层只跑脚本验证脚本本身逻辑没问题第二层跑完整Agent链路验证模型能否正确调用技能。脚本有错先修脚本不要在模型层面硬调。我曾经见过有人花了两天调提示词最后发现只是Python脚本里一个变量名写错了这种亏吃一次就够了。3.5 迭代与版本管理技能包不是写完就完事的它需要像代码一样持续迭代。我会用Git对技能包目录做版本管理每次修改SKILL.md或脚本都记录原因。这里有一个很实用的版本技巧在SKILL.md的frontmatter里加一个version字段比如version: 1.2.0并在“变更记录”小节里写明这次改了什么。这样模型在执行过程中如果发现行为异常你可以快速知道当前跑的是哪个版本的逻辑。版本管理的另一个作用是方便A/B测试。我想调整周报模板就复制出一个weekly-report-generator-v2目录改好后实测几周确认效果更佳再替换原技能。这种低成本试错方式在技能迭代里特别好用。4. 进阶实战让技能包更聪明、更健壮4.1 技能组合一个Skill调用另一个Skill单一技能包的能力是有限的。真正复杂的任务往往需要多个技能配合。比如我之前做的“客户成功周报”流程就是三个技能串起来的数据解析技能解析CRM导出文件、指标计算技能计算健康分、报告生成技能渲染周报。技能之间怎么协作最常见的两种方式第一种是管道式技能A产出中间文件技能B读取该文件继续处理流程写在SKILL.md里让模型按序执行。第二种是嵌套式在SKILL.md的步骤里直接写明“调用data-analyzer技能获取指标”模型在运行时如果发现该技能存在会自动切换。嵌套式更适合父子任务关系明确的场景管道式更适合数据流清晰的场景。组合技能时最容易踩的坑是技能边界模糊。如果两个技能的description都写了“处理项目数据”模型就会纠结到底选哪个。我的建议是每个技能只做一件具体的事description里写清楚“本技能不做XX”反而比写“本技能做XX”更有用。比如数据解析技能可以写明“仅负责数据解析不生成报告”这样模型在做报告时就不会误选它。4.2 参数设计与动态内容注入第一次写Skill时容易把输入数据硬编码成固定的文件名。这在demo里没问题但真实场景中数据文件每天都在变。所以参数设计必须一开始就做对。我推荐的方案是在SKILL.md中约定好动态内容的存放位置执行时通过命令行参数或环境变量注入。比如周报技能里脚本通过--input参数读取用户指定或自动发现的JSON文件而不是写死input/2025-W22.json。模型在调用脚本前会先列出目录内容找到日期最新的文件再把它作为参数传进去。这样技能就有了通用性。动态内容注入还有一个层面是用户意图的传递。有时候用户会提醒“本周只看数据平台项目的进度”这时模型不能机械地汇总所有项目它应该有能力在SKILL.md的框架下做局部调整。我的做法是在SKILL.md里加一条“用户额外指令优先级高于本技能默认范围”的约定并让脚本支持--filter参数过滤项目名。这相当于给技能留了一个可变参数口既保持了流程的可控性也保留了灵活性。4.3 错误处理与边界情况技能包在生产环境中的差异往往体现在边界情况处理上。比如输入JSON为空数组怎么办某条记录缺少risk字段怎么办生成目录没有写权限怎么办这些都要在开发阶段想清楚。我的经验是脚本返回的错误信息要足够明确最好直接给出修复建议。比如collect_data.py遇到缺字段不只说“字段缺失”而是说明是第几条记录、缺哪个字段、可能的原因是什么。这样模型读取错误信息后可以自行尝试修复或向用户解释。模型不是万能的你给它的错误信息越结构化它的下一步决策就越靠谱。对于非确定性操作比如网络请求、外部命令调用我建议增加失败重试机制。脚本里可以直接写一个简单的retry装饰器失败两次间隔3秒再试一次。这个细节在演示环境看不出差别在生产环境中能省下大量排查时间。4.4 与MCP/API工具协同的取舍做Agent开发的人都会接触MCP这类工具协议。很多人的第一个问题是有了MCP还需要Skills吗我的结论是两者不是替代关系而是分工关系。MCP侧重于给Agent提供一个标准化的外接能力接口比如数据库连接器、浏览器、文件系统它解决“Agent能拿到什么数据、能操作什么系统”的问题。Skills侧重于封装“完成某类任务的完整方法论”它解决“Agent拿到数据之后怎么处理、按什么流程输出”的问题。你可以把一个Skill理解成一个专家把MCP理解成专家手里的工具箱。专家要写周报需要读取数据库这时他打开MCP这个工具箱去取数据库连接器但他怎么组织报告结构、怎么校验数据完整性依赖的是他自己的专业知识也就是SKILL.md里的内容。所以建议做技能包时不必把所有工具调用都写死在脚本里可以约定“读取项目数据时使用MCP database工具”让模型自己决定工具选择。脚本只处理纯计算和渲染工具调用交给Agent运行时去协调。这种边界划分最清晰也最不容易出问题。5. 常见问题与避坑指南5.1 技能不生效、误触发、上下文爆炸怎么办先说技能不生效。最常见的原因是置的文件名大小写不一致。平台在读取SKILL.md时通常要求名字完全匹配你把文件写成skill.md它可能就识别不到。我第一次做技能包时就栽在这个上面。其次是误触发。技能在无关场景下被模型调用多半是description写得太宽泛。我建议在description里加入“不适用”的提示例如“仅当用户明确要求生成周报时使用。其他总结类任务不要使用。”注意这里的指令语气要足够重模型对否定指令的遵守程度有时比肯定指令还高。上下文爆炸则是个更隐蔽的问题。技能包如果自带大量示例文本和长说明书模型每次调用都会先读取全部内容token消耗会非常夸张。解决办法是把大文档拆成多个小文件在SKILL.md中只写索引和读取时机让模型按需读取。比如模板文件不要直接贴在SKILL.md正文里而是放在assets目录在第3步让模型读取。这能显著降低单次调用的上下文开销。5.2 依赖冲突与多技能共存当技能包多起来之后依赖冲突就不可避免。我维护过十几个技能发现一个技能要装requests库另一个技能指定安装requests的旧版本最终导致集体跑不起来。这种问题在开发领域叫“依赖地狱”在技能包里同样存在。我的规避策略有三条第一技能尽量使用Python标准库减少外部依赖。上面例子里的两个脚本只用argparse、json、pathlib零第三方依赖这样基本不会冲突。第二如果一定要用第三方库锁定版本并在技能目录里附带requirements.txt部署时先为每个技能创建独立虚拟环境再通过子进程调用。第三保持技能目录隔离不要在多个技能中共用同一个临时文件命名避免相互覆盖。5.3 技能包的安全边界给Agent赋予执行脚本的能力就需要考虑安全问题。这里的原则是最小权限脚本只做它被设计做的事不碰系统关键路径不读写与任务无关的文件。举个反面例子有人的周报脚本为了图方便用os.system把所有input目录里的文件都删了。后来一次误操作把output目录当成input目录传参结果整个输出目录被清空。这种事故一旦发生就很麻烦。我现在的做法是脚本一开始先对路径做白名单校验确保读写路径都在技能包目录范围内然后才执行后续逻辑。另外凡是涉及删除、覆盖和网络请求的操作我都会在SKILL.md里明确要求模型先向用户确认。5.4 从个人效率到团队协作技能库管理个人使用技能包时怎么顺手怎么来。但一旦要在团队里共享就得引入管理和评审机制。我的建议是建立一个技能库仓库每个技能包作为一个子目录维护一个README索引表写明技能名称、负责人、版本、适用场景和最近更新时间。团队协作中经常出现的问题是重复造轮子。同一个人可能在一个月内被“数据清洗技能”和“数据标准化技能”命名折磨。我的做法是强制命名规范技能名用功能英文短横线命名描述用中文写清业务场景。比如data-normalizer-skill就比“处理数据的技能”清晰得多。技能复用率高的时候可以在斜杠命令或标签里建立别名方便模型优先选用成熟技能。5.5 能力评估与持续优化最后一个建议是给技能包建立持续反馈机制。我每跑一次技能都会顺手记录三件事是否一次成功、模型在哪一步用了最多时间、输出有没有被人工修改。用一两周时间就会积累出一份“技能体检报告”。根据这份报告你会发现问题高度集中在某几个环节比如“数据字段与模板不匹配”“风险为空时模板出现空列表”。针对这些问题去优化脚本或模板效率远高于漫无目的地重写提示词。技能不是一次定义终身使用的静态资产它是需要持续维护的动态能力。对我而言写技能包的过程本身也像在给自己做一份“AI时代的岗位说明书”——把一个模糊的需求拆解成可以稳定执行的流程再交给Agent去落地。我在实际项目中最大的体会是不要把技能想得太玄它本质上就是“一份好的操作手册几个趁手的工具”。真正决定一个技能包好不好用的不是脚本写得多高级而是你有没有把边界条件、触发条件、异常处理这些脏活累活都想到前面。先把一个小场景做到闭环再慢慢扩充技能版图这条路是最稳的。