設(shè)計(jì)指南:從定義到路由的完整落地實(shí)踐)
做了一段時(shí)間的Agent開發(fā)我最深的體會(huì)是別急著堆功能先把技能系統(tǒng)設(shè)計(jì)好。很多朋友拿到一個(gè)agent-skills項(xiàng)目要么一頭扎進(jìn)提示詞工程要么上來就接十幾個(gè)API結(jié)果智能體在demo里很驚艷一上真實(shí)場景就失靈。Agent的技能體系恰恰是決定它能不能從能聊變成能干活的關(guān)鍵。這篇文章我會(huì)從技能的定義標(biāo)準(zhǔn)、注冊路由機(jī)制到具體的實(shí)操案例和排錯(cuò)經(jīng)驗(yàn)完整拆一遍怎么搭建一套扛得住真實(shí)業(yè)務(wù)的Agent技能系統(tǒng)。適合正在做智能體應(yīng)用、想把手里的LLM能力真正工程化的開發(fā)者參考。1. 先想清楚Agent技能系統(tǒng)的設(shè)計(jì)邏輯1.1 為什么Agent需要一套獨(dú)立的技能體系不管你是用LangChain、AutoGen還是自己寫編排框架只要涉及到讓Agent完成實(shí)際任務(wù)就一定會(huì)遇到一個(gè)問題模型本身的知識(shí)和能力有限光靠對話和Prompt無法穩(wěn)定地完成查天氣、算數(shù)據(jù)、調(diào)接口、生成報(bào)表這類具體動(dòng)作。打個(gè)比方。一個(gè)剛?cè)肼毜膶?shí)習(xí)生你說幫我把這個(gè)月的數(shù)據(jù)整理一下他大概率手足無措。但如果你給他一套明確的崗位SOP手冊告訴他遇到什么情況用哪個(gè)流程、需要哪些輸入、輸出長什么樣他就能穩(wěn)定執(zhí)行。Agent的技能就是這個(gè)SOP手冊。沒有技能的Agent面對復(fù)雜指令只能胡猜有了技能它才知道遇到什么情況該掏出什么工具、按什么流程做事。這里要區(qū)分兩個(gè)概念工具調(diào)用和技能。工具調(diào)用是單次動(dòng)作比如調(diào)用天氣API技能則是意圖識(shí)別、參數(shù)解析、動(dòng)作執(zhí)行、結(jié)果格式化的完整閉環(huán)。很多新手以為把函數(shù)列表塞給模型就算完事實(shí)際上模型確實(shí)能把函數(shù)調(diào)用出來但調(diào)用完干什么、結(jié)果怎么處理這些環(huán)節(jié)沒有系統(tǒng)的約束輸出就很容易翻車。技能體系解決的正是這個(gè)完整鏈路問題。1.2 三類核心技能基礎(chǔ)、領(lǐng)域、編排我習(xí)慣把技能分成三個(gè)層次方便管理也方便復(fù)用?;A(chǔ)技能是通用原子能力比如文本摘要、關(guān)鍵詞提取、格式轉(zhuǎn)換這類技能不依賴特定業(yè)務(wù)場景幾乎任何Agent都用得上。領(lǐng)域技能是針對具體業(yè)務(wù)場景封裝的能力比如生成電商周報(bào)、解析簡歷、查詢訂單物流狀態(tài)這類技能跟業(yè)務(wù)數(shù)據(jù)強(qiáng)相關(guān)。編排技能是把多個(gè)技能按規(guī)則串起來比如經(jīng)營復(fù)盤技能可能內(nèi)部調(diào)用了數(shù)據(jù)查詢、異常檢測、報(bào)告生成三個(gè)基礎(chǔ)技能。分層的價(jià)值在于基礎(chǔ)技能可以跨項(xiàng)目復(fù)用領(lǐng)域技能可以按業(yè)務(wù)模塊獨(dú)立迭代編排技能則對應(yīng)復(fù)雜任務(wù)的工作流。修改底層技能的實(shí)現(xiàn)時(shí)只要接口不變上層編排不用動(dòng)。這套設(shè)計(jì)讓技能庫可以像搭積木一樣按需組合而不是每來一個(gè)新需求就把原來的代碼推倒重來。1.3 技能設(shè)計(jì)的四個(gè)核心原則設(shè)計(jì)技能時(shí)我踩過不少坑最后沉淀下來四條原則。單一職責(zé)。一個(gè)技能只做一件事。不要設(shè)計(jì)一個(gè)全能處理技能因?yàn)樗入y描述清楚觸發(fā)條件也容易讓模型產(chǎn)生路由混淆。參數(shù)最小化。能由模型從上下文推斷的字段就不要讓用戶額外提供。比如技能內(nèi)部可以根據(jù)時(shí)間自動(dòng)確定本周的起止日期就不需要用戶手動(dòng)輸入。可觀測。每個(gè)技能都應(yīng)該有日志記錄記錄被哪些意圖觸發(fā)、傳入了哪些參數(shù)、執(zhí)行是否成功、耗時(shí)多少。沒有可觀測性的技能體系出問題時(shí)根本無從排查。漸進(jìn)增強(qiáng)。先跑通主干流程再逐步給技能增加邊界處理。一上來就想把邊緣情況全覆蓋技能還沒上線維護(hù)成本先把人壓垮了。2. 技能定義的標(biāo)準(zhǔn)化結(jié)構(gòu)一個(gè)技能到底包含什么2.1 技能定義的核心字段拆解要把技能變成機(jī)器可以識(shí)別和調(diào)用的資產(chǎn)得定義一套統(tǒng)一的結(jié)構(gòu)。我目前使用的技能定義包含六個(gè)核心字段技能名稱、描述信息、參數(shù)Schema、執(zhí)行流程、輸出Schema、約束條件。技能名稱要短且語義明確比如daily_briefing、calc_expense別用含糊的process_data這種名字。描述信息是整個(gè)定義里最關(guān)鍵也最容易寫差的部分它直接決定模型能不能在正確時(shí)機(jī)觸發(fā)這個(gè)技能。參數(shù)Schema沿用JSON Schema的寫法明確類型和約束。執(zhí)行流程是技能真正干活的邏輯可以是調(diào)API、跑Python腳本也可以是嵌套調(diào)用其他技能。輸出Schema規(guī)定了返回結(jié)果的JSON結(jié)構(gòu)保證下游處理的穩(wěn)定性。約束條件則寫明技能的適用范圍和副作用比如該技能只接受UTC時(shí)間格式、調(diào)用該技能會(huì)寫入數(shù)據(jù)庫。2.2 描述信息怎么寫才能提升命中率有段時(shí)間我排障排到頭禿后來發(fā)現(xiàn)90%的技能路由錯(cuò)誤都出在描述寫得太抽象。比如一個(gè)查詢賬單的技能描述寫的是查詢用戶的賬單信息模型在用戶說我這個(gè)月花了多少錢時(shí)常常不觸發(fā)因?yàn)榛ㄙM(fèi)和賬單這兩個(gè)詞在語義上沒被映射起來。踩過幾次坑之后我的描述寫法改為三段式觸發(fā)場景、功能聲明、負(fù)面提示。觸發(fā)場景用當(dāng)用戶想要...時(shí)觸發(fā)把能想到的自然語義都列出來比如當(dāng)用戶想了解本月消費(fèi)、查賬、核對賬單、詢問開銷明細(xì)時(shí)。功能聲明說明技能能做什么、輸入輸出是什么。負(fù)面提示同樣重要寫明當(dāng)用戶在討論賬單分期規(guī)則、提問政策條款時(shí)不要觸發(fā)這一條能顯著降低誤觸發(fā)率。實(shí)測下來加上負(fù)面提示之后路由準(zhǔn)確率能從75%提到90%以上。2.3 參數(shù)Schema的設(shè)計(jì)細(xì)節(jié)與常見坑參數(shù)設(shè)計(jì)看起來簡單實(shí)際上最考驗(yàn)經(jīng)驗(yàn)。先說必填與可選模型不是萬能的用戶說幫我查訂單時(shí)沒給出訂單號(hào)你要么把訂單號(hào)標(biāo)為可選并設(shè)計(jì)默認(rèn)值要么在參數(shù)缺失時(shí)走追問流程但不能既標(biāo)必填又沒有默認(rèn)兜底。其次是類型與格式日期字段如果用字符串建議明確寫format: YYYY-MM-DD否則模型可能給你四種不同格式。枚舉值字段要列全合法值比如[day, week, month]不要只寫時(shí)間范圍讓人猜。最后是依賴關(guān)系參數(shù)A依賴于參數(shù)B的場景需要在Schema的dependencies字段里聲明否則模型會(huì)傳出一個(gè)缺少前置條件的組合。這里分享一個(gè)技巧給每個(gè)參數(shù)補(bǔ)充一個(gè)description告訴模型這個(gè)參數(shù)應(yīng)該從用戶哪句話里取。比如開始時(shí)間參數(shù)可以寫優(yōu)先從用戶提到的日期中解析未提及時(shí)取本周一0點(diǎn)。參數(shù)描述越具體抽取越準(zhǔn)。3. 技能注冊與路由讓Agent學(xué)會(huì)在合適時(shí)機(jī)出手3.1 技能注冊表Agent的能力清單技能定義好了之后需要一個(gè)統(tǒng)一的地方登記造冊這就是注冊表Registry。注冊表本質(zhì)上是一份結(jié)構(gòu)化的技能清單供路由模塊在運(yùn)行時(shí)檢索。我建議把注冊表做成一個(gè)獨(dú)立的JSON文件或數(shù)據(jù)庫表不要硬編碼在代碼里。注冊表至少包含技能ID、名稱、描述、參數(shù)Schema入口、執(zhí)行入口、版本號(hào)、啟用狀態(tài)。版本號(hào)這個(gè)字段一定要有我在上線新版本技能后發(fā)現(xiàn)效果回退想回滾舊版本因?yàn)闆]有版本號(hào)管理而回滾困難那次之后所有技能都強(qiáng)制帶版本。注冊表的另一個(gè)用途是控制能力邊界。給Agent配技能時(shí)不是越多越好而是按場景漏斗收斂。比如一個(gè)客服Agent只注冊5個(gè)與售前咨詢相關(guān)的技能就好注冊一個(gè)寫詩技能反而會(huì)干擾路由判斷。我的經(jīng)驗(yàn)是一次注冊給Agent的技能數(shù)控制在20個(gè)以內(nèi)這樣可以有效保證路由準(zhǔn)確率。技能數(shù)量上來之后路由模型的注意力會(huì)被稀釋容易選錯(cuò)。3.2 路由機(jī)制選型LLM路由還是語義路由技能路由就是決定當(dāng)前用戶請求該調(diào)用哪個(gè)技能。市面上主流有三種做法。第一種是LLM路由把技能注冊表的描述信息塞進(jìn)Prompt讓模型返回技能ID和參數(shù)。這種方案的好處是能處理復(fù)雜語義壞處是Token消耗大、延遲高。第二種是語義路由用Embedding計(jì)算用戶輸入與技能描述之間的相似度取Top K。第三種是混合路由先用語義路由縮小候選范圍到3到5個(gè)再讓LLM精確判定。我實(shí)際推薦混合路由。第一步全量技能先用向量相似度召回Top 5候選這步很快且便宜第二步把5個(gè)候選技能的詳細(xì)描述交給LLM做精確選擇和參數(shù)抽取。這套方案兼顧了準(zhǔn)確率和成本。如果是OpenAI系模型直接走Function Calling做LLM路由也很穩(wěn)如果用的是開源模型本地部署混合路由是性價(jià)比最高的方案。3.3 技能編排串行、并行與條件分支當(dāng)任務(wù)需要多個(gè)技能協(xié)作時(shí)編排邏輯就要上場了。最簡單的編排是串行比如用戶要日報(bào)觸發(fā)daily_briefing內(nèi)部先fetch_news再summarize最后format_markdown前一個(gè)輸出是后一個(gè)輸入。串行適合場景固定、步驟清晰的流水線。并行編排適合多個(gè)技能互相沒有依賴的情況比如生成一份市場分析報(bào)告時(shí)可以同時(shí)調(diào)用競品信息采集和行業(yè)趨勢查詢兩個(gè)技能并行執(zhí)行再合并結(jié)果。這里注意并行調(diào)用多個(gè)LLM技能時(shí)Token消耗會(huì)成倍增長建議只在真正獨(dú)立的讀者分支上使用。條件分支最靈活也最難調(diào)比如如果用戶輸入包含訂單號(hào)則查訂單否則查庫存。這種邏輯可以用規(guī)則引擎硬編碼也可以交給模型判斷。我的建議是把穩(wěn)定不變的分支寫在代碼里把開放語義的判斷交給模型不要全部依賴模型做邏輯判斷否則一旦模型抽風(fēng)整個(gè)流程就斷了。4. 實(shí)操案例從零實(shí)現(xiàn)一個(gè)AI日報(bào)技能4.1 需求拆解日報(bào)技能到底要做什么紙上談兵沒用我拿一個(gè)真實(shí)的案例來走一遍全流程。假設(shè)你要給Agent加一個(gè)AI日報(bào)技能用戶對Agent說幫我生成今天的AI行業(yè)日報(bào)Agent需要能夠抓取當(dāng)天AI相關(guān)的資訊列表、對每篇文章做摘要、按主題聚合輸出一份結(jié)構(gòu)化的日報(bào)。拆解下來這個(gè)任務(wù)可以分解成三個(gè)子技能fetch_news采集內(nèi)容、summarize_text生成摘要、format_report生成日報(bào)模板。為了保持示例完整我直接用一個(gè)復(fù)合技能daily_briefing來封裝這三個(gè)步驟。先定義技能的JSON Schema{ skill_name: daily_briefing, description: 當(dāng)用戶想要生成當(dāng)日AI行業(yè)日報(bào)、晨間簡報(bào)、獲取AI領(lǐng)域要聞匯總時(shí)觸發(fā)。該技能會(huì)采集資訊、生成摘要并以結(jié)構(gòu)化日報(bào)形式輸出。當(dāng)用戶僅詢問單條新聞細(xì)節(jié)或要求實(shí)時(shí)聊天時(shí)不要觸發(fā)。, parameters: { type: object, properties: { date: { type: string, format: YYYY-MM-DD, description: 日報(bào)對應(yīng)的日期優(yōu)先從用戶輸入中提取缺省取當(dāng)前日期。 }, topics: { type: array, items: { type: string }, default: [大模型, AI應(yīng)用, 智能體], description: 日報(bào)聚焦的主題領(lǐng)域從用戶輸入中提取缺省使用默認(rèn)主題。 } } }, execution_flow: fetch_news - summarize_text - format_report, output_schema: { type: object, properties: { summary: { type: string }, items: { type: array, items: { type: object, properties: { title: { type: string }, source: { type: string }, summary: { type: string } } } }, trends: { type: array, items: { type: string } } } } }這里有幾個(gè)細(xì)節(jié)需要說明。description里的負(fù)面提示我寫上了當(dāng)用戶僅詢問單條新聞細(xì)節(jié)時(shí)不要觸發(fā)這個(gè)會(huì)讓路由準(zhǔn)確率明顯提升。topics參數(shù)設(shè)了默認(rèn)值模型在用戶沒有明確指定主題時(shí)不會(huì)報(bào)錯(cuò)。output_schema里固定了summary、items、trends三個(gè)字段這樣下游不管是推送給用戶還是渲染成頁面數(shù)據(jù)結(jié)構(gòu)都是穩(wěn)定的。4.2 執(zhí)行流程實(shí)現(xiàn)從抓取到格式化實(shí)現(xiàn)daily_briefing時(shí)我不建議把一個(gè)技能的所有邏輯都塞進(jìn)一個(gè)函數(shù)里而是讓daily_briefing作為編排入口內(nèi)部調(diào)用子技能。fetch_news負(fù)責(zé)根據(jù)topics生成搜索關(guān)鍵詞然后請求資訊API比如通過RSS聚合或者搜索服務(wù)的返回拿到候選文章列表。這里有個(gè)經(jīng)驗(yàn)?zāi)玫搅斜砗蟛灰刻幚硐劝磿r(shí)間倒序取前20條再做一個(gè)去重關(guān)鍵詞相同、標(biāo)題相近的文章手動(dòng)過濾掉不然摘要環(huán)節(jié)會(huì)浪費(fèi)大量Token。summarize_text對每篇候選文章截取正文前后文用一個(gè)小模型做摘要控制每條摘要不超過80字。如果文章數(shù)量多了就做個(gè)排序把來源權(quán)威、發(fā)布時(shí)間新、跟主題匹配度高的放前面。format_report把摘要結(jié)果填入固定模板生成最終日報(bào)。下面是一段簡化版的核心邏輯我用Python偽代碼風(fēng)格寫出來def daily_briefing(date, topics): # 1. 采集候選文章 candidates fetch_news(date, topics, limit20) # 2. 去重裁剪壓縮處理范圍 candidates dedup_and_rank(candidates, max_count10) # 3. 逐條摘要 summarized [summarize_text(item) for item in candidates] # 4. 聚合趨勢判斷 trends extract_trends(summarized) # 5. 格式化輸出 return format_report(summarysummarized, trendstrends)4.3 集成測試與路由驗(yàn)證技能實(shí)現(xiàn)完之后最重要的一步是驗(yàn)證路由和參數(shù)抽取是否正常。拿幾個(gè)常見說法做測試用戶說今天AI圈有什么大事Agent應(yīng)觸發(fā)daily_briefingtopics取默認(rèn)值用戶說幫我出一份昨天關(guān)于智能體和機(jī)器人的簡報(bào)Agent應(yīng)觸發(fā)技能且topics自動(dòng)解析為[智能體,機(jī)器人]date取昨天用戶說這篇文章講了啥Agent不應(yīng)觸發(fā)日報(bào)技能而是走通用對話或者其他技能。我習(xí)慣在測試階段把路由日志打開。每條用戶輸入記錄觸發(fā)候選的Top 3技能和得分這樣能看到模型在猶豫什么。有一次測試發(fā)現(xiàn)用戶說來一份早報(bào)時(shí)模型同時(shí)把daily_briefing和另一個(gè)weather_report都拉進(jìn)了候選最后因?yàn)槊枋隼锏某块g簡報(bào)字面更近誤觸發(fā)了天氣技能。后來我在daily_briefing的描述里補(bǔ)了一句用戶提到早報(bào)、晨報(bào)、行業(yè)動(dòng)態(tài)時(shí)觸發(fā)不涉及天氣和出行再測就正常了。這再次印證了負(fù)面提示的重要性。5. 故障排查與效果調(diào)優(yōu)實(shí)錄5.1 高頻問題技能誤觸發(fā)與路由搖擺技能系統(tǒng)最常見的故障就兩類該觸發(fā)的沒觸發(fā)不該觸發(fā)的誤觸發(fā)。該觸發(fā)沒觸發(fā)多半是描述里缺少用戶實(shí)際口語的映射比如用戶說報(bào)一下昨天的數(shù)描述里只寫了查詢數(shù)據(jù)報(bào)表語義鴻溝太大。這時(shí)把用戶歷史里真實(shí)出現(xiàn)過的說法收集起來定期反哺到技能描述里。不該觸發(fā)卻觸發(fā)一般是技能描述太寬泛或者多個(gè)技能描述重疊。比如同時(shí)有周報(bào)生成和工作總結(jié)兩個(gè)技能用戶說寫個(gè)總結(jié)就可能在兩者之間搖擺。解決辦法是優(yōu)先在描述里做區(qū)隔兩個(gè)技能分別強(qiáng)調(diào)各自的專屬場景實(shí)在區(qū)隔不開就合并成一個(gè)技能用參數(shù)區(qū)分工作類型。記住一個(gè)原則技能邊界模糊時(shí)優(yōu)先合并不要靠模型硬扛。5.2 參數(shù)抽取與輸出格式的穩(wěn)定性問題參數(shù)抽取出錯(cuò)也是常見問題。模型經(jīng)常把下周解析成下周而不是本周或者把日期格式搞成07/04/2025而不是2025-07-04。我的做法是在參數(shù)Schema的description里明確寫法規(guī)則并在執(zhí)行流程的第一步跑一個(gè)參數(shù)校驗(yàn)函數(shù)不滿足格式時(shí)自動(dòng)按規(guī)則修正修正不了再走追問流程而不是把壞參數(shù)直接傳給下游接口。輸出穩(wěn)定性幾乎是所有Agent項(xiàng)目的痛點(diǎn)。LLM生成JSON經(jīng)常出現(xiàn)多一個(gè)逗號(hào)、字段名大小寫不一致、數(shù)組嵌套層級(jí)錯(cuò)亂。我踩過幾次坑后統(tǒng)一做了三件事第一所有結(jié)構(gòu)化輸出都用輸出Schema定義并讓模型按固定模板返回第二增加一層解析容錯(cuò)遇到非法JSON時(shí)先嘗試修復(fù)而非直接報(bào)錯(cuò)第三解析失敗重試時(shí)把錯(cuò)誤信息回傳給模型讓它知道自己哪里錯(cuò)了重新生成。實(shí)測這套流程能把結(jié)構(gòu)化輸出的成功率從80%拉到98%。5.3 性能與成本調(diào)優(yōu)的五個(gè)方向技能系統(tǒng)上線之后性能和成本往往成為瓶頸。我總結(jié)了五個(gè)調(diào)優(yōu)方向。上下文裁剪。給模型看的技能描述不要太長每個(gè)技能的描述控制在200字以內(nèi)描述精煉對路由準(zhǔn)確率反而有幫助。模型輸入的技能列表只保留必要的Schema不要全量塞入。緩存復(fù)用。用戶經(jīng)常查詢的熱門數(shù)據(jù)比如早報(bào)、周報(bào)可以按日期做緩存同一份內(nèi)容只生成一次。小模型分流。摘要、提取關(guān)鍵詞這些簡單任務(wù)用小參數(shù)模型執(zhí)行只有復(fù)雜編排和最終決策用大模型。并行化。獨(dú)立技能之間用并行調(diào)用替代串行調(diào)用能把總延遲降到原來的三分之一。監(jiān)控告警。統(tǒng)計(jì)每個(gè)技能的調(diào)用成功率、平均延遲和Token消耗一旦出現(xiàn)異常及時(shí)回滾。這五條落實(shí)下來我實(shí)際項(xiàng)目里的成本下降了約40%響應(yīng)速度提升了一倍多。5.4 技能迭代與回歸測試的實(shí)操方法技能不是寫一次就完事的它需要持續(xù)迭代。但要小心一個(gè)問題優(yōu)化一個(gè)技能的路由表現(xiàn)時(shí)可能連帶影響其他技能的路由。我做過一次改動(dòng)把某個(gè)技能的描述擴(kuò)充了很多結(jié)果把另一個(gè)相似技能的調(diào)用量擠掉了一半。從那以后我建立了一套簡單的回歸測試集把過去一個(gè)月里真實(shí)的用戶輸入樣本收集起來每次修改技能定義后都跑一遍統(tǒng)計(jì)路由命中率和參數(shù)抽取命中率。這套回歸測試集規(guī)模不用大300條覆蓋各技能類型的樣本就夠用了。跑一次只要兩分鐘但能擋住絕大多數(shù)回歸問題。結(jié)合我的經(jīng)驗(yàn)技能系統(tǒng)做得好的標(biāo)準(zhǔn)不是技能的數(shù)量多而是路由的準(zhǔn)確率穩(wěn)。先保證20個(gè)以內(nèi)技能的路由穩(wěn)定、參數(shù)抽取干凈、輸出格式可控再考慮擴(kuò)展場景。等新場景積累多了再按業(yè)務(wù)域拆分新的Agent讓每個(gè)Agent的技能集更聚焦整體反而更好維護(hù)。