1. 为什么“把陌生领域方法论做成skill”这件事值得单独聊
第一次听到“skill”这个词,很多人的第一反应是游戏里的技能树,或者是某个AI工具里的插件。但在我实际折腾了一段时间之后,我发现它真正的价值点根本不在于“插件”这个形态,而在于它把一套可复用的做事流程从人的脑子里搬到了一个可以被反复调用的结构里。这件事听起来很虚,但落到具体场景里就非常实在:你临时要处理一个完全陌生的领域,比如帮朋友看一份PCB打样报价、给一个数学建模题目搭框架、或者快速理解一个GitHub上陌生项目的目录结构,你不可能每次都从零开始查资料、试错、总结。而skill就是把这些“从零到一”的过程固化下来,下次遇到同类问题直接调用。
我之所以想写这篇,是因为我自己踩过一个很典型的坑。最开始我以为skill就是写一段提示词,把步骤列清楚就行了。结果做出来的东西要么太泛,泛到任何领域都能套但任何领域都不好用;要么太窄,窄到只能处理某一个具体案例,换个场景就完全失效。后来我慢慢摸索出一套“从陌生领域到可调用skill”的转化方法,核心不是写提示词,而是先做领域解构,再做流程抽象,最后才是结构化封装。这个顺序一旦搞反,做出来的skill基本就是废的。
这篇文章适合几类人看:一是经常需要跨领域处理问题的人,比如产品经理、独立开发者、咨询顾问;二是已经在用Codex、GPT6这类工具做自动化,但觉得每次都要重新描述需求很烦的人;三是单纯对“skill”这个概念好奇,想知道它和agent到底有什么区别的人。我会尽量把每一步拆开讲,包括我实际用到的工具、遇到的报错、以及最后怎么绕过去的。全文没有理论堆砌,都是我自己跑过一遍的流程。
提示:如果你之前完全没接触过skill这个概念,可以先把它理解成“一个封装好的、可被调用的任务执行单元”。它和agent的区别在于,agent更偏向自主决策和动态规划,而skill更偏向固定流程的高效执行。两者不是替代关系,是配合关系。
2. 先搞清楚skill和agent的边界,不然方向一开始就错了
2.1 我最初把skill当agent用,结果翻车了
刚开始接触skill的时候,我脑子里想的是“这不就是让AI自己干活吗”,于是我尝试把一个完整的领域调研任务直接丢进去,期望它自己拆解、自己搜索、自己总结。结果就是:它确实能跑,但跑出来的东西质量极不稳定。同一个问题问两次,一次给出一堆泛泛而谈的废话,一次又钻到某个细节里出不来。后来我才意识到,我犯了一个根本性错误:我把skill当成了agent,但skill的本质是流程固化,不是自主决策。
Agent的核心能力是“在不确定环境下做决策”,它需要动态判断下一步做什么、要不要换路径、什么时候停下来。而skill的核心能力是“在确定流程下高效执行”,它不需要判断,只需要按照预设的步骤一步步走完。你把一个需要决策的任务塞给skill,就像让一个流水线工人去当项目经理,不是他能力不行,是角色错配了。
2.2 一个判断标准:任务有没有“固定套路”
那怎么判断一个任务该做成skill还是该交给agent?我后来总结了一个很简单的判断标准:看这个任务有没有固定套路。如果每次做的时候步骤基本一致,只是输入内容不同,那就适合做成skill。比如“把一份陌生领域的PDF拆解成核心概念清单”,这个流程是固定的:先提取目录、再识别关键术语、再按层级归类、最后输出结构化列表。每次只是PDF不同,步骤不变,这就是skill的典型场景。
反过来,如果任务需要根据中间结果动态调整策略,那就适合交给agent。比如“帮我调研一下这个行业值不值得进入”,这个任务没有固定套路,因为调研过程中可能会发现新问题、需要换方向、需要深入某个意外发现。这种任务交给agent更合适,skill做不了。
2.3 两者配合的实际工作流
在实际操作中,我现在的做法是:用agent做探索,用skill做沉淀。比如我接到一个陌生领域的任务,先让agent去跑一遍,看看这个领域大概是什么结构、有哪些关键节点、哪些步骤是重复出现的。跑完之后,我把其中重复出现的步骤抽出来,做成skill。下次再遇到同类任务,直接用skill跑固定流程,遇到需要决策的地方再切回agent。
这个工作流的好处是,你不会一开始就陷入“到底该用哪个”的纠结。先跑起来,跑的过程中自然就能看出哪些部分该固化、哪些部分该保留灵活性。我试过好几次,一开始觉得“这个任务太复杂了肯定做不成skill”,结果跑完一遍发现,80%的步骤都是重复的,只有20%需要动态判断。那80%就可以做成skill,剩下20%留给agent。
注意:不要试图把一个需要动态决策的任务硬做成skill。我见过有人把“帮我写一份商业计划书”做成skill,结果就是每次输出都像模板填空,完全没有针对性。这种任务的核心价值在于根据具体情况做判断,固化流程反而会杀死它的价值。
3. 从陌生领域到skill原型的四步解构法
3.1 第一步:用“三遍阅读法”快速摸清领域骨架
拿到一个陌生领域,最忌讳的就是一头扎进细节里。我自己的做法是“三遍阅读法”:第一遍只看目录和标题,把整个领域的结构画出来;第二遍只看每个章节的第一段和最后一段,把核心论点抓出来;第三遍才看具体内容,但只挑跟我要解决的问题相关的部分看。
这个方法听起来很笨,但实测下来效率极高。比如我之前要处理一个数学建模的题目,完全不懂那个领域。第一遍看目录,发现它分成了问题重述、模型假设、符号说明、模型建立、模型求解、结果分析几个部分。第二遍看每部分的首尾段,发现核心是“把实际问题转化成数学表达式,再用算法求解”。第三遍我只看了模型建立和求解部分,因为我的任务只是搭框架,不需要自己解。
三遍下来,我对这个领域的骨架就有了基本认知。这个骨架就是后面做skill的底层结构。如果你连骨架都没摸清就开始写步骤,写出来的东西一定是散的。
3.2 第二步:把“我做了什么”翻译成“可复用的动作序列”
摸清骨架之后,下一步是把你实际做的事情翻译成可复用的动作序列。这里有个关键点:不要写“我理解了XX”,要写“我执行了XX动作”。因为“理解”是不可复用的,但“执行动作”是可复用的。
举个例子,我在处理一个GitHub陌生项目的时候,实际做的事情是:先看README了解项目定位,再看目录结构判断代码组织方式,再看package.json或requirements.txt判断依赖,最后看issue区判断项目活跃度。这一串动作就是可复用的。我把它写成skill的时候,不会写“理解项目”,而是写“第一步:读取README前200字,提取项目定位关键词;第二步:列出根目录下所有文件夹,按名称判断模块划分;第三步:查找依赖文件,提取核心依赖列表……”
这种动作序列的好处是,任何人拿到这个skill,都能按照同样的步骤跑一遍,得到差不多的结果。它不依赖个人经验,只依赖流程本身。
3.3 第三步:给每个动作加上“判断条件”和“输出格式”
光有动作序列还不够,因为实际执行的时候,每个动作都可能遇到不同情况。比如“读取README”这个动作,有的项目README很长,有的很短,有的干脆没有。所以每个动作后面要加上判断条件和输出格式。
判断条件解决的是“遇到不同情况怎么办”。比如README超过500字就只读前200字和后100字,README不存在就跳到目录结构分析。输出格式解决的是“这一步产出什么”。比如“提取项目定位关键词”的输出格式是“三个以内的名词短语,按重要性排序”。
这一步是整个流程里最耗时间的,但也是最关键的。因为判断条件和输出格式决定了skill的鲁棒性。没有判断条件,skill遇到异常输入就崩了;没有输出格式,下一步就不知道拿什么当输入。
3.4 第四步:用“最小可运行版本”跑通再迭代
很多人做skill的时候喜欢一步到位,想把所有情况都考虑进去。我的经验是:先做一个最小可运行版本,能跑通一个最简单的案例就行,然后再迭代。
我第一个跑通的skill是“把陌生PDF拆解成概念清单”。最小版本只做了三件事:提取目录、识别加粗术语、按层级输出。跑通之后,我发现有些PDF没有目录,于是加了“无目录时按段落首句提取”的判断;又发现有些术语是斜体不是加粗,于是加了格式判断。迭代了四五轮之后,这个skill已经能处理大部分常见PDF了。
如果你一开始就想把所有情况都覆盖,大概率会卡在某个细节上出不来。先跑通,再补漏,这个顺序不能反。
4. 实操:把我处理PCB打样报价的流程做成一个skill
4.1 为什么选这个场景:足够陌生、足够重复、足够有痛点
我选PCB打样报价这个场景来演示,原因有三个。第一,它对我来说足够陌生,我完全不懂PCB制造工艺,第一次看报价单的时候连“沉金”和“喷锡”有什么区别都不知道。第二,它足够重复,我每个月都要帮团队处理几次打样需求,每次都要重新看报价、对比参数。第三,它有明确的痛点:报价单里的参数太多,不同厂家的格式还不一样,人工对比很容易漏掉关键项。
这个场景完美符合“陌生领域+重复流程”的特征,是做skill的理想素材。下面我把整个转化过程拆开讲,包括我实际用到的工具和遇到的坑。
4.2 领域解构:一份PCB报价单里到底有哪些关键参数
我先用三遍阅读法把一份典型的PCB报价单拆了一遍。第一遍看整体结构,发现它分成板材信息、工艺参数、数量与交期、价格明细四个部分。第二遍看每个部分的核心项,发现板材信息里最关键的是板厚、铜厚、材质;工艺参数里最关键的是最小线宽、最小孔径、表面处理方式;数量与交期里最关键的是起订量、加急费用;价格明细里最关键的是工程费、板费、测试费。
第三遍我重点看了不同厂家的报价单差异,发现虽然格式不同,但核心参数就那么十几个。有些厂家会把“沉金”写成“ENIG”,有些会把“喷锡”写成“HASL”,但本质上是一回事。这个发现很关键,因为它意味着我可以用一套统一的参数体系来归一化不同厂家的报价。
4.3 动作序列设计:从“收到报价单”到“输出对比表”
摸清参数体系之后,我开始设计动作序列。整个流程我拆成了六步:
- 读取报价单:支持PDF、Excel、图片三种格式,图片走OCR识别。
- 提取核心参数:按照预设的十几个关键项,从报价单里抽取对应数值。
- 参数归一化:把不同厂家的术语统一成标准术语,比如ENIG统一成沉金。
- 异常值标记:对超出常规范围的参数打标记,比如板厚超过3mm、交期少于24小时。
- 生成对比表:把多个厂家的报价按统一格式输出成表格。
- 输出建议:根据预设规则给出“推荐优先联系”的厂家排序。
这六步里,第一步和第二步是纯执行,第三步需要术语映射表,第四步需要阈值表,第五步和第六步是格式化输出。每一部分我都单独做了测试,确保输入不同格式的报价单都能跑通。
4.4 判断条件与输出格式的具体写法
判断条件我举几个实际例子。比如“读取报价单”这一步,判断条件是:如果是PDF且文字可选中,直接提取文字;如果是PDF但文字不可选中,走OCR;如果是Excel,直接读单元格;如果是图片,走OCR。输出格式是:纯文本,保留原始表格结构。
“提取核心参数”这一步,判断条件是:如果某个参数在报价单里出现多次,取最后一次出现的值;如果某个参数完全没出现,标记为“未提供”。输出格式是:键值对列表,键是标准参数名,值是提取到的数值加单位。
“参数归一化”这一步,判断条件是:如果术语在映射表里,替换成标准术语;如果不在映射表里,保留原术语并标记“待确认”。输出格式是:归一化后的键值对列表,外加一个待确认术语清单。
这些判断条件和输出格式看起来琐碎,但正是它们让skill变得可靠。没有它们,skill就是一个脆弱的脚本,输入稍微变一下就跑不通了。
4.5 跑通之后发现的三个意外问题
第一个意外问题是:有些厂家的报价单里,价格是含税的,有些是不含税的。我一开始没注意这个,导致对比表里的价格根本没法直接比。后来加了一个判断条件:如果报价单里出现“含税”或“不含税”字样,提取并标记;如果没有出现,默认按不含税处理并在输出里注明。
第二个意外问题是:有些厂家会把工程费单独列出来,有些会摊到板费里。这导致总价对比失真。我的处理方式是:在输出对比表的时候,同时列出“工程费”和“板费”两列,让用户自己判断。如果工程费被摊到板费里,就在工程费列标记“已摊入板费”。
第三个意外问题是:OCR识别图片报价单的时候,经常把“0”识别成“O”,把“1”识别成“l”。这个问题我试了好几种方案,最后发现最简单的办法是在OCR之后加一步正则校验,把所有疑似字母的字符在数字上下文里强制转成数字。虽然偶尔会误判,但比人工检查快多了。
提示:做skill的时候,一定要留一个“异常标记”的输出通道。不要试图让skill处理所有异常,而是让它把异常标出来,交给人工判断。这样既保证了流程的自动化,又不会因为异常导致整个流程崩溃。
5. 让skill真正可复用的三个封装技巧
5.1 参数外置:把“会变的东西”从流程里抽出来
我第一个版本的skill是把所有参数都写死在流程里的,结果换个厂家就要改一遍代码。后来我把所有会变的东西都抽出来做成外部参数,比如术语映射表、阈值表、输出格式模板。流程本身只负责“读取-提取-归一化-输出”这个骨架,具体用什么映射表、什么阈值,全部通过参数传入。
这个改动带来的好处非常明显。现在我新增一个厂家的报价单,只需要在映射表里加几行术语对应关系,流程完全不用动。参数外置的本质是把“流程”和“配置”分离,流程保持稳定,配置随时可改。
5.2 分层输出:让skill既能给机器看,也能给人看
我一开始的输出格式是纯文本,后来发现不同场景需要不同格式。有时候我需要把结果喂给下一个skill,这时候需要结构化数据;有时候我需要直接给人看,这时候需要可读性强的表格。于是我做了分层输出:底层是JSON格式的结构化数据,中层是Markdown表格,顶层是一句话总结。
分层输出的好处是,同一个skill可以适配不同下游需求。需要机器处理的时候取底层,需要人看的时候取中层,需要快速判断的时候取顶层。不用为每个场景单独做一个skill。
5.3 版本标记:每次修改都留痕,不然会把自己搞乱
这个技巧听起来很基础,但我实际踩过坑。有段时间我频繁修改skill的判断条件,改到后来自己都忘了哪个版本是什么逻辑。有一次跑出来结果不对,排查了半天才发现是用了旧版本的映射表。
后来我养成了习惯:每次修改skill,都在文件头部加一行版本标记,写明修改日期、修改内容、修改原因。比如“v1.3 2025-03-12 增加含税判断,因为发现三家厂家报价含税状态不一致”。这个习惯看起来麻烦,但省下来的排查时间远超写标记的时间。
6. 从skill到workbuddy:怎么让多个skill协同干活
6.1 单个skill的局限:只能处理单一流程
单个skill再强,也只能处理一个固定流程。但实际工作中,一个完整任务往往需要多个流程串联。比如处理PCB打样,除了对比报价,还需要评估厂家资质、跟踪交期、归档历史报价。这些流程各自独立,但最终要串在一起才能完成整个任务。
我一开始的做法是手动串联:跑完报价对比skill,再把结果复制到下一个skill里。但这样效率很低,而且容易在复制过程中丢信息。后来我开始尝试让多个skill协同工作,也就是所谓的“workbuddy”模式。
6.2 协同的关键:统一数据格式和调用协议
多个skill协同,最大的障碍是数据格式不统一。A skill输出的是JSON,B skill需要的是Markdown表格,中间就得加一个转换步骤。我的解决方案是:所有skill的底层输出统一用JSON,并且约定一套最小公共字段。比如每个skill的输出都必须包含status、data、errors三个字段,status表示执行状态,data是具体数据,errors是异常列表。
有了这套约定,skill之间就可以直接互相调用。A skill跑完,把JSON传给B skill,B skill从data里取自己需要的字段,从errors里判断有没有需要处理的异常。不需要中间转换,也不需要人工干预。
6.3 实际跑下来的效果和踩过的坑
我目前跑通了三个skill的协同:报价对比、资质评估、交期跟踪。整体流程是:报价对比skill输出对比表,资质评估skill根据对比表里的厂家名单去查资质信息,交期跟踪skill根据对比表里的交期信息生成跟踪提醒。三个skill串起来之后,原本需要半小时的人工流程压缩到了三分钟左右。
踩过的坑主要有两个。第一个是错误传递:A skill的errors字段如果没处理好,B skill可能会把异常数据当成正常数据继续处理。我的解决办法是在每个skill的入口加一个校验步骤,如果上游传来的errors不为空,先处理异常再继续。第二个是超时:某个skill跑太久会导致整个链条卡住。我的解决办法是给每个skill设一个超时阈值,超时就跳过并标记,不让它拖垮整个流程。
注意:多个skill协同的时候,一定要有一个“总控”来管理调用顺序和异常处理。不要让skill之间直接互相调用,而是通过总控来调度。这样任何一个skill出问题,都不会影响其他skill。
7. 我踩过的五个坑和对应的绕行方案
7.1 坑一:把“领域知识”和“流程知识”混在一起
最开始做skill的时候,我把领域知识和流程知识混在一起写。比如在“提取参数”这一步里,我不仅写了怎么提取,还写了一大段“什么是沉金、什么是喷锡”的解释。结果就是skill变得非常臃肿,而且换个领域这些解释完全没用。
后来我把领域知识抽出来做成独立的“知识卡片”,流程里只保留“调用知识卡片”的动作。这样流程保持精简,知识卡片可以单独更新和复用。比如PCB的知识卡片和数学建模的知识卡片完全独立,但流程骨架可以共用。
7.2 坑二:判断条件写得太死,遇到变体就崩
我一开始写判断条件的时候,喜欢用精确匹配。比如“如果报价单里出现‘沉金’两个字,就标记为沉金工艺”。结果遇到写“ENIG”的厂家就识别不了。后来我把精确匹配改成模糊匹配加映射表,先模糊搜索关键词,再通过映射表归一化。这样即使厂家用不同的术语,也能正确识别。
7.3 坑三:输出格式没有版本控制,下游对不上
这个坑我在第5.3节提过,但值得再强调一次。输出格式一旦定了,下游skill就会依赖它。如果你改了输出格式但没通知下游,下游就会解析失败。我的解决方案是给输出格式加版本号,比如output_version: "1.2",下游skill先检查版本号,版本不匹配就报错而不是静默失败。
7.4 坑四:没有做输入校验,脏数据直接进流程
有一次我收到一份报价单,里面有个参数写的是“待定”,结果我的skill直接把“待定”当成数值处理,后面所有计算全错了。后来我在每个skill的入口加了输入校验,检查关键字段是否存在、格式是否正确、数值是否在合理范围内。校验不通过就直接返回错误,不让脏数据进流程。
7.5 坑五:忘了做日志,出问题找不到原因
这个坑是最隐蔽的。skill跑的时候如果不记日志,出问题了你根本不知道是哪一步错了。我后来在每个skill的每个步骤都加了日志输出,记录输入、输出、耗时、异常。日志不用很复杂,一行文本就行,但关键时刻能救命。
8. 关于skill后续扩展的一些个人想法
我现在做skill的流程基本稳定了:先用agent跑一遍陌生领域,摸清骨架;再用四步解构法把流程抽出来;然后做最小可运行版本,跑通再迭代;最后做参数外置和分层输出,让它可复用。这套流程跑下来,做一个新skill的时间大概在两到三个小时,比我一开始动辄一两天快了很多。
后续我打算尝试的方向有两个。一个是把更多领域的知识卡片积累起来,让skill的领域覆盖更广。另一个是尝试让skill自己生成skill,也就是用agent去分析一个陌生流程,自动抽取出可复用的动作序列,然后生成skill原型。这个想法目前还在实验阶段,跑通了再分享。
如果你也在做类似的事情,我的建议是:不要追求一步到位,先跑通一个最小场景,哪怕它只能处理一种格式的输入。跑通之后你会发现,迭代的方向自然就出来了。最怕的是一直在设计阶段纠结,迟迟不动手,最后什么都没做出来。