發(fā)實(shí)戰(zhàn):用三件套打造高效測(cè)試Skill)
我第一次正式給Agent寫(xiě)Skill是在一個(gè)單測(cè)覆蓋率跌到40%的項(xiàng)目里。當(dāng)時(shí)按網(wǎng)上的教程飛快地寫(xiě)了一個(gè)SKILL.md讓AI“運(yùn)行項(xiàng)目測(cè)試并輸出優(yōu)化報(bào)告”。結(jié)果它跑完pytest之后把終端輸出原樣貼回來(lái)再煞有介事地總結(jié)一句“測(cè)試全部通過(guò)”。覆蓋率沒(méi)提失敗用例沒(méi)歸類(lèi)優(yōu)化建議全是通用話(huà)術(shù)。那一刻我意識(shí)到一個(gè)Skill絕不是一個(gè)markdown文件的事。后來(lái)我把同一個(gè)需求重寫(xiě)了一遍用上了SKILL.md scripts references三件套效果完全不一樣。AI會(huì)自動(dòng)收集測(cè)試范圍、執(zhí)行腳本拿到結(jié)構(gòu)化結(jié)果、對(duì)照模板生成報(bào)告、遇到失敗還會(huì)翻參考資料里的案例庫(kù)。整個(gè)過(guò)程像把一個(gè)只會(huì)嘴上說(shuō)說(shuō)的實(shí)習(xí)生訓(xùn)練成了能獨(dú)立干活且懂規(guī)矩的正式員工。這篇實(shí)戰(zhàn)指南就是圍繞這個(gè)“測(cè)試Skill”從0到1的完整過(guò)程展開(kāi)的。我會(huì)拆解三件套各自的職責(zé)邊界給出SKILL.md、scripts、references每一步具體怎么寫(xiě)再帶你走一遍聯(lián)調(diào)測(cè)試和迭代維護(hù)的全流程。適合剛接觸Agent Skill開(kāi)發(fā)、寫(xiě)過(guò)但總跑不通以及想讓Skill從“能用”變“好用”的開(kāi)發(fā)者。1. Skill的底層邏輯三件套不是隨便湊出來(lái)的組合很多人在接觸Skill開(kāi)發(fā)時(shí)會(huì)問(wèn)既然SKILL.md本身就能寫(xiě)清楚“該怎么做”為什么還要單獨(dú)搞scripts和references兩個(gè)目錄這個(gè)問(wèn)題如果沒(méi)想明白后面寫(xiě)出來(lái)的Skill大概率是四不像。1.1 Skill不是插件也不是Prompt模板Skill這個(gè)概念在Claude Code、Codex等Agent開(kāi)發(fā)環(huán)境中越來(lái)越常見(jiàn)但很多人對(duì)它的理解還停留在“一個(gè)長(zhǎng)一點(diǎn)的Prompt”或“一個(gè)輕量插件”。這兩種理解都不準(zhǔn)確。插件通常常駐運(yùn)行有明確的切入點(diǎn)和生命周期Skill則是按需加載的。AI根據(jù)當(dāng)前任務(wù)判斷“這個(gè)場(chǎng)景好像有對(duì)應(yīng)的Skill”然后主動(dòng)讀取Skill目錄里的內(nèi)容按照里面的約定去執(zhí)行。Prompt模板則只有文字Skill除了文字還可以包含可執(zhí)行腳本和結(jié)構(gòu)化參考資料。我更愿意用一個(gè)類(lèi)比來(lái)解釋Skill像是一個(gè)“帶說(shuō)明書(shū)、工具包和參考資料的外包師傅”。說(shuō)明書(shū)告訴師傅什么時(shí)候該接活、按什么流程干工具包裝著電鉆、水平儀這些真正干活的工具參考資料則是師傅過(guò)去積累的施工圖紙和驗(yàn)收標(biāo)準(zhǔn)。只有說(shuō)明書(shū)沒(méi)有工具師傅只能紙上談兵只有工具沒(méi)有圖紙師傅容易干出野路子。1.2 三件套的分工認(rèn)知、能力、知識(shí)SKILL.md、scripts、references這三個(gè)部分正好對(duì)應(yīng)了一個(gè)專(zhuān)業(yè)崗位的三個(gè)核心要素認(rèn)知判斷、操作能力、經(jīng)驗(yàn)知識(shí)。組成部分對(duì)應(yīng)要素AI什么時(shí)候用到寫(xiě)不好會(huì)怎樣SKILL.md認(rèn)知與流程任務(wù)剛開(kāi)始AI判斷要不要用這個(gè)Skill、按什么步驟執(zhí)行時(shí)AI不會(huì)調(diào)用或調(diào)用后流程混亂、邊界失守scripts操作能力需要執(zhí)行多步命令、處理數(shù)據(jù)、生成結(jié)構(gòu)化結(jié)果時(shí)AI只能“假裝”執(zhí)行輸出不可驗(yàn)證容易編造結(jié)果references經(jīng)驗(yàn)與標(biāo)準(zhǔn)需要產(chǎn)出符合規(guī)范的報(bào)告、排查歷史問(wèn)題、套用模板時(shí)輸出質(zhì)量看運(yùn)氣每次生成的東西風(fēng)格不一致表格里“寫(xiě)不好會(huì)怎樣”這一列是我在大量實(shí)際案例里反復(fù)驗(yàn)證過(guò)的。尤其是scripts缺失的問(wèn)題隱蔽性最強(qiáng)。因?yàn)锳I非常擅長(zhǎng)“用文字模擬執(zhí)行”你要是沒(méi)給它真能跑的腳本它會(huì)在報(bào)告里寫(xiě)“經(jīng)分析建議優(yōu)化xxx”但實(shí)際上什么都沒(méi)分析。1.3 為什么“只寫(xiě)SKILL.md”是最常見(jiàn)的翻車(chē)方式大部分人的第一個(gè)Skill都是只寫(xiě)了一個(gè)SKILL.md包括我自己。原因很簡(jiǎn)單網(wǎng)上教程多數(shù)只展示這個(gè)文件而且它寫(xiě)起來(lái)門(mén)檻最低感覺(jué)像在寫(xiě)Markdown文檔。但只寫(xiě)SKILL.md會(huì)帶來(lái)幾個(gè)連鎖問(wèn)題。第一AI沒(méi)有“抓手”。你讓它“運(yùn)行測(cè)試并分析覆蓋率”它可能會(huì)選擇自己構(gòu)造一條shell命令去執(zhí)行也可能選擇不執(zhí)行、直接根據(jù)項(xiàng)目里的代碼結(jié)構(gòu)憑空分析。不執(zhí)行的時(shí)候輸出就是幻覺(jué)。第二輸出格式不可控。沒(méi)有腳本統(tǒng)一生成結(jié)構(gòu)化結(jié)果AI每次返回的報(bào)告樣式都不同。今天用表格明天用列表后天可能變成一段散文你根本沒(méi)法在后續(xù)流程里自動(dòng)化處理。第三邊界無(wú)法約束。Scripts里可以寫(xiě)嚴(yán)格的參數(shù)校驗(yàn)、超時(shí)處理、退出碼約定純文本的SKILL.md很難做到這點(diǎn)。沒(méi)有這些工程化約束AI的“自由發(fā)揮空間”就太大了。所以我的判斷是一個(gè)合格的Skill必須是三件套協(xié)同工作。SKILL.md負(fù)責(zé)“知道做什么、按什么順序做”scripts負(fù)責(zé)“真正把事情做成”references負(fù)責(zé)“保證做出來(lái)的東西符合標(biāo)準(zhǔn)”。2. 第一步SKILL.md是給Agent看的“上崗說(shuō)明書(shū)”SKILL.md是整個(gè)Skill的入口文件也是Agent決定“要不要調(diào)用你”“調(diào)用你之后聽(tīng)你指揮”的關(guān)鍵。它的寫(xiě)法跟寫(xiě)產(chǎn)品文檔完全是兩回事核心目標(biāo)只有一個(gè)讓一個(gè)擁有很強(qiáng)推理能力但缺乏業(yè)務(wù)語(yǔ)境的模型在幾秒內(nèi)理解你的Skill適合什么場(chǎng)景、應(yīng)該怎么執(zhí)行。2.1 frontmatter里的description才是真正的調(diào)用開(kāi)關(guān)SKILL.md頂部的YAML frontmatter看起來(lái)只是一個(gè)格式要求但字段設(shè)計(jì)的顆粒度直接決定了Skill能不能被正確觸發(fā)。以我做的auto-test-skill為例--- name: auto-test-skill description: 在Python項(xiàng)目中自動(dòng)收集、運(yùn)行測(cè)試用例并生成可讀的測(cè)試報(bào)告。當(dāng)用戶(hù)要求“檢查測(cè)試”“跑一下單測(cè)”“驗(yàn)證代碼沒(méi)有引入回歸”或CI失敗需要分析時(shí)使用。輸入為項(xiàng)目路徑或目標(biāo)測(cè)試范圍輸出為結(jié)構(gòu)化測(cè)試報(bào)告。 ---這里最關(guān)鍵的不是name而是description。AI判斷是否加載這個(gè)Skill時(shí)主要就是拿用戶(hù)當(dāng)前的需求跟所有Skill的description做語(yǔ)義匹配。description寫(xiě)得越具體匹配越精準(zhǔn)。反例是很多人喜歡寫(xiě)“A skill for running tests and generating reports”這種描述太泛AI面對(duì)稍微特殊一點(diǎn)的需求就不會(huì)想起來(lái)用它。正例應(yīng)該是把“觸發(fā)場(chǎng)景”和“不觸發(fā)場(chǎng)景”都揉進(jìn)去比如“當(dāng)用戶(hù)只是想聊測(cè)試概念時(shí)不要用當(dāng)用戶(hù)要求實(shí)際執(zhí)行測(cè)試時(shí)使用”。2.2 正文結(jié)構(gòu)觸發(fā)條件、工作流程、執(zhí)行規(guī)則寫(xiě)完frontmatter之后SKILL.md的正文才是重頭戲。我見(jiàn)過(guò)很多人的SKILL.md就是一篇項(xiàng)目文檔把所有功能羅列一遍AI看完依然不知道從哪里下手。我的推薦結(jié)構(gòu)是以下五段式這個(gè)Skill解決什么問(wèn)題一段話(huà)說(shuō)明邊界“它負(fù)責(zé)什么、不負(fù)責(zé)什么”。什么時(shí)候使用比description更詳細(xì)的觸發(fā)場(chǎng)景列表給出正例和反例。工作流程編號(hào)列表每一步做什么、這一步的輸出是什么。執(zhí)行規(guī)則明確允許做什么、禁止做什么包括異常情況的兜底策略。輸入與輸出約定告訴AI當(dāng)前任務(wù)的輸入怎么讀取最終成果物以什么形式交付。以auto-test-skill為例工作流程段我這樣寫(xiě)## 工作流程 1. 用 scripts/collect_tests.py 收集項(xiàng)目中的測(cè)試文件清單確認(rèn)本次測(cè)試范圍。 2. 用 scripts/run_tests.py 執(zhí)行測(cè)試傳入目標(biāo)路徑和超時(shí)秒數(shù)獲得結(jié)構(gòu)化結(jié)果。 3. 如果測(cè)試失敗先讀取 references/failure_playbook.md按其中的常見(jiàn)案例進(jìn)行定位。 4. 用 references/report_template.md 生成最終報(bào)告報(bào)告需包含通過(guò)率、失敗用例明細(xì)、耗時(shí)、修復(fù)建議。注意第3步和第4步中references的引用方式。不要寫(xiě)“參考相關(guān)資料”要寫(xiě)清楚“去哪個(gè)文件里查”。AI對(duì)顯式路徑的敏感度遠(yuǎn)高于模糊指引這是實(shí)測(cè)出來(lái)的結(jié)論。2.3 邊界條件告訴AI什么不能做比告訴它能做什么更重要沒(méi)有邊界的Skill是危險(xiǎn)的。一個(gè)測(cè)試Skill如果不加約束AI可能在“修復(fù)失敗用例”時(shí)順手改掉業(yè)務(wù)源碼或者在項(xiàng)目沒(méi)有安裝依賴(lài)時(shí)自作主張執(zhí)行pip install甚至為了通過(guò)率好看而跳過(guò)失敗用例。所以我在SKILL.md里單獨(dú)列出“規(guī)則”一節(jié)## 規(guī)則 - 不要修改任何源碼和測(cè)試文件除非用戶(hù)明確要求。 - 不要安裝依賴(lài)除非用戶(hù)明確要求。依賴(lài)缺失時(shí)在報(bào)告中標(biāo)注即可。 - 測(cè)試結(jié)果以腳本解析出的數(shù)據(jù)為準(zhǔn)不要自行判斷“應(yīng)該沒(méi)問(wèn)題”。 - 如果執(zhí)行超時(shí)或命令不存在停止操作并在報(bào)告中說(shuō)明原因。 - 報(bào)告必須按 references/report_template.md 的格式輸出禁止自由發(fā)揮。這幾條規(guī)則本質(zhì)上是在限制AI的“動(dòng)作空間”。動(dòng)作空間越小出幺蛾子的概率越低。你要理解一個(gè)事實(shí)模型天然傾向于“把事辦了”哪怕事辦得粗糙它也會(huì)想辦。你如果不劃定紅線(xiàn)它會(huì)用各種意想不到的方式幫你“優(yōu)化”。我個(gè)人的經(jīng)驗(yàn)是每一版SKILL.md改完都花10分鐘自我拷問(wèn)一遍——“如果讓一個(gè)有點(diǎn)能力但不太懂規(guī)矩的新人來(lái)執(zhí)行這份說(shuō)明書(shū)他會(huì)鉆哪些空子”所有能想到的空子都值得寫(xiě)進(jìn)規(guī)則里。3. 第二步scripts要能讓Agent像調(diào)用工具一樣放心調(diào)用SKILL.md寫(xiě)得再好也代替不了真正干活的腳本。scripts目錄是整個(gè)Skill的“手和腳”它的設(shè)計(jì)原則跟普通工程項(xiàng)目不太一樣核心指標(biāo)是可預(yù)測(cè)性。Agent在調(diào)用時(shí)必須能預(yù)判腳本輸入什么、輸出什么、什么情況下會(huì)掛。3.1 什么時(shí)候必須寫(xiě)腳本什么時(shí)候可以不寫(xiě)不是所有Skill都需要scripts。比如一個(gè)“代碼審查規(guī)范Skill”主要給AI提供審查規(guī)則清單強(qiáng)調(diào)判斷標(biāo)準(zhǔn)那不一定非要有腳本。但如果涉及執(zhí)行類(lèi)任務(wù)比如運(yùn)行測(cè)試、統(tǒng)計(jì)代碼量、檢查接口狀態(tài)、批量處理文件不寫(xiě)腳本就是給自己挖坑。判斷標(biāo)準(zhǔn)很簡(jiǎn)單如果這個(gè)任務(wù)的執(zhí)行結(jié)果需要“被驗(yàn)證”就必須有腳本。所謂被驗(yàn)證就是AI不能自己說(shuō)了算必須有一個(gè)外部程序生成一個(gè)確定性的結(jié)果。測(cè)試場(chǎng)景恰好是典型代表——AI說(shuō)“測(cè)試通過(guò)了”不算數(shù)pytest退出碼是0才算數(shù)。一個(gè)常被忽略的點(diǎn)是腳本數(shù)量不必多但要保證“原子性”。每個(gè)腳本只干一件事名字用動(dòng)詞開(kāi)頭參數(shù)含義要明確。我見(jiàn)過(guò)有人把一個(gè)測(cè)試Skill做成一個(gè)巨大的pipeline腳本接收十幾個(gè)參數(shù)AI調(diào)用時(shí)經(jīng)常拼錯(cuò)一個(gè)參數(shù)然后整體報(bào)錯(cuò)。這種設(shè)計(jì)是反可預(yù)測(cè)性的。3.2 腳本與SKILL.md的調(diào)用約定腳本寫(xiě)完之后SKILL.md必須明確告訴AI怎么調(diào)用。這里有個(gè)容易犯的錯(cuò)只寫(xiě)“用scripts里的腳本執(zhí)行測(cè)試”卻不寫(xiě)具體命令。AI遇到這種情況會(huì)自己去翻目錄猜腳本名猜錯(cuò)的概率不低。正確的做法是給出完整命令模板執(zhí)行測(cè)試 !bash scripts/run_tests.py --target 目標(biāo)路徑 --timeout 秒數(shù)把參數(shù)項(xiàng)、參數(shù)含義、輸出格式都寫(xiě)清楚。AI看到一個(gè)規(guī)范到位的命令模板它就知道這不是讓你自由發(fā)揮的接口而是必須按約定調(diào)用。輸入輸出契約同樣重要。我在所有scripts里都堅(jiān)持兩個(gè)原則輸入只用命令行參數(shù)和標(biāo)準(zhǔn)輸入不用環(huán)境變量傳遞關(guān)鍵業(yè)務(wù)參數(shù)因?yàn)锳I在執(zhí)行腳本時(shí)環(huán)境變量不可控。輸出必須是可解析的純文本或JSON。運(yùn)行結(jié)果要能一眼看出“成功/失敗/跳過(guò)/錯(cuò)誤”的狀態(tài)分類(lèi)不能把一堆無(wú)關(guān)日志混在結(jié)果里。3.3 實(shí)戰(zhàn)寫(xiě)一個(gè)測(cè)試執(zhí)行腳本這里分享一個(gè)我在auto-test-skill里真正用到的核心腳本。它的任務(wù)不是把pytest跑一遍就完而是要拿到一份讓AI能直接用來(lái)生成報(bào)告的結(jié)構(gòu)化結(jié)果。#!/usr/bin/env python3 運(yùn)行測(cè)試并輸出結(jié)構(gòu)化摘要。 import argparse import json import subprocess import sys from pathlib import Path def parse_args(): parser argparse.ArgumentParser(descriptionRun tests and summarize result) parser.add_argument(--target, requiredTrue, helptarget directory or file) parser.add_argument(--timeout, typeint, default120, helptimeout seconds) return parser.parse_args() def run_pytest(target: str, timeout: int) - dict: cmd [python, -m, pytest, target, -q, --tbshort] try: proc subprocess.run( cmd, capture_outputTrue, textTrue, timeouttimeout, ) return { exit_code: proc.returncode, stdout_tail: proc.stdout[-2000:], stderr_tail: proc.stderr[-1000:], } except subprocess.TimeoutExpired: return { exit_code: 124, stdout_tail: , stderr_tail: timeout after %d seconds % timeout, } def main(): args parse_args() result run_pytest(args.target, args.timeout) # 輸出JSON避免AI解析長(zhǎng)文本失敗 print(json.dumps(result, ensure_asciiFalse, indent2)) sys.exit(0 if result[exit_code] 0 else result[exit_code]) if __name__ __main__: main()這個(gè)腳本有幾個(gè)設(shè)計(jì)細(xì)節(jié)值得說(shuō)。第一stdout_tail截取了輸出末尾2000個(gè)字符。原因很簡(jiǎn)單模型的上下文窗口很寶貴一個(gè)塞滿(mǎn)幾千行測(cè)試日志的輸出會(huì)把AI“沖昏頭腦”。只保留尾部關(guān)鍵信息足夠判斷錯(cuò)誤原因。第二超時(shí)時(shí)間由調(diào)用方傳入腳本本身不做死配置。不同項(xiàng)目測(cè)試規(guī)模差異巨大SKILL.md里要求AI根據(jù)目標(biāo)目錄大小調(diào)整超時(shí)參數(shù)而不是所有項(xiàng)目都用同一個(gè)值。第三輸出JSON格式。這樣AI讀到結(jié)果后能直接按字段提取信息生成報(bào)告不需要在一大坨文本里人肉找數(shù)據(jù)。3.4 腳本的容錯(cuò)與“啞彈”處理腳本還有一個(gè)容易被低估的點(diǎn)容錯(cuò)。Agent執(zhí)行腳本時(shí)環(huán)境可能跟你想的完全不一樣。比如項(xiàng)目用的依賴(lài)管理器不是pip是poetry或pytest根本沒(méi)有安裝甚至python命令本身指向了Python 2。這些情況腳本都要有明確輸出不能直接崩潰留一堆traceback。我一般會(huì)在腳本開(kāi)頭做環(huán)境自檢def check_environment(): missing [] try: import pytest # noqa: F401 except ImportError: missing.append(pytest) if missing: print(json.dumps({ exit_code: 127, error: missing dependencies: , .join(missing) })) sys.exit(127)注意這里設(shè)置了一個(gè)特殊的退出碼127語(yǔ)義是“命令不存在”。AI拿到這個(gè)退出碼后會(huì)知道這是環(huán)境問(wèn)題不是測(cè)試本身失敗從而在報(bào)告中如實(shí)說(shuō)明而不是編造一個(gè)“測(cè)試不通過(guò)”的假結(jié)論。4. 第三步references決定輸出質(zhì)量的下限SKILL.md給出了行動(dòng)路徑scripts提供了執(zhí)行能力但還有一個(gè)問(wèn)題沒(méi)解決AI產(chǎn)出的東西“像不像樣”。這正是references要負(fù)責(zé)的事。很多人寫(xiě)Skill不重視r(shí)eferences結(jié)果AI每次輸出的報(bào)告格式都不一樣細(xì)節(jié)經(jīng)常丟失。references的本質(zhì)是給AI一份“照抄都不會(huì)抄錯(cuò)”的底稿。4.1 references里到底該放什么references目錄的核心原則是放那些AI在生成結(jié)果時(shí)“應(yīng)該照著做”的東西而不是放“AI需要閱讀理解的背景資料”。以auto-test-skill為例我的references目錄長(zhǎng)這樣references/ ├── report_template.md ├── coverage_policy.md └── failure_playbook.mdreport_template.md是測(cè)試報(bào)告的固定模板里面有章節(jié)結(jié)構(gòu)、表格格式、填表說(shuō)明。coverage_policy.md定義了覆蓋率評(píng)判標(biāo)準(zhǔn)比如新增代碼覆蓋率低于80%要標(biāo)記為風(fēng)險(xiǎn)。failure_playbook.md記錄了過(guò)去項(xiàng)目里出現(xiàn)過(guò)的典型失敗案例及對(duì)應(yīng)處理方式。這三類(lèi)文件分別對(duì)應(yīng)三個(gè)不同的用途輸出風(fēng)格約束、判斷標(biāo)準(zhǔn)約束、異常處理經(jīng)驗(yàn)。一個(gè)有經(jīng)驗(yàn)的開(kāi)發(fā)者看到這里應(yīng)該能感覺(jué)到這其實(shí)就是把“隱性知識(shí)”顯性化的過(guò)程。4.2 實(shí)戰(zhàn)給測(cè)試Skill準(zhǔn)備references模板report_template.md是我最看重的一個(gè)文件它決定了AI最終交出來(lái)的報(bào)告長(zhǎng)什么樣。我的模板大概長(zhǎng)這樣# 測(cè)試報(bào)告 ## 1. 概覽 - 測(cè)試范圍目標(biāo)路徑 - 執(zhí)行時(shí)間日期 - 總用例數(shù)N - 通過(guò)/失敗/跳過(guò)N/N/N - 通過(guò)率百分比 ## 2. 失敗用例明細(xì) | 用例名 | 失敗原因 | 涉及文件 | 建議操作 | | --- | --- | --- | --- | ## 3. 覆蓋率分析 - 總覆蓋率百分比 - 關(guān)鍵模塊覆蓋率模塊名 百分比 - 風(fēng)險(xiǎn)提示是否低于閾值 ## 4. 修復(fù)建議 按優(yōu)先級(jí)列出每條建議需說(shuō)明依據(jù)關(guān)鍵在“建議操作”那一列。我要求AI必須填寫(xiě)不能留空。因?yàn)锳I特別容易在“失敗原因”里寫(xiě)得很詳細(xì)到“建議操作”就含糊起來(lái)。有了模板約束它至少會(huì)寫(xiě)一條可執(zhí)行的下一步動(dòng)作。SKILL.md里必須明確寫(xiě)最終報(bào)告必須按這個(gè)模板生成不能自行調(diào)整結(jié)構(gòu)。不這么寫(xiě)的話(huà)AI會(huì)覺(jué)得模板只是參考信息自己改得更“好”。4.3 references的維護(hù)紀(jì)律少而精隨Skill演進(jìn)references不是知識(shí)庫(kù)不能貪多。模型每次調(diào)用Skill時(shí)只會(huì)讀取SKILL.md中顯式提到的文件。放太多雜七雜八的東西進(jìn)去一方面浪費(fèi)上下文另一方面會(huì)讓AI抓不住重點(diǎn)。我自己定的維護(hù)紀(jì)律有三條每個(gè)Skill的references文件數(shù)量控制在5個(gè)以?xún)?nèi)。文件之間不要有重復(fù)內(nèi)容。如果兩個(gè)文件都對(duì)“覆蓋率閾值”做了定義AI會(huì)困惑以哪個(gè)為準(zhǔn)。每次修改SKILL.md都要檢查references是否需要同步更新。還有一條實(shí)戰(zhàn)建議給references文件加“最后更新日期”和“適用版本”標(biāo)注。這樣當(dāng)AI發(fā)現(xiàn)某個(gè)策略過(guò)時(shí)時(shí)能在報(bào)告中主動(dòng)提示而不是默默按舊標(biāo)準(zhǔn)執(zhí)行。這個(gè)小細(xì)節(jié)能給你爭(zhēng)取很多后續(xù)維護(hù)的主動(dòng)權(quán)。5. 從零聯(lián)調(diào)一個(gè)“測(cè)試Skill”的完整過(guò)程三件套都寫(xiě)完并不意味著Skill已經(jīng)能用了。聯(lián)調(diào)測(cè)試是真正的試金石。很多Skill在紙上看起來(lái)很完美一放到真實(shí)對(duì)話(huà)場(chǎng)景里就露餡要么觸發(fā)不精準(zhǔn)要么工作流程走不通要么腳本在特定環(huán)境下直接崩掉。5.1 標(biāo)準(zhǔn)目錄結(jié)構(gòu)長(zhǎng)什么樣一個(gè)完整可發(fā)布的skill目錄至少要包含以下內(nèi)容auto-test-skill/ ├── SKILL.md ├── scripts/ │ ├── collect_tests.py │ └── run_tests.py └── references/ ├── report_template.md ├── coverage_policy.md └── failure_playbook.md如果你是直接從網(wǎng)上或從模板倉(cāng)庫(kù)clone下來(lái)的Skill第一件事不是急著改SKILL.md而是先確認(rèn)scripts的權(quán)限和可執(zhí)行性。很多Skill不能運(yùn)行純粹是腳本沒(méi)有執(zhí)行權(quán)限或者依賴(lài)沒(méi)有安裝。5.2 三種測(cè)試姿勢(shì)手動(dòng)觸發(fā)、自動(dòng)觸發(fā)、調(diào)試模式我把Skill的測(cè)試分為三種跑法對(duì)應(yīng)不同的驗(yàn)證目標(biāo)。第一種是手動(dòng)觸發(fā)。明確對(duì)AI說(shuō)“使用auto-test-skill檢查當(dāng)前項(xiàng)目的測(cè)試狀態(tài)”。這種跑法用來(lái)驗(yàn)證SKILL.md里的工作流程是否順暢、腳本有沒(méi)有bug、報(bào)告模板是否合理。優(yōu)點(diǎn)是可以快速暴露問(wèn)題缺點(diǎn)是繞過(guò)了“觸發(fā)機(jī)制”無(wú)法驗(yàn)證description寫(xiě)得好不好。第二種是自動(dòng)觸發(fā)。不給AI任何提示直接說(shuō)“我剛改了src/utils下面的代碼你幫我確認(rèn)一下有沒(méi)有引入回歸”。如果AI能自己想起來(lái)加載auto-test-skill說(shuō)明description寫(xiě)得足夠好。如果它選擇自己亂跑命令說(shuō)明觸發(fā)描述還需要優(yōu)化。第三種是調(diào)試模式。開(kāi)發(fā)環(huán)境一般都有Skill調(diào)試開(kāi)關(guān)可以強(qiáng)制讓AI只讀取某個(gè)Skill、忽略其他Skill。當(dāng)你的Skill比較多時(shí)這種隔離測(cè)試很有用。5.3 聯(lián)調(diào)時(shí)的驗(yàn)證清單我每次測(cè)試一個(gè)Skill都會(huì)記錄以下維度的表現(xiàn)而不是只看“最終對(duì)不對(duì)”驗(yàn)證維度具體問(wèn)題我的判斷標(biāo)準(zhǔn)觸發(fā)準(zhǔn)確性該用的時(shí)候是否主動(dòng)用不該用的時(shí)候是否保持沉默10次場(chǎng)景測(cè)試中至少8次觸發(fā)正確流程完整性是否嚴(yán)格按SKILL.md的工作流程走有沒(méi)有跳步除特殊情況外不可跳步腳本健壯性在依賴(lài)缺失、路徑不存在、超時(shí)情況下是否正常報(bào)錯(cuò)必須有明確錯(cuò)誤信息不能直接崩潰輸出穩(wěn)定性同一場(chǎng)景跑3次報(bào)告格式和內(nèi)容是否一致格式必須一致數(shù)據(jù)不能有隨機(jī)差異第四個(gè)維度非常重要。AI本身就帶有隨機(jī)性如果你發(fā)現(xiàn)同一份測(cè)試報(bào)告兩次生成結(jié)果不一樣通常不是隨機(jī)性的問(wèn)題而是SKILL.md的規(guī)則不夠強(qiáng)或者references模板沒(méi)有被嚴(yán)格執(zhí)行。6. 讓Skill長(zhǎng)期可用的迭代紀(jì)律與常見(jiàn)翻車(chē)修復(fù)Skill不是寫(xiě)完就結(jié)束了它跟普通代碼一樣需要持續(xù)維護(hù)。尤其是AI Agent生態(tài)發(fā)展很快工具鏈一變之前精心設(shè)計(jì)的調(diào)用方式可能就失效了。這節(jié)分享一些我踩過(guò)的坑和處理方法。6.1 常見(jiàn)翻車(chē)點(diǎn)與修正方案我整理了五個(gè)出現(xiàn)頻率最高的問(wèn)題基本可以覆蓋90%的Skill翻車(chē)場(chǎng)景?,F(xiàn)象根因修正方案AI從不主動(dòng)調(diào)用Skilldescription里沒(méi)有覆蓋真實(shí)觸發(fā)場(chǎng)景回顧歷史對(duì)話(huà)把用戶(hù)實(shí)際說(shuō)法提煉進(jìn)description調(diào)用了但執(zhí)行流程混亂SKILL.md只給了目標(biāo)沒(méi)給步驟用編號(hào)列表把工作流程寫(xiě)死每一步都有輸出物腳本執(zhí)行報(bào)錯(cuò)、AI不會(huì)處理腳本文檔沒(méi)寫(xiě)清失敗語(yǔ)義和退出碼在SKILL.md里補(bǔ)充每個(gè)退出碼對(duì)應(yīng)的處理動(dòng)作報(bào)告結(jié)構(gòu)每次都不一樣references模板沒(méi)有被強(qiáng)制執(zhí)行SKILL.md中加強(qiáng)“必須按模板輸出”之類(lèi)的強(qiáng)約束語(yǔ)句邊界被突破、亂改文件禁止項(xiàng)列表缺失或太模糊明確列出允許操作和禁止操作用詞要絕對(duì)絕對(duì)化其中第二和第四類(lèi)問(wèn)題值得多說(shuō)兩句。流程混亂的根因往往是SKILL.md把“目標(biāo)”和“步驟”混在一起了。AI看得到“要做出一份測(cè)試報(bào)告”這個(gè)目標(biāo)但看不到“先收集用例、再執(zhí)行、再分析、最后出報(bào)告”的強(qiáng)順序于是它自己發(fā)明了路徑。第四類(lèi)問(wèn)題則要反思references模板某段描述是否有多義性。比如模板里寫(xiě)“按優(yōu)先級(jí)列出建議”但沒(méi)定義什么叫“優(yōu)先級(jí)”AI每次理解的優(yōu)先級(jí)自然不一樣。解決辦法是再加一句“優(yōu)先級(jí)定義為阻塞性高中低”。6.2 用執(zhí)行日志和AI自反饋優(yōu)化Skill迭代Skill最有效的信息來(lái)源是Agent執(zhí)行Skill時(shí)產(chǎn)生的日志。我看日志時(shí)特別關(guān)注三處AI首次讀到SKILL.md的決策路徑、調(diào)用腳本前有沒(méi)有按照模板組織命令、生成報(bào)告時(shí)有沒(méi)有偏離模板。另一個(gè)技巧是在SKILL.md里內(nèi)置“執(zhí)行回顧”環(huán)節(jié)。讓AI完成任務(wù)后額外輸出一段自我回顧本次執(zhí)行有沒(méi)有跳步哪些規(guī)則產(chǎn)生了歧義如果再來(lái)一次會(huì)怎么優(yōu)化流程這些都是真實(shí)的模型視角反饋比你自己猜測(cè)有效得多。6.3 我的迭代節(jié)奏經(jīng)過(guò)幾輪項(xiàng)目實(shí)踐我形成了這樣的迭代節(jié)奏新Skill先在小范圍項(xiàng)目里試用三天期間每天看日志、記錄異常三天后集中優(yōu)化一輪SKILL.md和references之后進(jìn)入穩(wěn)定期每周只花十分鐘看一次使用頻次和不觸發(fā)率。迭代時(shí)嚴(yán)格遵守一個(gè)原則一次只改一個(gè)變量。如果同時(shí)改了SKILL.md和腳本再重新測(cè)試出問(wèn)題時(shí)很難定位是哪個(gè)改動(dòng)導(dǎo)致的。我把這個(gè)原則寫(xiě)進(jìn)了自己的開(kāi)發(fā)規(guī)范里實(shí)測(cè)下來(lái)能節(jié)省大量排查時(shí)間。最后分享兩個(gè)小習(xí)慣。第一每次改完SKILL.md我都會(huì)用同一批測(cè)試場(chǎng)景完整跑一遍再和上一版的結(jié)果對(duì)比防止改了A規(guī)則損壞了B行為。第二給references里的每個(gè)文件加上更新時(shí)間戳這樣AI能感知到資料的新舊你也能在日志里看出哪個(gè)模板已經(jīng)很久沒(méi)人用了。Skill開(kāi)發(fā)本質(zhì)上不是“寫(xiě)一個(gè)文件”而是“設(shè)計(jì)一套讓Agent穩(wěn)定復(fù)現(xiàn)專(zhuān)業(yè)行為的工作系統(tǒng)”。三件套各司其職配合迭代紀(jì)律你的Skill才能真正從演示品變成每天都能用、用了不操心的生產(chǎn)力工具。