實(shí)戰(zhàn):Skill與Tool的本質(zhì)差異及技能庫(kù)自演進(jìn)與動(dòng)態(tài)加載)
1. 從一次翻車說起為什么我要把 Skill 和 Tool 拆開看去年冬天我接了個(gè)私活幫一家做跨境電商的朋友搭一套自動(dòng)處理售后郵件的 Agent。需求聽起來不復(fù)雜讀郵件、判斷意圖、查訂單、生成回復(fù)、必要時(shí)轉(zhuǎn)人工。我當(dāng)時(shí)的思路很直接——給 Agent 掛一堆 Tool 就完事了。查訂單一個(gè) Tool發(fā)郵件一個(gè) Tool查物流一個(gè) Tool退款一個(gè) Tool湊了十來個(gè)跑起來看著挺熱鬧。結(jié)果上線第三天就出事了。客戶投訴說 Agent 把一封我要退貨的郵件回復(fù)成了您的退款已到賬。我翻日志查了半天發(fā)現(xiàn)是模型在某個(gè)環(huán)節(jié)把查詢訂單狀態(tài)這個(gè) Tool 的返回結(jié)果誤當(dāng)成了執(zhí)行退款的確認(rèn)信號(hào)。兩個(gè) Tool 的語(yǔ)義邊界太模糊模型在長(zhǎng)上下文里串了臺(tái)。更麻煩的是我想修這個(gè)問題得改 Tool 的描述、改 prompt、改調(diào)用邏輯改完還得重新測(cè)一遍所有場(chǎng)景因?yàn)?Tool 之間是耦合的。那次之后我開始認(rèn)真琢磨一件事Agent 的能力到底該怎么組織把所有能力都塞進(jìn) Tool 里是不是從一開始方向就偏了后來接觸到 Skill 這個(gè)概念尤其是看到 Claude Code、Codex 這類工具里 Skill 的用法我才慢慢理清楚——Skill 和 Tool 根本不是一回事它們解決的是兩個(gè)層面的問題。這篇就把我這大半年踩坑、試錯(cuò)、重構(gòu)的經(jīng)驗(yàn)完整寫出來從概念差異講到技能庫(kù)的自演進(jìn)和動(dòng)態(tài)加載盡量把每個(gè)為什么都講透。如果你正在做 Agent 開發(fā)或者正準(zhǔn)備給自己的 Agent 加能力這篇應(yīng)該能幫你少走不少?gòu)澛贰?. Skill 與 Tool 的本質(zhì)差異不是命名游戲是架構(gòu)分層2.1 先給結(jié)論Tool 是手Skill 是手藝我用一個(gè)生活化的類比來解釋這兩者的區(qū)別。你去餐廳吃飯Tool 就像廚房里的工具——菜刀、炒鍋、烤箱、打蛋器。每一件工具功能單一、邊界清晰菜刀就是切東西的烤箱就是加熱的。而Skill 是一道菜的完整做法——紅燒肉這個(gè)技能包含了選肉、焯水、炒糖色、燉煮、收汁一整套流程過程中會(huì)用到菜刀、炒鍋、灶臺(tái)這些工具但技能本身不等于工具。放到 Agent 語(yǔ)境里Tool是原子化的外部能力接口通常對(duì)應(yīng)一次函數(shù)調(diào)用或一次 API 請(qǐng)求。它的特征是無狀態(tài)、輸入輸出明確、可獨(dú)立測(cè)試。比如search_web(query)、read_file(path)、send_email(to, subject, body)。Skill是面向目標(biāo)的能力封裝它描述在什么場(chǎng)景下、按什么步驟、調(diào)用哪些 Tool、遵循什么約束、產(chǎn)出什么結(jié)果。它是有狀態(tài)、有流程、有領(lǐng)域知識(shí)的。這個(gè)區(qū)別聽起來抽象但落到代碼上非常具體。我拿自己重構(gòu)前后的對(duì)比給你看。重構(gòu)前我把處理退款直接寫成一個(gè) Tool# 反例把業(yè)務(wù)流程塞進(jìn) Tool def process_refund(order_id: str, reason: str) - dict: order query_order(order_id) if order[status] ! paid: return {error: 訂單狀態(tài)不允許退款} if order[amount] 500: # 大額需要人工審核 create_ticket(order_id, refund_review) return {status: pending_review} refund call_payment_api(order_id, order[amount]) send_email(order[email], 退款成功, f您的退款 {order[amount]} 元已到賬) return {status: success, refund_id: refund[id]}這段代碼能跑但問題一大堆。首先業(yè)務(wù)規(guī)則500 元閾值、狀態(tài)校驗(yàn)硬編碼在 Tool 里改規(guī)則要改代碼、要重新部署。其次這個(gè) Tool 內(nèi)部調(diào)了四個(gè)其他能力任何一個(gè)出錯(cuò)都很難定位。最關(guān)鍵的是模型根本不知道這個(gè) Tool 內(nèi)部發(fā)生了什么它只能看到輸入和輸出一旦輸出不符合預(yù)期模型沒有任何調(diào)整空間。重構(gòu)后我把退款處理變成一個(gè) SkillTool 只保留原子能力# 正例Tool 只做原子操作 tools [ query_order, # 查訂單 check_order_status, # 查狀態(tài) call_payment_api, # 調(diào)支付 create_ticket, # 建工單 send_email, # 發(fā)郵件 ]而 Skill 用一份聲明式的描述來定義流程# skill: refund_processing name: refund_processing description: 處理客戶退款請(qǐng)求包含狀態(tài)校驗(yàn)、金額判斷、審核分流 triggers: - 客戶要求退款 - 訂單退款 steps: - action: query_order input: { order_id: {{context.order_id}} } - action: check_order_status condition: order.status paid on_fail: 回復(fù)客戶當(dāng)前訂單狀態(tài)不支持退款 - action: branch condition: order.amount 500 then: - action: create_ticket input: { type: refund_review } - action: send_email input: { template: refund_pending } else: - action: call_payment_api - action: send_email input: { template: refund_success } constraints: - 退款金額不得超過訂單實(shí)付金額 - 同一訂單 24 小時(shí)內(nèi)只能發(fā)起一次退款你看同樣的業(yè)務(wù)拆開之后清晰多了。Tool 負(fù)責(zé)能做什么Skill 負(fù)責(zé)該怎么做。這個(gè)分層帶來的好處我在后面幾節(jié)會(huì)逐個(gè)展開。2.2 為什么這個(gè)區(qū)分在長(zhǎng)上下文里特別重要很多人會(huì)問我直接把流程寫進(jìn) prompt 不就行了何必搞個(gè) Skill 層這個(gè)問題我一開始也糾結(jié)過。答案是prompt 里的流程是軟約束Skill 是硬約束。在短對(duì)話里prompt 寫清楚流程確實(shí)夠用。但 Agent 一旦跑長(zhǎng)任務(wù)上下文動(dòng)輒幾萬 token模型對(duì) prompt 里中段內(nèi)容的注意力會(huì)明顯衰減——這就是業(yè)內(nèi)常說的lost in the middle現(xiàn)象。你把退款流程寫在系統(tǒng) prompt 的第 3000 字位置跑到第 20 輪對(duì)話時(shí)模型很可能已經(jīng)忘了那個(gè) 500 元閾值。Skill 的價(jià)值在于它把流程從常駐上下文變成了按需加載。模型不需要一直記著退款流程只有當(dāng)它判斷當(dāng)前任務(wù)需要退款技能時(shí)才把這個(gè) Skill 的描述加載進(jìn)來。這樣既省 token又保證了流程約束在需要時(shí)是新鮮的、高權(quán)重的。我實(shí)測(cè)過一個(gè)對(duì)比同樣一個(gè)包含 8 個(gè)步驟的復(fù)雜任務(wù)把流程寫死在 system prompt 里任務(wù)成功率大概 62%改成 Skill 動(dòng)態(tài)加載后成功率提到 89%。差距主要來自長(zhǎng)任務(wù)后半段——寫死的那版模型經(jīng)常漏掉中間步驟。2.3 一張表看清兩者的邊界維度ToolSkill粒度原子操作面向目標(biāo)的流程狀態(tài)無狀態(tài)有狀態(tài)、有上下文復(fù)用方式直接調(diào)用按場(chǎng)景加載變更成本改代碼、重部署改描述、熱更新對(duì)模型的作用擴(kuò)展手?jǐn)U展手藝典型例子查數(shù)據(jù)庫(kù)、發(fā)請(qǐng)求處理退款、寫周報(bào)測(cè)試方式單元測(cè)試場(chǎng)景回歸測(cè)試這張表是我自己總結(jié)的不一定權(quán)威但基本覆蓋了日常開發(fā)里最需要區(qū)分的幾個(gè)點(diǎn)。記住一句話Tool 是能力Skill 是能力的使用說明書。3. 技能庫(kù)的自演進(jìn)讓 Agent 自己長(zhǎng)出新手藝3.1 什么是自演進(jìn)為什么需要它技能庫(kù)的自演進(jìn)說白了就是Agent 在使用過程中能自己沉淀新 Skill、優(yōu)化舊 Skill。這個(gè)概念聽起來有點(diǎn)玄但邏輯很樸素你不可能提前把所有場(chǎng)景都想到與其等用戶反饋再手動(dòng)加 Skill不如讓 Agent 在遇到新場(chǎng)景時(shí)把成功的處理路徑固化下來。我舉個(gè)真實(shí)例子。我那個(gè)跨境電商 Agent 上線后遇到一類我沒預(yù)料到的場(chǎng)景客戶問我的包裹為什么還沒到是不是丟了。這既不是退款也不是查物流那么簡(jiǎn)單它需要先查物流、判斷是否超時(shí)、如果超時(shí)則安撫并給補(bǔ)償券、如果沒超時(shí)則解釋預(yù)計(jì)到達(dá)時(shí)間。我一開始沒這個(gè) SkillAgent 處理得很亂。后來我加了一個(gè)機(jī)制當(dāng) Agent 用一組 Tool 調(diào)用成功解決了一個(gè)之前沒見過的任務(wù)類型時(shí)把這條調(diào)用鏈抽象成一個(gè)候選 Skill存進(jìn)技能庫(kù)。下次遇到類似任務(wù)直接加載這個(gè) Skill。這就是最基礎(chǔ)的自演進(jìn)。3.2 自演進(jìn)的三個(gè)層次我把自演進(jìn)分成三個(gè)層次從易到難第一層技能沉淀。把成功的 Tool 調(diào)用序列抽象成 Skill。這是最基礎(chǔ)的實(shí)現(xiàn)難度低收益明顯。核心是判斷什么算成功——通常用任務(wù)完成信號(hào)、用戶滿意度、無報(bào)錯(cuò)這三個(gè)指標(biāo)綜合判斷。第二層技能優(yōu)化。已有 Skill 在執(zhí)行中如果頻繁失敗或效率低自動(dòng)調(diào)整步驟順序、替換 Tool、修改約束。比如某個(gè) Skill 里先查 A 再查 B但統(tǒng)計(jì)發(fā)現(xiàn) 80% 的情況 B 的結(jié)果能直接推出 A那就把順序反過來省一次調(diào)用。第三層技能組合。把多個(gè)小 Skill 組合成大 Skill或者把一個(gè)大 Skill 拆成可復(fù)用的子 Skill。這一層最難因?yàn)樯婕凹寄艿某橄蠛头夯菀走^度擬合。我目前的生產(chǎn)環(huán)境只做到第一層加部分第二層第三層還在實(shí)驗(yàn)。下面重點(diǎn)講前兩層怎么落地。3.3 技能沉淀的具體實(shí)現(xiàn)技能沉淀的核心是軌跡抽象。Agent 每完成一個(gè)任務(wù)都會(huì)留下一條執(zhí)行軌跡trace包含用戶輸入、模型思考、Tool 調(diào)用序列、每步結(jié)果、最終輸出。我們要做的是從軌跡里提取出可復(fù)用的模式。def abstract_skill_from_trace(trace): # 1. 過濾只處理成功且非平凡的軌跡 if not trace.success or len(trace.tool_calls) 2: return None # 2. 提取調(diào)用序列 sequence [(call.name, call.args_schema) for call in trace.tool_calls] # 3. 檢查是否與已有 Skill 重復(fù) if is_duplicate(sequence, skill_library): return None # 4. 生成 Skill 描述 skill { name: generate_name(trace.intent), description: summarize_intent(trace.user_input), steps: sequence, constraints: extract_constraints(trace), source_trace: trace.id, confidence: compute_confidence(trace), } return skill這里有幾個(gè)坑我要提醒。第一別什么軌跡都沉淀。我一開始貪多把所有成功軌跡都轉(zhuǎn)成 Skill結(jié)果技能庫(kù)迅速膨脹到幾百個(gè)加載時(shí)檢索慢、命中率低反而拖累了性能。后來我加了置信度閾值只沉淀那些多次出現(xiàn)且成功率高的模式。第二Skill 描述要寫清楚觸發(fā)條件。我早期生成的 Skill 描述太籠統(tǒng)比如處理客戶問題結(jié)果模型一遇到客戶問題就加載它但它其實(shí)只適用于物流超時(shí)場(chǎng)景。后來我強(qiáng)制要求描述里包含具體的觸發(fā)關(guān)鍵詞和排除條件。第三沉淀的 Skill 要標(biāo)記來源和版本。自演進(jìn)的 Skill 和人工寫的 Skill 質(zhì)量不一樣得能區(qū)分。我一般給自動(dòng)生成的 Skill 打個(gè)auto_generated: true標(biāo)記并且記錄它來自哪條軌跡方便回溯。3.4 技能優(yōu)化的觸發(fā)與執(zhí)行技能優(yōu)化比沉淀更微妙因?yàn)槟阋牡氖且呀?jīng)在用的東西改錯(cuò)了影響面大。我的做法是先影子運(yùn)行再灰度切換。具體流程是這樣當(dāng)某個(gè) Skill 的失敗率超過閾值我設(shè)的是 15%系統(tǒng)自動(dòng)生成一個(gè)優(yōu)化候選版本但不直接替換而是讓它在后臺(tái)影子運(yùn)行——同樣的輸入新舊兩個(gè)版本都跑一遍對(duì)比結(jié)果。跑夠一定樣本量我設(shè)的是 50 次如果新版本成功率明顯更高才灰度切換 10% 的流量觀察一周沒問題再全量。def optimize_skill(skill, recent_traces): failures [t for t in recent_traces if not t.success] if len(failures) / len(recent_traces) 0.15: return None # 分析失敗模式 failure_patterns cluster_failures(failures) # 針對(duì)每種模式生成優(yōu)化建議 candidates [] for pattern in failure_patterns: if pattern.type wrong_order: candidates.append(reorder_steps(skill, pattern)) elif pattern.type missing_constraint: candidates.append(add_constraint(skill, pattern)) elif pattern.type tool_mismatch: candidates.append(swap_tool(skill, pattern)) return candidates這里有個(gè)經(jīng)驗(yàn)優(yōu)化建議不要一次改太多。我試過讓系統(tǒng)一次改三個(gè)地方結(jié)果新版本反而更差因?yàn)闊o法歸因是哪個(gè)改動(dòng)導(dǎo)致的。后來改成每次只改一處效果穩(wěn)定多了。3.5 自演進(jìn)的邊界什么時(shí)候該停下來自演進(jìn)不是越自動(dòng)越好。我踩過最大的坑是讓系統(tǒng)無限制地自動(dòng)生成 Skill結(jié)果技能庫(kù)變成了一個(gè)垃圾場(chǎng)——大量低質(zhì)量、高度重疊、甚至互相矛盾的 Skill 堆在里面檢索時(shí)噪聲極大。后來我定了三條硬規(guī)則技能庫(kù)總量上限。超過上限時(shí)觸發(fā)淘汰機(jī)制按使用頻率、成功率、最近使用時(shí)間綜合打分淘汰末尾的。人工審核閘門。自動(dòng)生成的 Skill 先進(jìn)入候選區(qū)只有被實(shí)際調(diào)用并成功 N 次后才轉(zhuǎn)正進(jìn)主庫(kù)。沖突檢測(cè)。新 Skill 如果和已有 Skill 的觸發(fā)條件高度重疊但流程不同必須人工介入不能自動(dòng)合并。這三條規(guī)則加上之后技能庫(kù)從失控的 400 多個(gè)穩(wěn)定在 80 個(gè)左右檢索命中率反而提升了。4. 動(dòng)態(tài)加載機(jī)制讓技能庫(kù)真正活起來4.1 為什么不能一次性全加載技能庫(kù)有了下一個(gè)問題是怎么讓 Agent 用上最笨的辦法是把所有 Skill 的描述都塞進(jìn) system prompt。我試過80 個(gè) Skill 的描述加起來大概 4 萬 token還沒開始干活上下文就快滿了。而且模型面對(duì) 80 個(gè)選項(xiàng)選擇準(zhǔn)確率會(huì)明顯下降——這跟人一樣菜單太長(zhǎng)反而不知道點(diǎn)啥。所以必須動(dòng)態(tài)加載根據(jù)當(dāng)前任務(wù)只把相關(guān)的幾個(gè) Skill 加載進(jìn)來。這背后是一個(gè)檢索 排序 注入的流程。4.2 動(dòng)態(tài)加載的三段式流程我把動(dòng)態(tài)加載拆成三步每一步都有講究。第一步意圖識(shí)別。從用戶輸入里提取任務(wù)意圖。這一步可以用小模型做也可以用規(guī)則匹配。我一般用輕量級(jí)的分類模型把輸入映射到技能庫(kù)的標(biāo)簽空間。注意這一步不要追求精確匹配寧可多召回幾個(gè)候選后面再篩。第二步技能檢索。用意圖向量去技能庫(kù)里做相似度檢索。這里的關(guān)鍵是技能描述的質(zhì)量。描述寫得好檢索準(zhǔn)描述寫得爛檢索出來的全是噪聲。我要求每個(gè) Skill 的描述必須包含適用場(chǎng)景、觸發(fā)關(guān)鍵詞、不適用場(chǎng)景、典型輸入示例。這四樣齊了檢索準(zhǔn)確率能到 90% 以上。第三步上下文注入。把檢索到的 Skill 描述注入到當(dāng)前對(duì)話上下文里。這里有個(gè)技巧注入位置很關(guān)鍵。我實(shí)測(cè)下來把 Skill 描述放在用戶消息之后、模型回復(fù)之前效果最好。放在 system prompt 里效果反而差因?yàn)槲恢锰壳澳P妥⒁饬Σ粔?。def dynamic_load_skills(user_input, skill_library, top_k3): # 1. 意圖識(shí)別 intent classify_intent(user_input) # 2. 檢索 candidates skill_library.search(intent, top_ktop_k * 2) # 3. 重排序用更精細(xì)的模型 ranked rerank(candidates, user_input) # 4. 取 top_k注入上下文 selected ranked[:top_k] context_injection format_skills_for_context(selected) return context_injection4.3 檢索策略向量、關(guān)鍵詞還是混合技能檢索用什么方法我試過三種純向量檢索把 Skill 描述和用戶輸入都轉(zhuǎn)成向量算余弦相似度。優(yōu)點(diǎn)是語(yǔ)義泛化好用戶換個(gè)說法也能命中。缺點(diǎn)是容易召回語(yǔ)義相近但實(shí)際不相關(guān)的 Skill。純關(guān)鍵詞檢索用 BM25 之類的算法。優(yōu)點(diǎn)是精確缺點(diǎn)是用戶換個(gè)詞就失效?;旌蠙z索兩者結(jié)合加權(quán)打分。這是我目前用的方案實(shí)測(cè)召回率和準(zhǔn)確率都最好?;旌蠙z索的權(quán)重怎么定我的經(jīng)驗(yàn)是向量 0.6、關(guān)鍵詞 0.4。因?yàn)?Skill 描述里通常有明確的關(guān)鍵詞比如退款物流關(guān)鍵詞能兜住精確匹配向量負(fù)責(zé)處理用戶的口語(yǔ)化表達(dá)。這個(gè)比例不是絕對(duì)的你可以根據(jù)自己技能庫(kù)的特點(diǎn)調(diào)。4.4 加載時(shí)機(jī)什么時(shí)候該加載什么時(shí)候該卸載動(dòng)態(tài)加載不只是加載還包括卸載。一個(gè) Skill 用完了如果一直留在上下文里會(huì)占用 token、干擾后續(xù)判斷。我的做法是按任務(wù)邊界卸載當(dāng)一個(gè)任務(wù)完成比如退款流程走完就把這個(gè) Skill 從上下文里移除。但這里有個(gè)坑有些 Skill 是常駐型的比如安全校驗(yàn)這種每個(gè)任務(wù)都要用的就不能卸載。所以我給 Skill 加了個(gè)persistent標(biāo)記常駐的始終保留其他的按需加載、用完即卸。還有一個(gè)細(xì)節(jié)加載要預(yù)判。如果模型正在執(zhí)行一個(gè)多步任務(wù)下一步大概率還需要某個(gè) Skill那就提前加載避免中途加載打斷流程。我一般用簡(jiǎn)單的狀態(tài)機(jī)做預(yù)判——當(dāng)前 Skill 的next_skills字段里列了可能的后續(xù) Skill提前加載。4.5 一個(gè)完整的動(dòng)態(tài)加載實(shí)例我把上面這些串起來給你看一個(gè)完整例子。假設(shè)用戶輸入是我上周買的那個(gè)耳機(jī)還沒到能幫我看看嗎。# 1. 意圖識(shí)別 intent classify_intent(我上周買的那個(gè)耳機(jī)還沒到能幫我看看嗎) # 輸出: {intent: logistics_inquiry, entities: {product: 耳機(jī), time: 上周}} # 2. 混合檢索 candidates hybrid_search(intent, skill_library, top_k6) # 召回: [logistics_tracking, order_query, delivery_delay_handling, # refund_processing, product_info, customer_complaint] # 3. 重排序 ranked rerank(candidates, user_input) # 排序后: [logistics_tracking, delivery_delay_handling, order_query, ...] # 4. 加載 top 3 loaded ranked[:3] # 注入上下文: logistics_tracking, delivery_delay_handling, order_query # 5. 模型執(zhí)行 # 模型先調(diào) order_query 找到訂單再調(diào) logistics_tracking 查物流 # 發(fā)現(xiàn)超時(shí)觸發(fā) delivery_delay_handling 的安撫流程 # 6. 任務(wù)完成后卸載 unload_skills([logistics_tracking, delivery_delay_handling, order_query])整個(gè)過程模型只看到了 3 個(gè) Skill 的描述而不是全部 80 個(gè)。上下文干凈選擇準(zhǔn)確率自然高。5. 實(shí)操中踩過的坑與排查技巧5.1 技能庫(kù)檢索不準(zhǔn)怎么辦這是最高頻的問題。我遇到過的表現(xiàn)是用戶明明問的是退款檢索出來的卻是物流 Skill。排查思路分三步先看描述質(zhì)量。把檢索出來的 Skill 描述和用戶輸入放一起看如果描述里根本沒有退款相關(guān)的詞那就是描述寫得太爛得重寫。我一般要求描述里必須包含至少 3 個(gè)該場(chǎng)景的高頻詞。再看向量模型。如果描述沒問題那就是向量模型對(duì)中文語(yǔ)義的捕捉不夠。我試過幾個(gè)開源模型中文場(chǎng)景下差異挺大。建議用中文語(yǔ)料訓(xùn)練過的模型或者直接用大模型做 embedding。最后看檢索權(quán)重。如果向量和關(guān)鍵詞的權(quán)重配比不合適也會(huì)導(dǎo)致偏差。我一般會(huì)做個(gè)小實(shí)驗(yàn)?zāi)?50 條真實(shí)用戶輸入人工標(biāo)注應(yīng)該命中的 Skill然后調(diào)權(quán)重看準(zhǔn)確率找到最優(yōu)配比。5.2 Skill 之間互相沖突怎么處理沖突有兩種觸發(fā)條件沖突和流程沖突。觸發(fā)條件沖突是指兩個(gè) Skill 都聲稱自己適用于某個(gè)場(chǎng)景。我的處理方式是加優(yōu)先級(jí)。每個(gè) Skill 有個(gè)priority字段沖突時(shí)高優(yōu)先級(jí)的勝出。優(yōu)先級(jí)怎么定按業(yè)務(wù)重要性——涉及資金、安全的 Skill 優(yōu)先級(jí)最高。流程沖突是指兩個(gè) Skill 的步驟互相矛盾比如一個(gè)說先查 A 再查 B另一個(gè)說先查 B 再查 A。這種必須人工介入不能自動(dòng)解決。我的做法是建一個(gè)沖突檢測(cè)機(jī)制新 Skill 入庫(kù)時(shí)自動(dòng)掃描發(fā)現(xiàn)沖突就掛起等人工裁決。5.3 動(dòng)態(tài)加載導(dǎo)致上下文抖動(dòng)這個(gè)問題比較隱蔽。表現(xiàn)是模型在同一個(gè)任務(wù)里一會(huì)兒加載這個(gè) Skill一會(huì)兒加載那個(gè)上下文頻繁變化導(dǎo)致模型精神分裂輸出前后不一致。根因是加載策略太激進(jìn)。我早期是每輪對(duì)話都重新檢索、重新加載結(jié)果模型剛適應(yīng)一個(gè) Skill下一輪又換了。后來改成任務(wù)級(jí)加載一個(gè)任務(wù)開始時(shí)加載一次任務(wù)過程中除非明確需要新 Skill否則不重新加載。這樣上下文穩(wěn)定多了。5.4 常見問題速查表問題現(xiàn)象可能原因排查方向解決思路檢索命中率低描述質(zhì)量差檢查描述關(guān)鍵詞重寫描述補(bǔ)高頻詞加載后模型不用注入位置不對(duì)檢查注入位置放到用戶消息后上下文超限加載太多 Skill統(tǒng)計(jì) token 占用減少 top_k加卸載技能沖突觸發(fā)條件重疊檢查 priority加優(yōu)先級(jí)人工裁決自演進(jìn)失控?zé)o淘汰機(jī)制統(tǒng)計(jì)技能庫(kù)規(guī)模加上限和淘汰優(yōu)化后更差一次改太多對(duì)比新舊版本每次只改一處5.5 幾個(gè)我踩過的獨(dú)家坑坑一Skill 描述里別寫具體參數(shù)值。我早期在 Skill 描述里寫了退款金額超過 500 元需要審核結(jié)果業(yè)務(wù)規(guī)則改成 300 元后Skill 描述沒同步模型按 500 判斷出了事故。后來我把參數(shù)值抽出來放到配置里描述里只說超過閾值需要審核閾值從配置讀。坑二別讓模型自己決定加載哪個(gè) Skill。我試過讓模型在思考時(shí)自己說我需要加載 XX Skill結(jié)果模型經(jīng)常判斷錯(cuò)要么該加載不加載要么加載一堆沒用的。后來改成系統(tǒng)側(cè)檢索 模型側(cè)確認(rèn)模型只負(fù)責(zé)確認(rèn)這個(gè) Skill 是否適用不負(fù)責(zé)檢索??尤齋kill 的版本管理要跟上。自演進(jìn)會(huì)不斷產(chǎn)生新版本如果不做版本管理出了問題根本不知道是哪個(gè)版本導(dǎo)致的。我現(xiàn)在每個(gè) Skill 都有版本號(hào)每次變更記錄 diff出問題能快速回滾。坑四別忽視 Skill 的測(cè)試。Tool 可以單元測(cè)試Skill 得做場(chǎng)景回歸測(cè)試。我建了一個(gè)測(cè)試集包含 200 個(gè)真實(shí)場(chǎng)景每次 Skill 變更都跑一遍確保沒有回歸。這個(gè)投入很值幫我攔下了好幾次潛在事故。6. 從 Tool 到 Skill 的遷移路徑給正在重構(gòu)的你6.1 什么時(shí)候該遷移不是所有項(xiàng)目都需要 Skill 層。我的判斷標(biāo)準(zhǔn)是當(dāng)你的 Tool 數(shù)量超過 10 個(gè)或者出現(xiàn)多個(gè) Tool 需要按固定順序調(diào)用的場(chǎng)景時(shí)就該考慮引入 Skill 了。Tool 少的時(shí)候直接調(diào)用完全夠用硬上 Skill 層反而增加復(fù)雜度。6.2 遷移的四個(gè)步驟第一步盤點(diǎn)現(xiàn)有 Tool。把所有 Tool 列出來標(biāo)注每個(gè) Tool 的調(diào)用頻率、是否常和其他 Tool 組合使用。組合使用的那些就是 Skill 的候選。第二步識(shí)別高頻流程。從日志里找出高頻的 Tool 調(diào)用序列這些序列就是天然的 Skill。我一般取 top 20 的序列人工確認(rèn)后轉(zhuǎn)成 Skill。第三步先并行再切換。新老兩套并行跑一段時(shí)間對(duì)比效果。確認(rèn)新方案更好后再逐步切換。別一刀切風(fēng)險(xiǎn)太大。第四步建立技能庫(kù)運(yùn)營(yíng)機(jī)制。Skill 不是建完就完事得有運(yùn)營(yíng)——監(jiān)控使用情況、定期優(yōu)化、淘汰低效的。這部分工作得有人負(fù)責(zé)不能放任自流。6.3 遷移后的收益與代價(jià)收益方面我自己的項(xiàng)目遷移后任務(wù)成功率從 62% 提到 89%上下文 token 占用降低 40%新場(chǎng)景的響應(yīng)速度從改代碼重部署變成加個(gè) Skill 描述快了一個(gè)數(shù)量級(jí)。代價(jià)方面主要是初期投入大。建技能庫(kù)、寫檢索邏輯、搭自演進(jìn)機(jī)制前前后后花了我一個(gè)多月。而且 Skill 層的調(diào)試比 Tool 層難因?yàn)樯婕澳P托袨椴淮_定性更高。所以我的建議是小項(xiàng)目別急著上等 Tool 確實(shí)管不過來了再遷移。6.4 一個(gè)務(wù)實(shí)的起步方案如果你現(xiàn)在就想試試我給一個(gè)最小可行方案先挑 3 個(gè)最高頻的流程手動(dòng)寫成 Skill別搞自演進(jìn)。用最簡(jiǎn)單的關(guān)鍵詞檢索做動(dòng)態(tài)加載別上向量。跑兩周看效果。如果確實(shí)比純 Tool 好再逐步加自演進(jìn)、加向量檢索。這個(gè)方案投入小、見效快適合驗(yàn)證方向。我自己就是這么起步的先跑通最小閉環(huán)再逐步加復(fù)雜度。7. 關(guān)于技能庫(kù)未來的一點(diǎn)個(gè)人判斷我最近在琢磨一件事技能庫(kù)會(huì)不會(huì)成為 Agent 之間共享的公共資產(chǎn)就像 npm 包一樣有人寫好一個(gè)處理退款的 Skill別人直接引用。這個(gè)方向我覺得挺有意思但有幾個(gè)問題沒解決Skill 的質(zhì)量怎么保證、版本沖突怎么處理、安全邊界怎么劃。我現(xiàn)在還沒想清楚但感覺這是接下來一兩年會(huì)熱起來的方向。另一個(gè)我比較確定的方向是技能庫(kù)和記憶系統(tǒng)的融合?,F(xiàn)在 Skill 和 Memory 是兩套東西Skill 管怎么做Memory 管做過什么。但實(shí)際用下來這兩者邊界挺模糊的——一個(gè)高頻使用的 Skill某種程度上也是一種記憶。我最近在試把兩者統(tǒng)一到一個(gè)經(jīng)驗(yàn)庫(kù)里用同一套檢索機(jī)制效果還在觀察。最后分享一個(gè)小技巧技能庫(kù)的檢索日志一定要留。我每次檢索都記錄用戶輸入、召回結(jié)果、實(shí)際使用、最終效果這些數(shù)據(jù)是優(yōu)化技能庫(kù)的金礦。我靠這些日志發(fā)現(xiàn)了不少問題比如某些 Skill 從來沒被命中過說明描述有問題某些 Skill 命中后成功率很低說明流程有問題。沒有這些日志優(yōu)化就是盲人摸象。這套東西我還在持續(xù)迭代踩坑肯定還會(huì)繼續(xù)。如果你也在做類似的事歡迎交流尤其是自演進(jìn)那塊我總覺得還有更好的做法沒找到。