戰(zhàn):從混亂工具調(diào)用到可復(fù)用技能庫(kù))
1. “agent-skills”到底在解決什么問(wèn)題我在做 Agent 項(xiàng)目的第三個(gè)月決定把所有的能力模塊全部重寫(xiě)成一套統(tǒng)一的 agent-skills 體系。起因很直接同一個(gè)智能體換了個(gè)業(yè)務(wù)場(chǎng)景之后原來(lái)的提示詞和工具調(diào)用邏輯全亂套了。當(dāng)時(shí)最大的感受是模型本身并不弱真正拖后腿的是我給它的“手和腳”——那些能力邊界模糊、互相耦合、難以單獨(dú)驗(yàn)證的函數(shù)與提示詞片段。這里說(shuō)的 agent-skills不是某個(gè)框架的專有名詞而是我習(xí)慣用的一套工程化組織方式把 Agent 能做的事拆成一個(gè)個(gè)可聲明、可測(cè)試、可復(fù)用的技能模塊每個(gè)技能都有清晰的描述、輸入輸出協(xié)議、實(shí)現(xiàn)邏輯和驗(yàn)證方式。如果你正在開(kāi)發(fā) AI 助手、自動(dòng)化流程、智能客服這類產(chǎn)品或者你發(fā)現(xiàn)自己的 Agent 到了“demo 能跑、上線就崩”的階段那么這篇文章里的思路和踩坑記錄應(yīng)該能幫上忙。1.1 一次事故讓我決定重寫(xiě)技能層事情發(fā)生在給一個(gè)客戶做智能客服機(jī)器人時(shí)。當(dāng)時(shí)為了快速上線我把所有工具調(diào)用邏輯都堆在一個(gè)大文件里意圖判斷靠大段 if-else業(yè)務(wù)規(guī)則散落在各處。最初功能很少跑起來(lái)還算順暢。后來(lái)客戶要求增加節(jié)假日話術(shù)我在某個(gè)工具函數(shù)里改了一行返回值格式結(jié)果導(dǎo)致另一個(gè)不相關(guān)的意圖分支開(kāi)始錯(cuò)誤觸發(fā)線上對(duì)話連續(xù)出現(xiàn)答非所問(wèn)。排查了很久才發(fā)現(xiàn)問(wèn)題根源不是模型而是我把“技能”和“業(yè)務(wù)規(guī)則”焊死在了同一段代碼里。節(jié)假日話術(shù)本質(zhì)上是一個(gè)獨(dú)立的領(lǐng)域能力它應(yīng)該有自己獨(dú)立的入口、參數(shù)和返回結(jié)構(gòu)可以被單獨(dú)替換和測(cè)試。但在當(dāng)時(shí)的架構(gòu)里它和周邊十幾個(gè)功能共用同一個(gè)狀態(tài)機(jī)牽一發(fā)而動(dòng)全身。這次事故之后我把思路調(diào)整為“技能優(yōu)先”凡是 Agent 需要對(duì)外執(zhí)行的動(dòng)作先抽象成技能再通過(guò)技能模塊去組合業(yè)務(wù)規(guī)則。這樣每個(gè)能力像抽屜一樣獨(dú)立存在模型按需抽取工程側(cè)也能針對(duì)單一技能做回歸測(cè)試。聽(tīng)起來(lái)像常識(shí)但真正動(dòng)手做之前我確實(shí)低估了這件事的價(jià)值。1.2 技能模塊解決的三個(gè)真實(shí)痛點(diǎn)第一個(gè)痛點(diǎn)是模型的可理解性。如果你把一堆業(yè)務(wù)邏輯直接寫(xiě)進(jìn)系統(tǒng)提示詞模型需要從長(zhǎng)文本里自己找調(diào)用條件稍微復(fù)雜一點(diǎn)就容易漏。技能模塊則把每個(gè)能力壓縮成一段“能力說(shuō)明書(shū)”模型只需要在候選列表里做匹配理解和選擇的成本都低很多。第二個(gè)痛點(diǎn)是工程的可測(cè)試性。傳統(tǒng)工具函數(shù)可以單測(cè)但 Agent 的工具調(diào)用鏈路很難單測(cè)因?yàn)槟悴恢滥P蜁?huì)在什么上下文里觸發(fā)它。技能模塊通過(guò)標(biāo)準(zhǔn)化輸入輸出和獨(dú)立執(zhí)行邏輯讓測(cè)試變成一個(gè)純粹的函數(shù)驗(yàn)證過(guò)程。先測(cè)技能本身能不能跑再測(cè)模型能不能選對(duì)技能問(wèn)題邊界變得非常清楚。第三個(gè)痛點(diǎn)是能力的可復(fù)用性。同一個(gè)“查詢訂單”技能可以用在客服機(jī)器人、工單助手、企業(yè)微信機(jī)器人里只要描述和協(xié)議不變換場(chǎng)景就是換 Agent 殼。之前我所有的能力都長(zhǎng)在某個(gè)項(xiàng)目里換個(gè)項(xiàng)目就要復(fù)制粘貼改一堆東西現(xiàn)在沉淀成 agent-skills 庫(kù)之后新項(xiàng)目的冷啟動(dòng)速度明顯快了很多。這三件事聽(tīng)起來(lái)不大卻直接影響 Agent 從“能用”到“好用”的關(guān)鍵一步。1.3 什么內(nèi)容才配叫 skill不是所有函數(shù)都值得做成技能。我現(xiàn)在的判斷標(biāo)準(zhǔn)有三個(gè)一是輸入輸出邊界是否清晰二是是否有可預(yù)期的副作用三是能否獨(dú)立驗(yàn)證。比如“查詢訂單狀態(tài)”“計(jì)算運(yùn)費(fèi)”“發(fā)送提醒消息”這類操作邊界明確、結(jié)果可檢驗(yàn)天然適合做成技能。相反有些任務(wù)過(guò)于開(kāi)放比如“寫(xiě)一篇爆款文章”就不適合直接塞成一個(gè)技能。這類任務(wù)需要進(jìn)一步拆解為“生成標(biāo)題候選”“搭建文章大綱”“生成正文段落”等更小的子技能否則描述寫(xiě)不清楚模型也不知道從哪下手。過(guò)早把大而泛的能力固化成技能只會(huì)讓注冊(cè)表變得臃腫還會(huì)增加模型選錯(cuò)技能的幾率。判斷一個(gè)能力能不能沉淀為技能我的經(jīng)驗(yàn)是先在對(duì)話里手工測(cè)試三次如果你每次都需要補(bǔ)充新規(guī)則才能讓它穩(wěn)那就說(shuō)明這個(gè)技能還沒(méi)有收斂繼續(xù)拆。2. 重新拆解 agent-skills一個(gè)技能單元長(zhǎng)什么樣我落地的 agent-skills 體系里一個(gè)完整的技能單元由四部分組成技能描述、輸入輸出協(xié)議、實(shí)現(xiàn)邏輯、自檢測(cè)試。很多人只重視實(shí)現(xiàn)邏輯把技能當(dāng)成普通函數(shù)來(lái)寫(xiě)結(jié)果模型根本不調(diào)用或者調(diào)用了卻傳錯(cuò)參數(shù)。其實(shí)在大模型應(yīng)用里最關(guān)鍵的往往是那幾行“給模型看的描述”。2.1 技能描述給模型看的產(chǎn)品說(shuō)明書(shū)技能描述的目標(biāo)是讓模型在候選列表里一眼認(rèn)出“這個(gè)能力該不該由我來(lái)觸發(fā)”。我寫(xiě)描述的格式基本固定第一句說(shuō)明能力邊界第二句說(shuō)明執(zhí)行前提第三句給出常見(jiàn)參數(shù)示例。最后還會(huì)加一句“什么時(shí)候不要用”用來(lái)減少誤觸發(fā)。舉個(gè)例子一個(gè)查詢天氣的技能我會(huì)寫(xiě)成這樣name: get_weather description: | 查詢指定城市當(dāng)前天氣和未來(lái)三天預(yù)報(bào)。 當(dāng)用戶明確提到天氣、氣溫、降水、風(fēng)力等意圖時(shí)使用。 參數(shù) city 需要是中文城市名盡量從用戶原句中提取。 如果用戶只是在閑聊天氣感受不要調(diào)用本技能。這樣的描述看起來(lái)很短但信息密度很高。模型在做技能選擇時(shí)本質(zhì)上是在做語(yǔ)義匹配它不需要看到你的 Python 類型注解它需要的是“觸發(fā)條件”和“參數(shù)來(lái)源”。我見(jiàn)過(guò)很多團(tuán)隊(duì)把函數(shù)文檔直接復(fù)制成技能描述里面全是技術(shù)術(shù)語(yǔ)模型當(dāng)然容易選錯(cuò)。2.2 輸入輸出協(xié)議一切可以序列化技能和普通函數(shù)的另一個(gè)區(qū)別是它面向的調(diào)用方不是程序員而是模型。模型生成的是結(jié)構(gòu)化文本所以技能輸入輸出必須是可序列化的最好用 JSON Schema 明確約束。我在定義協(xié)議時(shí)會(huì)為每個(gè)技能建立一個(gè)輸入輸出結(jié)構(gòu)例如from typing import TypedDict, Optional class GetWeatherInput(TypedDict): city: str date: Optional[str] # 缺省則為今天 class GetWeatherOutput(TypedDict): status: str # ok 或 error data: Optional[dict] # 天氣詳情 message: str # 給模型看的簡(jiǎn)短說(shuō)明輸出里一定要帶上message。因?yàn)槟P托枰鶕?jù)返回值決定下一步動(dòng)作如果技能只返回一個(gè)裸 dict模型很容易不知道發(fā)生了什么。加上一句“查詢成功北京今天晴最高溫度 30 度”這樣自然的描述模型就能直接理解并轉(zhuǎn)述給用戶。協(xié)議設(shè)計(jì)要盡量扁平避免深層嵌套。模型擅長(zhǎng)生成平面結(jié)構(gòu)復(fù)雜的嵌套對(duì)象容易出現(xiàn)字段缺失或類型錯(cuò)誤。寧可多幾個(gè)頂層字段也不要搞三層以上的對(duì)象。2.3 注冊(cè)與發(fā)現(xiàn)把代碼變?yōu)閿?shù)據(jù)最初的版本里我是用一個(gè)巨大的 if-else 去分發(fā)工具調(diào)用后來(lái)?yè)Q成注冊(cè)表機(jī)制。注冊(cè)表的核心思路是把技能名、技能描述、輸入結(jié)構(gòu)和實(shí)現(xiàn)函數(shù)登記到一個(gè)全局字典里模型只需要看這個(gè)字典的“目錄頁(yè)”就能了解整個(gè) Agent 的能力范圍。我通常用 Python 裝飾器來(lái)做這件事代碼會(huì)清清爽爽SKILL_REGISTRY: dict[str, Skill] {} def skill(func): name func.__name__ SKILL_REGISTRY[name] Skill( namename, descriptionfunc.__doc__.strip(), fnfunc, ) return func skill def get_weather(city: str, date: str ): 查詢指定城市當(dāng)前天氣和未來(lái)三天預(yù)報(bào)。 ...當(dāng)模型需要調(diào)用時(shí)Agent 會(huì)把SKILL_REGISTRY里所有技能名和描述拼成一個(gè)“技能菜單”讓模型從中選擇。這個(gè)過(guò)程中代碼變成了數(shù)據(jù)新增技能不再需要改分發(fā)邏輯只需要寫(xiě)一個(gè)函數(shù)并加上裝飾器。這里有個(gè)容易被忽略的點(diǎn)注冊(cè)順序會(huì)影響模型的選擇概率。如果兩個(gè)技能描述相似通常排在前面的更容易被選中。所以我會(huì)把高頻技能放在前面低頻技能放在后面而不是按字母序排列。3. 實(shí)操?gòu)牧愦罱ㄒ惶卓陕涞氐?skill 庫(kù)理論說(shuō)了一堆接下來(lái)展示一套我實(shí)際在用的技能庫(kù)結(jié)構(gòu)和完整示例。沿著這個(gè)模板你可以很快把現(xiàn)有代碼整理成屬于自己的 agent-skills 庫(kù)。3.1 目錄結(jié)構(gòu)與命名規(guī)范項(xiàng)目根目錄下我會(huì)專門(mén)建一個(gè)skills文件夾每個(gè)技能獨(dú)占一個(gè)子目錄子目錄里放描述文件、實(shí)現(xiàn)文件和測(cè)試文件。skills/ ├── get_weather/ │ ├── skill.yaml │ ├── impl.py │ └── test_impl.py ├── get_exchange_rate/ │ ├── skill.yaml │ ├── impl.py │ └── test_impl.py └── send_email/ ├── skill.yaml ├── impl.py └── test_impl.py技能命名的規(guī)范我用的是“動(dòng)詞 目標(biāo)對(duì)象”比如get_weather、send_email、calculate_delivery_fee。盡量避免使用process_data、handle_request這類模糊名字因?yàn)槟P驮诩寄芷ヅ鋾r(shí)對(duì)名稱很敏感動(dòng)詞越具體召喚成功率越高。skill.yaml存放模型的可見(jiàn)元信息包括技能名、描述、參數(shù)示例和授權(quán)級(jí)別等。impl.py是純實(shí)現(xiàn)邏輯不摻雜任何 Agent 上下文。test_impl.py是單元測(cè)試直接調(diào)用函數(shù)驗(yàn)證結(jié)果。3.2 一個(gè)最小案例匯率查詢技能我們做一個(gè)最簡(jiǎn)單的匯率查詢技能。先寫(xiě)skill.yamlname: get_exchange_rate description: | 查詢實(shí)時(shí)匯率支持常見(jiàn)貨幣之間換算。 當(dāng)用戶提到匯率、換匯、外匯、某貨幣兌某貨幣時(shí)使用。 參數(shù) base 表示基礎(chǔ)貨幣代碼quote 表示目標(biāo)貨幣代碼。 如果用戶未指定目標(biāo)貨幣默認(rèn)使用 CNY。 返回?fù)Q算比例和參考金額。 version: 1.0.0然后寫(xiě)impl.pyfrom typing import TypedDict, Optional class ExchangeRateInput(TypedDict): base: str # 基礎(chǔ)貨幣如 USD quote: str # 目標(biāo)貨幣如 CNY amount: Optional[float] # 金額缺省則返回匯率 class ExchangeRateOutput(TypedDict): status: str rate: Optional[float] converted: Optional[float] message: str def get_exchange_rate(input_data: ExchangeRateInput) - ExchangeRateOutput: base input_data[base].upper() quote input_data.get(quote, CNY).upper() try: rate fetch_rate_from_db(base, quote) except Exception as e: return { status: error, rate: None, converted: None, message: f查詢失敗{e}請(qǐng)檢查貨幣代碼是否輸入正確, } amount input_data.get(amount) converted amount * rate if amount is not None else None if amount is not None: message f{amount} {base} 約等于 {converted:.2f} {quote}當(dāng)前匯率為 {rate} else: message f當(dāng)前 {base}/{quote} 匯率為 {rate} return { status: ok, rate: rate, converted: converted, message: message, }接入 Agent 時(shí)只需要把get_exchange_rate注冊(cè)進(jìn)SKILL_REGISTRY然后把技能菜單交給模型。整個(gè)過(guò)程不需要改業(yè)務(wù)代碼。我第一次重構(gòu)時(shí)最驚訝的就是原來(lái)加一個(gè)新能力可以這么快。3.3 技能自檢與 dry_run實(shí)際運(yùn)行中模型經(jīng)常傳錯(cuò)參數(shù)比如把“人民幣”直接當(dāng)貨幣代碼傳進(jìn)來(lái)或者把日期傳成“明天”。為了減少這類問(wèn)題我在每個(gè)技能里加了一個(gè)輕量自檢邏輯當(dāng)參數(shù)缺省或明顯異常時(shí)返回一個(gè)“提示型錯(cuò)誤”告訴模型應(yīng)該怎么補(bǔ)參數(shù)。我還會(huì)給關(guān)鍵技能增加dry_run模式。這個(gè)模式只做校驗(yàn)和演練不真正產(chǎn)生副作用。比如發(fā)送郵件技能在dry_run下只會(huì)打印“將向某某發(fā)送主題為某某的郵件”不會(huì)真的發(fā)出去。這樣能讓模型在正式生成動(dòng)作前先自檢一遍大幅減少誤操作。dry_run的實(shí)現(xiàn)也簡(jiǎn)單就是給輸入增加一個(gè)test_mode字段處理函數(shù)在開(kāi)頭判斷一下。別小看這個(gè)字段它是我做技能灰度時(shí)最依賴的安全閥。3.4 版本管理與灰度技能不是寫(xiě)一次就不動(dòng)了。業(yè)務(wù)規(guī)則一改技能實(shí)現(xiàn)就要跟著改。但模型的行為需要保持一致所以我給每個(gè)技能加了version字段注冊(cè)表里記錄當(dāng)前請(qǐng)求使用的版本號(hào)。升級(jí)時(shí)先記錄舊版本行為方便回滾?;叶炔呗晕易龅帽容^樸素注冊(cè)表里同時(shí)保留新舊兩個(gè)版本通過(guò)一個(gè)開(kāi)關(guān)分配流量。比如get_exchange_rate從 v1 升到 v2先讓 10% 的請(qǐng)求走到 v2觀察調(diào)用成功率和用戶反饋再逐步放量。這個(gè)方法不花哨但確實(shí)能幫我避免“一次性全量上線然后被模型的新錯(cuò)誤行為淹沒(méi)”的情況。版本管理最需要注意的坑是不要只改描述不改協(xié)議。如果 v2 改了參數(shù)結(jié)構(gòu)一定要在skill.yaml里同步更新否則模型按舊描述生成新參數(shù)技能直接報(bào)錯(cuò)。4. 真正讓 skills 好用的幾個(gè)關(guān)鍵細(xì)節(jié)如果說(shuō)前面是骨架這一節(jié)就是血肉。我自己在把 agent-skills 打磨到能上生產(chǎn)環(huán)境的過(guò)程中積累了幾個(gè)非常實(shí)際的經(jīng)驗(yàn)。4.1 描述里要明確“什么時(shí)候不要用”給技能寫(xiě)描述時(shí)大家很容易只寫(xiě)“什么時(shí)候用”卻忘了寫(xiě)“什么時(shí)候不要用”。在真實(shí)對(duì)話里模型經(jīng)常過(guò)度調(diào)用技能。比如用戶只是抱怨“今天天氣太糟了”并不想查天氣但如果你的天氣技能描述里全是“天氣”“氣溫”等詞模型可能就觸發(fā)查詢。我現(xiàn)在會(huì)在描述末尾固定加一句如果用戶只是在表達(dá)主觀感受不要調(diào)用本技能。這句“負(fù)向提示”對(duì)降低誤觸發(fā)非常有效。同樣地如果一個(gè)技能只能由管理員使用就在描述里寫(xiě)清楚“普通用戶詢問(wèn)權(quán)限相關(guān)問(wèn)題時(shí)不要調(diào)用轉(zhuǎn)交由權(quán)限判斷邏輯處理”。負(fù)向描述不用太長(zhǎng)一兩句話點(diǎn)中常見(jiàn)混淆場(chǎng)景就夠了。寫(xiě)得太多反而會(huì)讓模型困惑。4.2 錯(cuò)誤信息是給模型看的糾錯(cuò)信號(hào)技能里拋異常很容易但模型拿到的只是一個(gè)異常字符串時(shí)往往不知道下一步該做什么。我把錯(cuò)誤信息改成了結(jié)構(gòu)化格式包含狀態(tài)、原因和建議{ status: error, reason: invalid_currency_code, suggestion: 請(qǐng)將貨幣參數(shù)改為國(guó)際標(biāo)準(zhǔn)代碼例如 USD、CNY再重試 }這樣模型看到suggestion后會(huì)自然地對(duì)用戶說(shuō)“請(qǐng)?zhí)峁?biāo)準(zhǔn)貨幣代碼”甚至主動(dòng)修正參數(shù)后重試。我實(shí)測(cè)過(guò)結(jié)構(gòu)化錯(cuò)誤讓技能調(diào)用失敗后的恢復(fù)成功率提高了不少。記住技能返回的錯(cuò)誤也是模型的一次“輸入”你的錯(cuò)誤信息寫(xiě)得越像給同事看的消息模型就越容易接著干活。4.3 控制返回體量與敏感信息Agent 的上下文窗口是有限的。如果技能返回一大段完整訂單明細(xì)、幾十條搜索結(jié)果模型還沒(méi)開(kāi)始推理上下文就已經(jīng)被撐爆了。我的原則是技能返回給模型的內(nèi)容只保留“決策所需的最小信息量”詳細(xì)信息寫(xiě)入外部存儲(chǔ)需要時(shí)再按消息 ID 拉取。舉個(gè)例子查詢訂單列表時(shí)不要在返回值里塞完整的商品詳情和物流軌跡只返回訂單號(hào)、狀態(tài)、金額、時(shí)間這幾個(gè)字段就夠了。如果用戶追問(wèn)詳情再通過(guò)另一個(gè)“查詢訂單詳情”技能去取。這種拆分不僅省 token還讓每個(gè)技能的鏈路更短、更容易排查。敏感信息方面技能輸出里絕不能帶明文密碼、完整身份證號(hào)、銀行卡號(hào)等。我在輸出層做了一層脫敏比如只返回尾號(hào)四位。防的不只是模型還有日志系統(tǒng)和下游服務(wù)。任何時(shí)候?qū)徲?jì)日志里都不該出現(xiàn)用戶敏感字段。4.4 冪等性與并發(fā)安全多個(gè)技能被并行調(diào)用時(shí)很容易出現(xiàn)重復(fù)副作用。最典型的是“支付”或“發(fā)消息”這類操作模型判斷失誤重試兩次用戶就收到兩條消息。所以我在技能設(shè)計(jì)里強(qiáng)制要求凡是有副作用的技能必須支持冪等。冪等的做法很簡(jiǎn)單給每次調(diào)用生成一個(gè)request_id服務(wù)端記錄這個(gè) id 是否已經(jīng)處理過(guò)。如果重復(fù)提交同一個(gè)request_id直接返回上一次的結(jié)果不再次執(zhí)行副作用。同時(shí)技能內(nèi)部盡量保持無(wú)狀態(tài)不要依賴全局變量避免并發(fā)時(shí)數(shù)據(jù)互相污染。這個(gè)設(shè)計(jì)在單機(jī) demo 里看不出來(lái)一旦技能被多個(gè) Agent 實(shí)例共享或者被用戶手動(dòng)觸發(fā)和模型觸發(fā)同時(shí)調(diào)用冪等就是保命符。5. 常見(jiàn)問(wèn)題與踩坑實(shí)錄再正確的理論落到實(shí)戰(zhàn)里都會(huì)有一堆意想不到的問(wèn)題。這里記錄幾個(gè)我反復(fù)遇到的坑以及對(duì)應(yīng)的排查方法。5.1 模型不調(diào)用技能時(shí)先別急著調(diào) prompt模型完全無(wú)視技能菜單是最常見(jiàn)的問(wèn)題。很多人第一反應(yīng)是加長(zhǎng)系統(tǒng)提示詞結(jié)果越加越亂。我現(xiàn)在的排查順序是先看技能描述是否出現(xiàn)在模型上下文中再看描述里的關(guān)鍵詞是否和用戶表達(dá)有明顯匹配最后才考慮調(diào)整 prompt。如果用戶說(shuō)“幫我查下美元兌人民幣”技能描述里卻沒(méi)有“美元”“人民幣”這些具體詞模型就很難觸發(fā)。解決方法是把常見(jiàn)說(shuō)法作為示例寫(xiě)進(jìn)描述里比如支持 USD/CNY、EUR/CNY 等常見(jiàn)貨幣對(duì)。這不是讓模型死記硬背而是給它更容易匹配的錨點(diǎn)。另一個(gè)容易被忽略的原因是技能菜單太長(zhǎng)。當(dāng)候選技能超過(guò)十幾個(gè)時(shí)模型可能遺漏靠后的技能。我會(huì)把高頻技能排在前面并且為同一類能力做一個(gè)“分組描述”減少候選數(shù)量。5.2 技能明明存在卻選錯(cuò)了技能選錯(cuò)技能比不調(diào)用更隱蔽。我遇到過(guò)兩個(gè)技能描述高度相似一個(gè)是“查詢訂單”另一個(gè)是“查詢售后單”模型總是把售后單查詢請(qǐng)求派給訂單查詢。后來(lái)我在兩個(gè)描述里分別加入了“如果不確定是哪個(gè)先問(wèn)用戶是否有售后糾紛”效果立竿見(jiàn)影。還有一個(gè)技巧是給每個(gè)技能寫(xiě)一個(gè)“反例”字段比如not_to_use: 當(dāng)用戶提到退貨、換貨、維修時(shí)請(qǐng)選擇 query_after_sale。這種顯式的互斥指引比單純加形容詞有用得多。要徹底排查我會(huì)維護(hù)一個(gè)技能評(píng)測(cè)集每個(gè)評(píng)測(cè)樣本包含“用戶話術(shù)”和“期望技能名”。每次改動(dòng)描述后跑一遍看準(zhǔn)確率和召回率變化。沒(méi)有評(píng)測(cè)集你根本不知道哪次描述改動(dòng)是變好還是變壞。5.3 技能返回內(nèi)容撐爆上下文早期我做一個(gè)搜索類技能直接把前幾十條搜索結(jié)果全部返回模型還沒(méi)來(lái)得及總結(jié)上下文就已經(jīng)爆了。后來(lái)我改用“分頁(yè)摘要”策略技能只返回前 5 條結(jié)果的核心標(biāo)題和摘要如果用戶要更多再通過(guò)參數(shù)page翻頁(yè)。這樣既控制了 token又讓模型每一步只聚焦一小批信息。還要注意返回值里的“冗余信息”。有些技能實(shí)現(xiàn)者圖省事把整個(gè)數(shù)據(jù)庫(kù)行原樣返回里面全是創(chuàng)建時(shí)間、更新時(shí)間、內(nèi)部 ID。這些字段對(duì)模型決策沒(méi)有幫助只會(huì)稀釋注意力。我在輸出層做白名單字段明確哪些可以出站。5.4 問(wèn)題排查速查表癥狀可能原因處理方式模型從不調(diào)用某技能描述關(guān)鍵詞不匹配、技能排序太后補(bǔ)充用戶常見(jiàn)說(shuō)法調(diào)整注冊(cè)順序調(diào)用技能但參數(shù)頻繁錯(cuò)誤輸入?yún)f(xié)議定義過(guò)寬缺少示例在描述中增加參數(shù)格式示例多個(gè)技能經(jīng)?;煜枋鱿嗨贫雀呷鄙倩コ庹f(shuō)明加反例字段明確觸發(fā)邊界技能返回內(nèi)容太長(zhǎng)未做摘要和字段白名單只返回決策所需最小字段升級(jí)后行為變化大描述或協(xié)議未同步更新版本號(hào)分離灰度放量重復(fù)執(zhí)行副作用操作技能非冪等增加 request_id 去重這張表是我每次上線前都會(huì)過(guò)一遍的基礎(chǔ)檢查清單能幫我快速定位八層以上的問(wèn)題。6. 落地 agent-skills 一年后的個(gè)人體會(huì)6.1 技能庫(kù)需要“新陳代謝”技能庫(kù)不能只增不減。我在維護(hù)了大半年后發(fā)現(xiàn)很多早期技能已經(jīng)沒(méi)人調(diào)用但還在注冊(cè)表里占著位置每次模型選擇時(shí)都會(huì)浪費(fèi)注意力。后來(lái)我加了一個(gè)“調(diào)用日志”統(tǒng)計(jì)每個(gè)月清理一次近 30 天調(diào)用次數(shù)為零的技能。不是直接刪而是先標(biāo)記為deprecated下線再刪代碼。這個(gè)過(guò)程讓我意識(shí)到agent-skills 不是一個(gè)靜態(tài)的目錄它更像代碼庫(kù)本身需要持續(xù)的 review 和重構(gòu)。給技能寫(xiě)描述時(shí)我心里會(huì)有個(gè)標(biāo)準(zhǔn)如果一個(gè)新同事不看實(shí)現(xiàn)代碼只看skill.yaml能完全理解這個(gè)技能的能力邊界那才算合格。達(dá)不到標(biāo)準(zhǔn)的描述一律重寫(xiě)。6.2 下一步可以從評(píng)測(cè)與觀測(cè)入手如果你已經(jīng)搭好了一套技能庫(kù)我建議下一步把重心放在“可觀測(cè)性”上。每次技能調(diào)用都記錄下選技結(jié)果、參數(shù)、耗時(shí)、返回狀態(tài)然后定期統(tǒng)計(jì)調(diào)準(zhǔn)率。我后來(lái)用這些數(shù)據(jù)做過(guò)一次很有效的優(yōu)化發(fā)現(xiàn)某個(gè)技能雖然經(jīng)常被選中但執(zhí)行成功率只有六成原因是它的輸入?yún)f(xié)議和描述之間存在兩張皮模型按描述生成參數(shù)函數(shù)卻按更嚴(yán)格的協(xié)議校驗(yàn)。改掉這個(gè)不一致后整體成功率立刻回升。最后再分享一個(gè)小技巧新增技能之前先問(wèn)自己三個(gè)問(wèn)題——這個(gè)能力可以被一句話說(shuō)明嗎它的輸入輸出可以被結(jié)構(gòu)化嗎它值得被獨(dú)立測(cè)試和復(fù)用嗎三個(gè)問(wèn)題都回答“是”再做。少建一個(gè)模糊技能比多寫(xiě)一個(gè)完美技能更重要。這套思路陪我走過(guò)幾個(gè)項(xiàng)目也希望幫你少踩一些坑。