资讯动态

Skill不是提示词:用skill-creator实现AI Agent技能的工程化管理

发布时间:2026/10/22 19:22:17 来源:尧图企业网站定制
1. 手写Skill定义的真实痛点为什么需要一个专门的创作工具很多人第一次接触Skill这个概念的时候都会觉得“这不就是给AI写一段更详细的提示词吗”。等我真正在Agent框架里维护过十几个Skill之后才发现这个想法错得离谱。一个Skill要稳定地被Agent理解、被正确调用、每次都产出符合预期的结果背后需要的是严格的结构、清晰的输入输出契约、可回归的测试集——这些靠手写是根本不可能长期维护的。1.1 Skill不是提示词而是一个需要工程化的对象在Agent的日常运行里用户的请求到达后第一件事不是执行而是路由判断这个请求该交给哪个能力去处理有些能力是写死在代码里的工具函数有些则是“由大模型去执行的指令模板上下文规范输出格式约束”。后者就是Skill。举个例子同样是“帮我总结一下这篇文档”的需求不同的人写出来的Skill可能千差万别。有人只写一句“总结文档并输出要点”有人写了两千字的分步指令还有人连输入字段、输出字段、失败兜底逻辑都考虑到了。这些写法在单独跑一次的时候可能都能出结果但一旦要维护、要变更、要多人协作问题就来了——没有人说得清哪一个版本是“正确的”也没有人敢保证改动一行描述之后Agent的行为不会漂移。这就像代码没有类型系统、没有单元测试、没有版本管理全靠程序员自觉。短期看能跑长期看必然失控。1.2 手工维护时刻面临的三个典型场景我自己在踩坑过程中总结出手工管理Skill必然会撞上的三堵墙第一堵墙是格式不统一。团队里有人用Markdown写有人用JSON有人直接把指令塞进System Prompt。想写一个自动化脚本去扫描所有Skill、检查必填字段是否存在根本做不了因为连“字段”这个概念本身都没有统一。第二堵墙是行为不透明。有一次我在某个Skill的description里把“总结”改成“提炼重点”结果Agent在其他无关场景里也开始触发它。没有任何日志能告诉我为什么我只能肉眼去对比两个版本的文本差异然后靠猜。第三堵墙是回归无门。改一个Skill之前我想验证这个改动会不会影响曾经能跑通的场景但过去的输入输出我没有留存。于是每次改动都像是一场赌博运气好没问题运气不好线上表现就崩了。1.3 工具化之后Skill从“一次性文案”变成“可管理资产”后来我开始使用skill-creator来创建和优化Skills核心思路其实特别朴素把Skill当作一个标准化的工程对象来处理而不是一段随手的写作。skill-creator做的事情可以拆成四块交互式生成Skill骨架让创建过程有规范可循用YAML Schema约束元数据和输入输出字段让每个Skill都长成统一的形态内置测试运行器支持批量回归和指标对比把版本快照纳入管理任意一次改动都可以追溯到来源。下面是手工方式与使用skill-creator管理Skill的对比对比维度手工维护skill-creator管理Skill格式因人而异混用Markdown/JSON/纯文本统一为SKILL.md schema.yaml examples目录行为验证靠肉眼观察无法量化内置测试集回归一次出指标报告版本追溯靠文件名后缀v1/v2/final内置history快照版本号与状态管理团队协作互相等待、口头对齐validate test 作为门禁可接入CI迁移复用每个项目重写一遍沉淀为模板二次创建时直接继承看到这张表你可能已经意识到工具本身没有魔法它只是把软件工程里已经被验证过的那套方法论平移到了Skill开发这件事上。接下来我详细说说实际创建和优化一个Skill时整个工作流该怎么走。2. skill-creator的核心工作流从需求描述到Skill骨架落地我第一次用skill-creator创建Skill的时候最不适应的点是它居然不让我直接写文件而是要我先回答一串交互式问题。后来我才理解这一步是在逼我先想清楚边界而不是打开编辑器就开始堆字。2.1 先回答一组问题而不是先写内容在终端里运行初始化命令后skill-creator会进入问答模式skill-creator init document_summarizer它会依次问你这些内容技能名称和一句话描述这个Skill应该在什么场景下被Agent调用明确哪些场景绝对不应该被触发输入参数有哪些哪些必填哪些可选输出应该长成什么样用Markdown还是JSON有没有参考的输入输出示例这个过程看起来琐碎但每一问都有它的目的。比如“绝对不应该被触发的场景”手工写的时候几乎没人会主动思考这一点可一旦遗漏Agent就会把不该接的活全丢给这个Skill。交互式问答的价值在于它把“设计反思”前置了你还没写正文就已经被迫把边界梳理了一遍。2.2 生成的目录结构每个文件都有明确职责初始化完成后skill-creator会在当前目录下生成这样一个结构skills/ document_summarizer/ SKILL.md # Skill主文件执行流程、输出规范、注意事项 schema.yaml # 输入输出契约字段、类型、约束 examples/ basic.md # 基础场景示例输入期望输出 contract.md # 进阶场景示例长合同摘要 tests/ cases.jsonl # 测试用例集真实输入断言条件 metrics.yaml # 质量基线回归测试的阈值配置 history/ v1_20250101.yaml # 版本快照 v2_20250118.yaml # 版本快照我要说的是这个结构不是随便拍脑袋定的。SKILL.md描述行为schema.yaml定义契约examples给模型参考tests管回归history管追溯——每一层都在回答一个具体问题这个Skill要做什么、怎么做、怎么验证、怎么演进。2.3 SKILL.md主文件的正确打开方式SKILL.md是核心它包含两部分front matter元数据和正文行为描述。一份典型的骨架长这样--- name: document_summarizer description: 当用户提供一篇较长的文档并要求生成摘要时使用支持合同、论文、会议记录等类型 version: 1.0.0 trigger: intents: - 总结 - 摘要 - 概括 contexts: - 输入文本长度超过800字 when_not_to_use: - 用户只是询问某段话的含义不要求提炼全文重点 - 用户要求翻译或改写而不是摘要 --- ## 执行流程 1. 检查用户是否已提供完整文本如果只有标题或链接先要求补全。 2. 判断文档类型选择对应的摘要模板。 3. 按模板生成结构化摘要包含核心结论、关键要点、遗留问题。很多人写描述时只写“总结文档”这句话实在太弱了。Agent做路由判断的时候靠的就是description和trigger里这些关键词和条件。你写得越具体它命中越准。我在第3节会展开讲怎么把元数据和Schema设计好这里先记住一个原则让Skill自己说清楚“什么时候该用什么时候不该用”这是整个文件里最值钱的部分。2.4 创建完成的Skill先过两关validate和smoke骨架生成、内容填完之后不要急着部署。先跑两条命令skill-creator validate --skill document_summarizer skill-creator smoke --skill document_summarizer --input samples/basic_input.txtvalidate会检查YAML格式、必填字段、枚举值合法性这类结构性问题smoke会用一个最小样例把整个Skill从头到尾跑一遍确认Agent能理解、能触发、能输出。这两步看似简单但能拦住大部分低级错误。我第一次创建Skill的时候跳过了smoke直接把定义接进Agent结果调试了半天才发现是front matter里少了一个引号导致整段元数据没被解析。从那以后validate和smoke成了我每次改动之后的肌肉记忆。3. 元数据与输入SchemaSkill能不能被正确调用的边界问题一个Skill写得再精彩如果Agent根本不触发它或者在错误的场景触发它那它的价值就是零。而决定这一切的恰恰是最容易被忽略的元数据字段和输入输出定义。3.1 description其实是Agent的“路由判断依据”先讲一个底层机制Agent拿到用户请求后会遍历当前可用的Skill列表逐个比对这些Skill的描述来判断“当前这个需求跟哪个Skill最匹配”。这就意味着description不是在写给人类用户看的而是在写给Agent的意图路由系统看的。我见过大量反面案例是这么写的description: 用于总结文档这个描述覆盖了所有文档、所有目的、所有语气。Agent一旦遇到“这封邮件是骂我的吗”这种请求也可能先触发它跑一遍摘要然后再回来回答——白白的浪费而且很容易产出文不对题的结果。更好的写法是这样的description: 当用户提供一篇完整的合同、论文或会议记录并要求提炼核心内容时使用。输入应为原文全文输出为结构化摘要包含结论、关键要点和遗留问题。不适用于对话型追问、翻译或逐段解释。这个描述里包含了三个信息场景完整长文档、输入条件原文全文、输出形态结构化摘要还附带了否定条件。这样Agent的路由命中率会明显提升误触发率则会显著下降。3.2 输入Schema严格类型比自由文本可靠如果说元数据决定“什么时候调用”那么schema.yaml决定的就是“调用时怎么传参”。我见过太多Skill不定义输入字段全靠模型在System Prompt里自由发挥结果就是同一句话不同轮次传进来的参数格式完全不一样。我的一份典型schema设计长这样input_fields: - name: content type: string required: true max_chars: 120000 description: 文档全文用户可直接粘贴或由上层从URL提取文本后传入 - name: doc_type type: enum values: [auto, contract, paper, meeting_notes, other] default: auto description: auto表示让模型自动识别文档类型 - name: focus_points type: array[string] required: false max_items: 5 description: 调用方希望重点关注的方面例如“价格条款”“实验结论” - name: target_length type: enum values: [short, medium, long] default: medium description: 摘要的目标篇幅 output: type: object required_fields: - summary - key_points optional_fields: - uncertainty - stats这里有三个设计细节值得展开讲。其一能设默认值的字段都设默认值。比如target_length的默认值是medium即使用户没有指定Agent也不会因为缺参数而反复追问。真实用户使用Skill时往往不会一次性把所有参数说全默认值就是你的容错空间。其二枚举值要尽可能少。doc_type这里给了五六个选项已经算多了。枚举越少模型选择的确定性越高你后续做回归测试也越容易写断言。如果你发现某个枚举值在真实调用中从来没有被触发过删掉它不要让它留在那里干扰模型。其三required字段要克制。content必须必填因为它没有默认值就无法执行但focus_points这类辅助参数完全没必要必填。我刚开始设计时习惯把所有字段都设成required结果用户只是想做一次快速摘要Agent却在反复索要focus_points体验非常糟糕。3.3 输出契约和few-shot示例让模型“照格式回答”schema.yaml里写了output的结构但大模型对结构遵循的真实程度主要取决于examples目录里给了什么样的参考。换句话说语言模型对输出格式的追随能力是靠示例喂出来的而不是靠你写一句“必须严格遵守”压出来的。我维护Skill时的习惯是至少给两个示例一个基础场景一个复杂场景。复杂度差别要拉开不要两个示例长得差不多。比如document_summarizer这个Skill我会放一个普通邮件摘要的示例再放一个长达两页的合同摘要示例。后者的输出必须完整展示多级目录、关键条款提取和风险提示让模型看到在复杂输入下该怎么组织内容。3.4 失败处理与不确定性Skill的兜底条款最后也是最容易被忽略的一块当这个Skill的输入不完整、文档类型无法识别、或者结论不确定时它应该怎么做。我在SKILL.md里会固定写一段“不确定时的行为”## 不确定时 1. 如果无法确定文档类型不要猜测输出doc_type为other。 2. 如果核心结论存在疑义请在uncertainty字段中说明疑义点。 3. 如果输入文本明显不属于要求类型直接返回“该内容不在当前Skill的支持范围内”。这段看起来像是在给模型“兜底”实际作用更大。它阻止了模型在信息不足时“不懂装懂”这是大模型输出里最令人头疼的问题之一。有了这段约束之后这个Skill产出的内容至少是诚实的——知道就是知道不知道就坦白说这反而更容易赢得使用者的信任。4. 测试集与回归评估把“优化”从感觉变成指标我在前文提到过手写Skill最大的问题不是写不出来而是改不动。要解决“改不动”唯一的办法就是建立一套可回归的测试集让每次改动都有数据说话。4.1 没有测试集的Skill根本不具备优化资格一个很残酷的现实是你觉得自己“优化”了某个Skill的描述可能只是你自己感觉变好了实际上线的行为完全没有变化甚至更差了。为什么因为你没有一套固定的输入在改动前后各跑一遍做对比。“不能测试的Skill就不能优化”这句话我重复过很多次。skill-creator里的tests/cases.jsonl就是用来解决这个问题的。每一个case是一条JSON记录包含输入、期望结果和断言条件{input: {content: 一段约2000字的商业合同文本, target_length: short}, expected: {required_fields: [summary, key_points], max_length: 400, min_length: 120, semantic_keywords: [付款条件, 违约责任]}}注意expected字段里的断言设计。required_fields和max_length属于强断言机器可以直接判断对错semantic_keywords属于弱断言它判断输出内容里是否覆盖了某些核心概念。强断言保证“格式对”弱断言保证“内容在”两者缺一不可。只做强断言的话Skill可能输出一个结构完美但完全没有抓住重点的空壳只做弱断言的话又无法保证输出稳定性。搭配使用才完整。4.2 测试集的覆盖思维不只是跑通还要跑边界给Skill写测试用例时我建议至少覆盖下面这几类场景场景类型说明示例正常场景最常见的输入形态一篇1500字的普通说明文极长输入逼近或超过长度上限一份10页的合同扫描件文本最小输入刚好达到触发门槛一篇不到300字的短备忘缺参情况缺少可选参数时能否走默认值只给content不给target_length越界拒答超出Skill能力范围时能否正确拒绝用户要求翻译不是总结边界用例的价值在于它能把“模型自由发挥”的空间压缩到最小。比如极长输入这种场景如果不提前压测你永远不会知道你的Skill在2万字之上会开始丢关键要点。而缺参情况如果测试用例覆盖到了你就能及时发现Agent在少参数时的行为是否稳健。4.3 跑一次回归看哪些指标测试集准备好之后回归就是一条命令的事skill-creator test --skill document_summarizer跑完会生成一份报告大致内容如下指标数值说明用例总数20覆盖正常、边界、拒答等场景调用成功率19/20有1个case未触发或超时输出格式合法率18/20有2个case没有按schema输出语义匹配分0.82弱断言平均通过率平均耗时3.4s单次完整执行的耗时拿到这份报告你才知道自己该优化什么。如果调用成功率低问题多半出在元数据和trigger上说明Agent没识别出来它需要触发这个Skill如果输出格式合法率低问题多半出在schema和few-shot示例上如果格式全对但语义匹配分低那才是真正的“内容不行”需要调整执行流程。这里要提示一句指标高不等于体验好指标低则一定有问题。语义匹配分这种弱断言本质上是让大模型给自己打分会有天然的宽松倾向。我在实际使用中会把阈值定得略高一些比如弱断言至少0.85才算合格给自己留出容错空间。4.4 把失败的case留下来它们最值钱每次回归跑完我都建议把失败的case保留在tests/failures目录里而不是直接修复后删掉。这些失败case是以后回归测试里最关键的“矿藏”。它们代表的是曾经发生过的问题如果你不把它们固化成用例下一次你改动别的字段时这个问题很可能原样复发。我自己维护Skill时有一条铁律修复一个bug之前先把这个bug对应的输入变成一条测试用例。做不到这一点修复就只能算临时补救没有沉淀价值。5. 多轮迭代实测一个文档摘要Skill的三次版本演进单讲概念有点飘我用一段实际的迭代经历来说明一个Skill是怎么在skill-creator的帮助下逐步变成“可靠”的。这个Skill很典型一个文档摘要能力看起来简单做深了全是细节。5.1 v1的问题什么文档都能总结恰恰是最大的缺陷这个Skill刚建好的时候我的实现方式和大多数人的第一版一样在SKILL.md里写“对输入文本进行总结输出摘要和要点”。当时跑smoke测试效果还行看起来能出结果。但把它暴露给真实用户之后反馈很快就来了有人拿它总结会议记录觉得要点不够集中有人拿它总结合同觉得关键条款被淹没了还有人拿它总结论文摘要觉得完全没有抓住核心贡献。问题出在哪问题在于我只设计了一个摘要模板所有类型的文档都用同一套思路去处理。合同的重点是付款条件、违约责任、争议解决论文的重点是问题、方法、结论会议记录的重点是决议事项和待办人。用一套模板去套所有文档产出自然是之乎者也都全但什么都没讲透。5.2 v2引入文档类型识别和可选参数v2我做了两个改动。一是在执行流程的最前面增加一步判断文档类型然后分派到不同的摘要模板。二是在schema里增加了focus_points这个可选参数允许调用方指定“重点看什么”。这两步改动之后回归数据有了明显变化指标v1v2调用成功率19/2020/20输出格式合法率16/2019/20语义匹配分0.780.88平均耗时4.2s3.1s语义匹配分从0.78升到0.88能看出模型产出的内容确实更贴合不同类型文档的期望了。但注意这一版还有一个问题没解决生成长度波动很大有时候摘要比原文都长有时候短得只有两句话。输出长度不可控对于下游系统来说就是致命伤。5.3 v3确定性输出和后处理约束v3的目标很明确让输出长度和结构尽量确定。我在SKILL.md里加了一条规则“摘要正文不超过输入文本的15%但至少保留3个要点当target_length为short时输出控制在150字以内。”同时在输出契约里把key_points改成固定结构每个要点必须由“观点依据”两段组成。这一版最明显的变化是相同的输入反复跑三次三次输出之间的结构差异明显缩小了。回归指标继续向好指标v2v3调用成功率20/2020/20输出格式合法率19/2020/20语义匹配分0.880.92平均耗时3.1s2.6s当然这三次迭代里我做的改动远不止这几个字段但核心逻辑就是一次只改一个变量然后用回归测试去验证这个变量是否真的起了作用。5.4 迭代过程中学到的三件小事这段实战经历让我对Skill优化有了三个很深的体感。第一不要同时改多个变量。如果你同时改了description、schema和执行流程最终指标上升了你根本不知道真正起作用的是哪一处改动也就没法继续放大这个正收益。第二指标上升不等于体验上升。语义匹配分从0.88到0.92看起来漂亮但如果你真的去读几条输出可能会发现模型只是更会“踩关键词”而内容的逻辑组织还是有毛刺。所以每次回归之后我至少会人工阅读三条成功case的完整输出用肉眼看一遍。第三v1比想象中重要得多。很多人在第一步就急着给Skill加各种复杂逻辑实际上第一版只要把“基本能跑通”和“测试集骨架”立住后面再一点点迭代方向反而更清晰。Skill是演进出来的不是设计出来的。6. 把Skill变成团队资产版本、评审与自动化卡点前面讲的是个人如何创建和优化单个Skill。当一个团队开始用skill-creator管理几十上百个Skill时真正的问题就从“怎么建一个”变成了“怎么让这么多Skill保持统一水准、避免互相干扰”。6.1 给每个Skill一个明确的生命周期状态团队协作里最大的混乱来源是有人改了一个Skill但另一个人不知道还在基于旧版本做二次开发。为了避免这种“行为漂移”我会在SKILL.md的front matter里维护两对字段version和status。status有四个取值draft、review、production、deprecated。draft是可以随便实验的阶段review是已经形成初稿、等待他人评审production是已经在生产环境被调用的阶段deprecated表示废弃Agent框架在加载Skill时会主动跳过它。每一次从production改成draft再改回来都要在history目录下生成一份快照。这样任何一个Skill的演进过程都是可追溯的哪一版引入了什么变化一目了然。6.2 Skill评审不只是看语法skill-creator的validate能检查结构和格式但它不能代替人工评审。我参与过的几个团队普遍会用一个评审清单来审查新提交的Skill大致如下description是否包含正面触发条件和负面不适用场景schema输入字段是否有默认值required是否足够克制examples目录是否至少有两个差异化显著的示例输出契约是否定义了必填字段和不确定性兜底测试集是否覆盖了正常、最小输入、极长输入和拒答场景语义匹配分基线是否设置合理而不是形同虚设这份清单的效果在于它把“这个Skill写得好不好”这种模糊的主观判断转化成了一系列可以用yes/no回答的客观问题。团队里哪怕是没有经验的新人照着清单走也能发现大部分质量问题。6.3 接入CI把质量门槛变成硬卡点Skill本身就是一个AI应用里的零部件那它理应像代码一样被CI管起来。我们在流水线里加了两道关卡合并前跑validate合入主干后跑test。如果validate失败直接阻止合并。如果test的回归分数低于metrics.yaml里定义的基线版本同样阻止合入。metric.yaml长这样baseline_version: v3 thresholds: call_success_rate: 0.95 format_valid_rate: 0.95 semantic_match_score: 0.85 max_avg_latency_ms: 5000设置threshold时有一个经验原则基线定得比当前版本实际分数略低一点给自己留出改进空间但也不能低太多失去意义。比如当前版本call_success_rate是0.92那基线就定0.90下一次改动只要分数低于0.90就会被拦下。这样可以防止任何人带着一个明显退步的改动合入。6.4 工具是表方法论是里如果只看工具本身skill-creator做的无非就是生成骨架、校验格式、跑测试、存快照。但当我把这套流程真正用起来之后发现最大的收获不是省了多少手写时间而是它把一种“工程化地对待AI行为”的思维方式带进了团队日常。以前我们讨论一个Skill好不好用是坐在会议室里说“我感觉它的输出文风很专业”“我觉得触发不够灵活”。现在讨论的是“这条case的语义匹配分为什么只有0.7”“这个参数缺省时Agent为什么走了错误分支”。前者是品味之争后者是问题定位两者之间有本质区别。我个人最深的体会是不要迷恋任何具体工具的参数配置重点去理解“定义契约—覆盖测试—回归对比—版本追溯”这条链路。你把这条链路建起来了任何一个叫skill-creator还是叫别的名字的工具都只是执行这套方法论的一个载体。真正值钱的从来不是工具本身而是你愿意像管理代码一样去管理那些看起来虚无缥缈的AI行为。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑