量測(cè)試 Skill 編寫手冊(cè):用漸進(jìn)式披露拆解 SKILL.md 結(jié)構(gòu))
1. 為什么你的 SKILL.md 越寫越臃腫Agent 反而越用越笨如果你正在給 Agent 寫測(cè)試類 Skill大概率踩過這個(gè)坑一開始 SKILL.md 只有幾十行寫著寫著變成幾百行最后連自己都不敢改。每次 Agent 執(zhí)行任務(wù)都要把整份文件塞進(jìn)上下文結(jié)果模型開始走神——明明規(guī)則里寫了要用基類它偏要自己造一個(gè)明明指定了參考文件它當(dāng)沒看見。這不是模型不行而是上下文被污染了。Transformer 的注意力機(jī)制在長(zhǎng)上下文里會(huì)稀釋關(guān)鍵信息你塞進(jìn)去的每一條無關(guān)規(guī)則都在搶真正重要規(guī)則的權(quán)重。測(cè)試場(chǎng)景尤其明顯權(quán)限測(cè)試、計(jì)費(fèi)測(cè)試、模型廣場(chǎng)測(cè)試的寫法差異很大如果全寫在一個(gè)文件里模型很容易把 A 模塊的寫法套到 B 模塊上。這篇要解決的就是這個(gè)問題。我會(huì)給你一套可復(fù)制的 SKILL.md 目錄骨架用漸進(jìn)式披露把知識(shí)分成三層再配上自動(dòng)化測(cè)試腳本驗(yàn)證技能加載順序和命中率。適合正在做 Agent 測(cè)試工程、被 Skill 文件維護(hù)成本折磨的同學(xué)。整套思路我在接口自動(dòng)化測(cè)試項(xiàng)目里跑過下面直接上結(jié)構(gòu)。2. 漸進(jìn)式披露把知識(shí)拆成三層讓 Agent 按需加載漸進(jìn)式披露的核心就一句話不要把全部規(guī)則一次性交給模型只在必要的時(shí)候加載對(duì)應(yīng)的知識(shí)。落到文件結(jié)構(gòu)上就是三層分離。第一層是 SKILL.md 本身只放工作流和跨模塊的公共知識(shí)。它像一個(gè)調(diào)度中心告訴 Agent 先做什么、再做什么、什么時(shí)候去讀哪個(gè)文件。第二層是references/目錄每個(gè)功能域一個(gè)文件。權(quán)限測(cè)試讀auth.md計(jì)費(fèi)測(cè)試讀billing.md互不干擾。這些文件里放的是該領(lǐng)域?qū)S玫幕?、Service、API 調(diào)用模式。第三層是具體用例目錄下的.rules文件和已有測(cè)試用例。Agent 在寫新用例前先讀同目錄的規(guī)則文件和 1-2 個(gè)最相近的已有用例學(xué)習(xí)命名風(fēng)格、導(dǎo)入方式、步驟寫法。這樣做的收益很直接單次加載的 token 量下降模型注意力集中在當(dāng)前任務(wù)相關(guān)的知識(shí)上一次通過率明顯提升。維護(hù)也簡(jiǎn)單——改權(quán)限邏輯只動(dòng)auth.md不會(huì)波及計(jì)費(fèi)模塊。3. 前置準(zhǔn)備TaoToken 接入與模型選擇在寫 SKILL.md 之前先把執(zhí)行環(huán)境搭好。Agent 跑測(cè)試 Skill 需要一個(gè)穩(wěn)定的模型入口我用的是 TaoToken 的 API 網(wǎng)關(guān)它兼容 OpenAI 和 Anthropic 的接口格式切換模型不用改代碼。先去控制臺(tái)創(chuàng)建 API Keyhttps://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentskill_progressive_disclosure創(chuàng)建完在 API Keys 頁(yè)面復(fù)制密鑰注意別提交到 Git 倉(cāng)庫(kù)https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentskill_progressive_disclosure模型選擇上測(cè)試 Skill 涉及代碼生成和規(guī)則遵循建議用長(zhǎng)上下文能力強(qiáng)的模型。如果你要長(zhǎng)期跑編碼類 Agent 任務(wù)Coding Plan 比按量計(jì)費(fèi)更劃算https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentskill_progressive_disclosure接入文檔在這里包含各語(yǔ)言的 SDK 示例https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentskill_progressive_disclosureAPI 基礎(chǔ)地址統(tǒng)一用https://taotoken.net/api不帶任何參數(shù)。下面配置環(huán)境變量export TAOTOKEN_API_KEYsk-你的密鑰 export TAOTOKEN_BASE_URLhttps://taotoken.net/apiPython 里驗(yàn)證一下連通性import os from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], ) resp client.chat.completions.create( modelclaude-sonnet-4-5, messages[{role: user, content: 回復(fù) OK 兩個(gè)字母}], ) print(resp.choices[0].message.content)返回OK就說明鏈路通了。這一步別跳過后面自動(dòng)化測(cè)試腳本依賴這個(gè)環(huán)境。4. 可復(fù)制的 SKILL.md 目錄骨架與分層配置先看完整目錄結(jié)構(gòu)這是整套方案的地基skills/ └── api-test-writer/ ├── SKILL.md ├── references/ │ ├── auth.md │ ├── billing.md │ ├── prompt-tpl.md │ ├── model-market.md │ └── multi-agent.md └── cases/ ├── platform_management/ │ ├── auth/ │ │ ├── .rules │ │ └── test_workspace_permission.py │ └── price/ │ ├── .rules │ └── test_billing_flow.py └── prompt_templates/ ├── .rules └── test_prompt_crud.pySKILL.md 的開頭部分定義工作流強(qiáng)制 Agent 按順序執(zhí)行# 自動(dòng)化測(cè)試用例編寫 - 公共知識(shí)庫(kù) ## 工作流必須嚴(yán)格按順序執(zhí)行 ### Step 1閱讀規(guī)則 1. 閱讀本文件獲取公共模塊知識(shí) 2. 根據(jù)用例所屬功能域讀取 references/ 下對(duì)應(yīng)的參考文件 3. 讀取用例目標(biāo)目錄下的 .rules 文件 ### Step 2參考已有用例 1. 在目標(biāo)目錄下找 1-2 個(gè)功能最相近的已有用例 2. 閱讀其基類、導(dǎo)入、命名、步驟風(fēng)格 3. 新用例風(fēng)格必須與同目錄已有用例保持一致 ### 分層參考文件索引 | 功能域 | 參考文件 | 對(duì)應(yīng)用例路徑 | |--------|---------|------------| | 權(quán)限測(cè)試 | references/auth.md | cases/platform_management/auth/ | | 計(jì)費(fèi)測(cè)試 | references/billing.md | cases/platform_management/price/ | | 提示詞模板 | references/prompt-tpl.md | cases/prompt_templates/ | | 模型廣場(chǎng) | references/model-market.md | cases/model_marketplace/ | | 多Agent模型 | references/multi-agent.md | cases/app_dev/multi_agent_model/ |references/auth.md里放權(quán)限模塊的專用知識(shí)比如三種授權(quán)方式的 API 差異from lib.lke_api.platform_management.auth.auth_api import AuthAPI from cases.platform_management.auth.permissions import AppPermissions # 用戶直接授權(quán) res AuthAPI.SetUserResourcePermissions( SpaceIdself.workspace_id, AccountUinself.sub_uin, PermissionsAppPermissions.adpAPP_no_permission, ResourceIds[*], ResourceTypeapp, ) if Error in res[Response]: raise Exception(f設(shè)置子賬號(hào)權(quán)限失敗. {res}) # 組織授權(quán)SubjectType1 表示組織 res AuthAPI.SetSubjectResourcePermissions( SpaceIdself.workspace_id, SubjectIdself.dept_id, SubjectType1, PermissionsAppPermissions.adpAPP_view, ResourceIds[*], ResourceTypeapp, ) time.sleep(40) # 等待權(quán)限生效注意time.sleep(40)這種細(xì)節(jié)必須寫在 references 里而不是 SKILL.md。因?yàn)橹挥袡?quán)限測(cè)試才需要等這么久計(jì)費(fèi)測(cè)試可能只需要 5 秒。這就是分層披露的價(jià)值——把領(lǐng)域特有的坑隔離在對(duì)應(yīng)文件里。.rules文件則記錄更細(xì)粒度的約束比如某個(gè)目錄下所有用例必須繼承BaseAuthCase斷言必須用self.assert_permission而不是原生 assert。5. 自動(dòng)化測(cè)試驗(yàn)證加載順序與命中率骨架搭好了怎么確認(rèn) Agent 真的按預(yù)期加載了正確的文件靠人眼看輸出不靠譜寫個(gè)自動(dòng)化測(cè)試腳本。思路是給 Agent 一個(gè)測(cè)試任務(wù)攔截它讀取文件的調(diào)用記錄加載順序然后斷言關(guān)鍵文件是否被命中。import json import re from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], ) SKILL_ROOT skills/api-test-writer def build_system_prompt(): with open(f{SKILL_ROOT}/SKILL.md, encodingutf-8) as f: return f.read() def extract_file_reads(text): 從模型輸出中提取它聲明要讀取的文件路徑 pattern r(?:讀取|read|load)\s*[\]?([\w/\.\-]\.(?:md|rules|py)) return re.findall(pattern, text, flagsre.IGNORECASE) def run_case(task_desc, expected_files): resp client.chat.completions.create( modelclaude-sonnet-4-5, messages[ {role: system, content: build_system_prompt()}, {role: user, content: task_desc}, ], temperature0, ) output resp.choices[0].message.content reads extract_file_reads(output) hit [f for f in expected_files if any(f in r for r in reads)] miss [f for f in expected_files if f not in hit] rate len(hit) / len(expected_files) print(f任務(wù): {task_desc[:40]}...) print(f命中: {hit}) print(f遺漏: {miss}) print(f命中率: {rate:.0%}) return rate # 測(cè)試用例權(quán)限測(cè)試應(yīng)命中 auth.md 和對(duì)應(yīng) .rules rate run_case( 為權(quán)限模塊編寫一個(gè)新測(cè)試用例驗(yàn)證角色授權(quán)后成員繼承權(quán)限, [references/auth.md, platform_management/auth/.rules], ) assert rate 0.8, f命中率過低: {rate}跑幾次下來如果命中率低于 80%說明 SKILL.md 里的索引表描述不夠明確或者工作流步驟的措辭讓模型產(chǎn)生了歧義。我試過把根據(jù)用例所屬功能域改成根據(jù)用例存放路徑匹配下表命中率從 60% 提到了 95%。加載順序也要驗(yàn)證。正確的順序是 SKILL.md → references → .rules → 已有用例。如果模型先讀用例再讀規(guī)則說明工作流的強(qiáng)制力不夠可以在 Step 1 里加一句在讀取任何用例文件之前必須先完成規(guī)則文件的讀取。6. 常見報(bào)錯(cuò)與排查清單報(bào)錯(cuò)一模型跳過了 references 直接寫代碼。癥狀是輸出里沒有文件讀取聲明直接開始生成。原因通常是 SKILL.md 的工作流用了建議可以這類軟措辭。改成必須嚴(yán)格按順序后基本能解決。如果還不行在系統(tǒng)提示末尾追加一句未讀取 references 就生成代碼視為任務(wù)失敗。報(bào)錯(cuò)二命中率忽高忽低。檢查索引表的路徑是否和實(shí)際目錄完全一致。大小寫、下劃線、復(fù)數(shù)形式都可能導(dǎo)致匹配失敗。建議用腳本掃描一遍目錄自動(dòng)生成索引表避免手寫筆誤。報(bào)錯(cuò)三.rules文件被讀取但內(nèi)容沒生效。這通常是.rules文件本身太長(zhǎng)或者規(guī)則之間互相矛盾。.rules控制在 30 行以內(nèi)只放該目錄特有的約束公共規(guī)則上提到 SKILL.md。報(bào)錯(cuò)四API 返回 401 或 403。檢查TAOTOKEN_API_KEY是否有多余空格以及 base_url 是否誤加了路徑后綴。正確寫法是https://taotoken.net/api不要寫成/api/v1。報(bào)錯(cuò)五模型輸出被截?cái)?。長(zhǎng)上下文任務(wù)容易觸發(fā) max_tokens 限制。在請(qǐng)求里顯式設(shè)置max_tokens8192或者把任務(wù)拆成先讀規(guī)則、再寫用例兩輪對(duì)話。排查時(shí)建議開temperature0排除隨機(jī)性干擾。等結(jié)構(gòu)穩(wěn)定了再調(diào)高溫度做多樣性測(cè)試。7. 下一步把驗(yàn)證腳本接進(jìn) CI骨架和測(cè)試腳本都有了接下來把它接進(jìn) CI 流程。每次修改 SKILL.md 或 references 后自動(dòng)跑一遍命中率測(cè)試低于閾值就阻斷合并。這樣技能文件的質(zhì)量就有了可量化的保障而不是靠感覺好像變好了。如果你還在選模型階段可以先用模型對(duì)話頁(yè)面手動(dòng)驗(yàn)證幾輪確認(rèn)工作流描述沒有歧義https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentskill_progressive_disclosure長(zhǎng)期跑編碼類 Agent 任務(wù)的話Coding Plan 的額度模型更適合高頻調(diào)用場(chǎng)景。接入細(xì)節(jié)參考官方文檔里面有完整的 SDK 示例和錯(cuò)誤碼說明。整套方案的核心就一句讓 Agent 只讀它當(dāng)下需要的知識(shí)剩下的交給目錄結(jié)構(gòu)去管理。