版套件化:一個(gè)Agent底座統(tǒng)管五個(gè)產(chǎn)品的架構(gòu)設(shè)計(jì)與實(shí)踐)
1. 從五個(gè)產(chǎn)品到一套底座WorkBuddy 企業(yè)版套件化的核心命題第一次看到“WorkBuddy 企業(yè)版套件化一個(gè) Agent 底座統(tǒng)管五個(gè)產(chǎn)品”這個(gè)標(biāo)題我腦子里蹦出來(lái)的第一個(gè)畫(huà)面不是架構(gòu)圖而是一個(gè)很具體的運(yùn)維場(chǎng)景公司內(nèi)部同時(shí)跑著五套 AI 工具每套都有自己的賬號(hào)體系、自己的模型配置、自己的日志格式運(yùn)維同事每天在五個(gè)后臺(tái)之間來(lái)回切換改一個(gè)超時(shí)參數(shù)要登錄五次。這種“煙囪式”的 AI 工具堆疊在 2024 年到 2025 年之間幾乎成了中大型團(tuán)隊(duì)的標(biāo)配痛點(diǎn)。WorkBuddy 企業(yè)版做的事情本質(zhì)上就是把這五套東西的“地基”抽出來(lái)做成一個(gè)統(tǒng)一的 Agent 底座讓上層五個(gè)產(chǎn)品變成這個(gè)底座上的“租戶”或者“插件”。這個(gè)思路聽(tīng)起來(lái)簡(jiǎn)單但真正落地的時(shí)候涉及的問(wèn)題遠(yuǎn)比“抽個(gè)公共庫(kù)”復(fù)雜得多五個(gè)產(chǎn)品的 Agent 能力邊界不一樣有的偏代碼生成有的偏工作流編排有的偏數(shù)據(jù)分析怎么用一個(gè)底座同時(shí)滿足底座的抽象層次定在哪里才不會(huì)既管不住上層、又把自己撐爆我先把結(jié)論放在前面套件化的關(guān)鍵不在于“統(tǒng)一”而在于“分層”。一個(gè) Agent 底座要統(tǒng)管五個(gè)產(chǎn)品它必須把“所有產(chǎn)品都一樣的部分”和“每個(gè)產(chǎn)品都不一樣”的部分切得足夠干凈。切錯(cuò)了底座要么變成一坨誰(shuí)都不敢改的巨石要么變成一層薄得沒(méi)有價(jià)值的殼。1.1 為什么是“一個(gè)底座”而不是“一套微服務(wù)”很多人第一反應(yīng)是五個(gè)產(chǎn)品那就拆成五個(gè)微服務(wù)共享一個(gè)網(wǎng)關(guān)不就行了這個(gè)方案在傳統(tǒng)業(yè)務(wù)系統(tǒng)里沒(méi)問(wèn)題但在 Agent 場(chǎng)景下會(huì)踩坑。原因是 Agent 的核心資源不是 CPU 和內(nèi)存而是模型調(diào)用配額、上下文窗口、工具Skill注冊(cè)表、會(huì)話狀態(tài)。這四樣?xùn)|西如果每個(gè)產(chǎn)品各管各的會(huì)出現(xiàn)三個(gè)致命問(wèn)題。第一配額打架。五個(gè)產(chǎn)品各自持有模型 API Key各自限流結(jié)果就是 A 產(chǎn)品把配額跑滿了B 產(chǎn)品直接 429。企業(yè)版必須有一個(gè)統(tǒng)一的配額池和調(diào)度器才能把有限的 token 預(yù)算按優(yōu)先級(jí)分配。第二Skill 重復(fù)注冊(cè)。熱詞里反復(fù)出現(xiàn)skill、skill插件、agent skill說(shuō)明 Skill 機(jī)制是這個(gè)體系的核心。如果五個(gè)產(chǎn)品各自維護(hù)一套 Skill 注冊(cè)表同一個(gè)“查詢數(shù)據(jù)庫(kù)”的 Skill 會(huì)被寫(xiě)五遍改一次要改五處。底座必須提供統(tǒng)一的 Skill Registry。第三會(huì)話狀態(tài)割裂。用戶在 A 產(chǎn)品里跟 Agent 聊到一半切到 B 產(chǎn)品上下文全丟了。企業(yè)級(jí)體驗(yàn)要求跨產(chǎn)品的會(huì)話連續(xù)性這只能靠底座統(tǒng)一管理 session。所以“一個(gè)底座”不是架構(gòu)潔癖而是被 Agent 的資源特性逼出來(lái)的必然選擇。微服務(wù)那套“每個(gè)服務(wù)自治”的理念在共享稀缺模型資源的前提下會(huì)直接失效。1.2 五個(gè)產(chǎn)品到底共享了什么我把這套套件化拆解下來(lái)底座真正需要統(tǒng)管的東西其實(shí)就五類(lèi)我習(xí)慣叫它“五件套”共享層具體內(nèi)容不共享會(huì)怎樣模型接入層多模型路由、配額、重試、降級(jí)配額打架、成本失控Skill 注冊(cè)中心Skill 定義、版本、權(quán)限、發(fā)現(xiàn)Skill 重復(fù)開(kāi)發(fā)、版本混亂會(huì)話與上下文Session、Memory、上下文壓縮跨產(chǎn)品體驗(yàn)斷裂身份與權(quán)限租戶、用戶、產(chǎn)品級(jí) RBAC權(quán)限模型五套、審計(jì)困難可觀測(cè)性日志、Trace、Token 計(jì)量出問(wèn)題無(wú)法定位、成本無(wú)法歸因這五類(lèi)里模型接入層和 Skill 注冊(cè)中心是底座的技術(shù)核心身份和可觀測(cè)性是工程保障會(huì)話與上下文是最容易被低估、但用戶感知最強(qiáng)的一層。后面我會(huì)逐個(gè)展開(kāi)。1.3 套件化之后五個(gè)產(chǎn)品變成了什么這是理解整個(gè)架構(gòu)的關(guān)鍵。套件化不是把五個(gè)產(chǎn)品合并成一個(gè)而是讓它們從“獨(dú)立應(yīng)用”降級(jí)為“底座上的配置 少量專(zhuān)屬邏輯”。用一句話概括產(chǎn)品 底座能力 產(chǎn)品專(zhuān)屬的 Prompt 策略 產(chǎn)品專(zhuān)屬的 Skill 組合 產(chǎn)品專(zhuān)屬的 UI。舉個(gè)具體例子。假設(shè)五個(gè)產(chǎn)品里有一個(gè)偏代碼的類(lèi)似 CodeBuddy 的定位一個(gè)偏通用辦公的WorkBuddy 本體一個(gè)偏數(shù)據(jù)分析的一個(gè)偏科研文獻(xiàn)的一個(gè)偏工作流自動(dòng)化的。套件化之后代碼產(chǎn)品 底座 代碼類(lèi) Skill 集 代碼專(zhuān)用系統(tǒng)提示詞 IDE 插件 UI辦公產(chǎn)品 底座 文檔類(lèi) Skill 集 辦公提示詞 對(duì)話式 UI數(shù)據(jù)產(chǎn)品 底座 SQL/圖表 Skill 集 分析提示詞 看板 UI你會(huì)發(fā)現(xiàn)產(chǎn)品之間的差異被壓縮到了“Skill 組合 提示詞 UI”這三樣。底座承擔(dān)了 80% 的復(fù)雜度產(chǎn)品只負(fù)責(zé) 20% 的差異化。這就是套件化的價(jià)值新增一個(gè)產(chǎn)品從“重寫(xiě)一個(gè) Agent 系統(tǒng)”變成“配置一套 Skill 和提示詞”。但這里有個(gè)陷阱我必須提醒不是所有產(chǎn)品都適合塞進(jìn)同一個(gè)底座。如果兩個(gè)產(chǎn)品的 Agent 交互范式差異過(guò)大比如一個(gè)是純對(duì)話一個(gè)是純批處理流水線強(qiáng)行統(tǒng)一底座會(huì)導(dǎo)致抽象層被迫做得極其寬泛最后誰(shuí)都用得不順手。判斷標(biāo)準(zhǔn)是它們的“模型調(diào)用 Skill 調(diào)用 會(huì)話管理”這三件事的形態(tài)是否一致。一致就能共享底座不一致就該獨(dú)立。2. Agent 底座的分層設(shè)計(jì)與 Skill 機(jī)制拆解底座怎么分層直接決定了它能撐多久。我見(jiàn)過(guò)太多“統(tǒng)一底座”項(xiàng)目死在第二層——抽象做淺了上層產(chǎn)品各自繞過(guò)底座直連模型抽象做深了底座變成一個(gè)改不動(dòng)的黑盒。WorkBuddy 這套體系能統(tǒng)管五個(gè)產(chǎn)品說(shuō)明它的分層是經(jīng)過(guò)實(shí)戰(zhàn)檢驗(yàn)的。我按自己的理解把它拆成四層并重點(diǎn)講 Skill 機(jī)制因?yàn)闊嵩~里skill出現(xiàn)的頻率高得離譜這一定是整個(gè)體系的重心。2.1 四層架構(gòu)接入層、編排層、能力層、資源層接入層負(fù)責(zé)協(xié)議適配。企業(yè)里五個(gè)產(chǎn)品可能用不同的調(diào)用方式有的走 HTTP OpenAPI有的走 WebSocket 長(zhǎng)連接有的走 SDK。接入層要把這些協(xié)議統(tǒng)一成內(nèi)部的 Agent 請(qǐng)求格式。熱詞里OpenAPI反復(fù)出現(xiàn)說(shuō)明對(duì)外暴露標(biāo)準(zhǔn) OpenAPI 是這套體系的重要能力——第三方系統(tǒng)可以通過(guò) OpenAPI 直接調(diào)用底座能力而不需要理解內(nèi)部協(xié)議。編排層是 Agent 的大腦負(fù)責(zé)決定“這一步該調(diào)模型還是調(diào) Skill”“上下文怎么組裝”“多輪怎么推進(jìn)”。這一層是產(chǎn)品差異化的主要戰(zhàn)場(chǎng)但底座要提供的是編排原語(yǔ)而不是替產(chǎn)品做編排決策。比如底座提供“條件分支”“并行調(diào)用”“重試”這些原語(yǔ)產(chǎn)品用它們拼出自己的流程。能力層就是 Skill 層。所有可被 Agent 調(diào)用的能力——查數(shù)據(jù)庫(kù)、調(diào) API、讀文件、畫(huà)圖、跑代碼——都注冊(cè)在這里。這一層是底座最核心的資產(chǎn)。資源層是模型、向量庫(kù)、存儲(chǔ)、計(jì)算資源的抽象。這一層要屏蔽具體供應(yīng)商差異讓上層不關(guān)心用的是哪個(gè)模型。這四層里編排層和能力層的邊界最容易畫(huà)錯(cuò)。我的經(jīng)驗(yàn)是編排層只負(fù)責(zé)“怎么調(diào)”能力層只負(fù)責(zé)“調(diào)什么”。一旦編排層開(kāi)始關(guān)心具體 Skill 的業(yè)務(wù)邏輯或者能力層開(kāi)始關(guān)心調(diào)用順序邊界就破了。2.2 Skill 機(jī)制底座的能力單元熱詞里有一堆關(guān)于 Skill 的搜索skill插件、agent skill、workbuddy skill、skill編碼193、skill編碼247、測(cè)試skill、豆包skill、codex skill、codex論文skill、打斗動(dòng)作提示詞skill、gemini反重力skill。這些詞說(shuō)明 Skill 已經(jīng)形成了一個(gè)生態(tài)不同來(lái)源、不同用途的 Skill 都在往這個(gè)體系里接。Skill 的本質(zhì)是給 Agent 用的函數(shù)。它和普通函數(shù)調(diào)用的區(qū)別在于三點(diǎn)第一Skill 必須能被模型“理解”所以它需要自然語(yǔ)言描述description第二Skill 的輸入輸出要能被模型消費(fèi)所以通常是結(jié)構(gòu)化的 JSON Schema第三Skill 要有權(quán)限和配額因?yàn)?Agent 可能被誘導(dǎo)調(diào)用危險(xiǎn)操作。一個(gè) Skill 的標(biāo)準(zhǔn)定義大概長(zhǎng)這樣{ name: query_sales_data, description: 查詢指定時(shí)間范圍內(nèi)的銷(xiāo)售數(shù)據(jù)返回匯總結(jié)果, version: 1.2.0, parameters: { type: object, properties: { start_date: {type: string, description: 開(kāi)始日期 YYYY-MM-DD}, end_date: {type: string, description: 結(jié)束日期 YYYY-MM-DD}, region: {type: string, description: 區(qū)域可選} }, required: [start_date, end_date] }, permissions: [sales:read], timeout_ms: 10000 }這里有幾個(gè)設(shè)計(jì)要點(diǎn)值得展開(kāi)。description 的寫(xiě)法直接決定模型能不能正確調(diào)用。我踩過(guò)的坑是description 寫(xiě)得太技術(shù)化模型理解不了業(yè)務(wù)語(yǔ)義寫(xiě)得太模糊模型會(huì)亂調(diào)。好的 description 是“業(yè)務(wù)語(yǔ)義 邊界條件”比如“查詢銷(xiāo)售數(shù)據(jù)僅支持最近兩年超過(guò)范圍會(huì)報(bào)錯(cuò)”。version 字段是必須的。Skill 會(huì)迭代如果沒(méi)版本管理某個(gè)產(chǎn)品依賴舊行為、另一個(gè)產(chǎn)品依賴新行為就會(huì)互相打架。底座要支持多版本共存產(chǎn)品按需鎖定版本。permissions 是安全底線。熱詞里有agent安全這不是空話。Agent 被 prompt injection 攻擊時(shí)最危險(xiǎn)的就是它調(diào)用了不該調(diào)的 Skill。底座必須在 Skill 調(diào)用前做權(quán)限校驗(yàn)而不是信任模型的判斷。2.3 Skill 的注冊(cè)、發(fā)現(xiàn)與隔離五個(gè)產(chǎn)品共享一個(gè) Skill 注冊(cè)中心但不是所有 Skill 對(duì)所有產(chǎn)品可見(jiàn)。這里需要三層隔離全局 Skill所有產(chǎn)品都能用比如“獲取當(dāng)前時(shí)間”“通用搜索”。產(chǎn)品級(jí) Skill只有特定產(chǎn)品能用比如代碼產(chǎn)品的“執(zhí)行單元測(cè)試”。租戶級(jí) Skill企業(yè)客戶自己上傳的私有 Skill只對(duì)該租戶可見(jiàn)。隔離靠的是 Skill 的 namespace 和權(quán)限標(biāo)簽。產(chǎn)品在初始化時(shí)聲明自己需要哪些 namespace底座只返回可見(jiàn)的 Skill 列表。這樣既保證了共享又避免了污染。Skill 的發(fā)現(xiàn)機(jī)制有兩種靜態(tài)注冊(cè)和動(dòng)態(tài)發(fā)現(xiàn)。靜態(tài)注冊(cè)是啟動(dòng)時(shí)加載配置文件適合穩(wěn)定的核心 Skill動(dòng)態(tài)發(fā)現(xiàn)是運(yùn)行時(shí)從注冊(cè)中心拉取適合頻繁更新的 Skill。企業(yè)版通常兩者結(jié)合核心 Skill 靜態(tài)加載保證啟動(dòng)速度擴(kuò)展 Skill 動(dòng)態(tài)拉取保證靈活性。注意動(dòng)態(tài)發(fā)現(xiàn) Skill 時(shí)一定要做簽名校驗(yàn)。我見(jiàn)過(guò)有團(tuán)隊(duì)為了圖方便允許從任意 URL 加載 Skill 定義結(jié)果被注入了一個(gè)“讀取環(huán)境變量”的惡意 Skill。Skill 的來(lái)源必須可信加載前必須驗(yàn)簽。2.4 上下文管理最容易被低估的一層會(huì)話與上下文管理是套件化里最不顯眼但用戶感知最強(qiáng)的一層。五個(gè)產(chǎn)品共享會(huì)話意味著用戶在代碼產(chǎn)品里說(shuō)“幫我看看昨天那個(gè) bug”切到辦公產(chǎn)品時(shí) Agent 還能記得“昨天那個(gè) bug”指的是什么。這需要底座維護(hù)一個(gè)跨產(chǎn)品的 Memory 層。Memory 的設(shè)計(jì)有兩個(gè)流派全量保留和摘要壓縮。全量保留簡(jiǎn)單但 token 成本爆炸摘要壓縮省錢(qián)但會(huì)丟信息。我的實(shí)踐是分層 Memory最近 N 輪對(duì)話全量保留更早的對(duì)話做摘要關(guān)鍵實(shí)體人名、項(xiàng)目名、文件路徑單獨(dú)抽取成結(jié)構(gòu)化記憶。這樣既控制了 token又保住了關(guān)鍵信息。上下文組裝的時(shí)候還有個(gè)細(xì)節(jié)不同產(chǎn)品的系統(tǒng)提示詞要注入到同一個(gè)上下文里。如果處理不好會(huì)出現(xiàn)“代碼產(chǎn)品的提示詞污染了辦公產(chǎn)品的對(duì)話”。解決辦法是給每段上下文打上來(lái)源標(biāo)簽組裝時(shí)按產(chǎn)品過(guò)濾。3. 從零搭建底座核心模塊的實(shí)操過(guò)程前面講的是設(shè)計(jì)思路這一節(jié)我講具體怎么落地。我會(huì)按“模型接入層 → Skill 注冊(cè)中心 → 會(huì)話管理 → OpenAPI 暴露”的順序給出可參考的實(shí)現(xiàn)方案。這些方案是我基于常見(jiàn)企業(yè)級(jí) Agent 平臺(tái)的實(shí)踐總結(jié)具體參數(shù)需要根據(jù)你的模型供應(yīng)商和團(tuán)隊(duì)規(guī)模調(diào)整。3.1 模型接入層多模型路由與配額池模型接入層的核心是統(tǒng)一接口 智能路由 配額管理。統(tǒng)一接口讓上層不關(guān)心具體模型智能路由根據(jù)任務(wù)類(lèi)型、成本、延遲選擇模型配額管理防止某個(gè)產(chǎn)品把預(yù)算跑光。先看統(tǒng)一接口的設(shè)計(jì)。我建議定義一個(gè)內(nèi)部模型調(diào)用協(xié)議所有模型都適配到這個(gè)協(xié)議class ModelRequest: def __init__(self, messages, model_hintNone, max_tokens4096, temperature0.7, toolsNone, tenant_idNone, product_idNone): self.messages messages self.model_hint model_hint # 上層可以給建議但路由層有最終決定權(quán) self.max_tokens max_tokens self.temperature temperature self.tools tools # Skill 列表轉(zhuǎn)成模型的 function calling 格式 self.tenant_id tenant_id self.product_id product_id路由邏輯我通常分三級(jí)任務(wù)類(lèi)型匹配 → 成本約束 → 可用性降級(jí)。任務(wù)類(lèi)型匹配是看這個(gè)請(qǐng)求是代碼生成、長(zhǎng)文本理解還是簡(jiǎn)單問(wèn)答不同任務(wù)用不同模型成本約束是看當(dāng)前租戶的預(yù)算余額余額低就切便宜模型可用性降級(jí)是主模型超時(shí)或報(bào)錯(cuò)時(shí)自動(dòng)切備用模型。配額池的實(shí)現(xiàn)要點(diǎn)是按租戶 產(chǎn)品雙維度計(jì)量。只按租戶計(jì)量無(wú)法知道哪個(gè)產(chǎn)品在燒錢(qián)只按產(chǎn)品計(jì)量無(wú)法做租戶級(jí)預(yù)算。兩個(gè)維度都要有才能既做成本歸因又做預(yù)算控制。# 配額檢查的簡(jiǎn)化邏輯 def check_quota(tenant_id, product_id, estimated_tokens): tenant_quota get_tenant_quota(tenant_id) product_quota get_product_quota(tenant_id, product_id) if tenant_quota.remaining estimated_tokens: raise QuotaExceeded(租戶配額不足) if product_quota.remaining estimated_tokens: raise QuotaExceeded(產(chǎn)品配額不足) return True實(shí)操心得配額檢查一定要在調(diào)用模型之前做而且要預(yù)留 buffer。我見(jiàn)過(guò)有團(tuán)隊(duì)在調(diào)用后才扣減配額結(jié)果并發(fā)請(qǐng)求同時(shí)通過(guò)了檢查實(shí)際消耗遠(yuǎn)超預(yù)算。正確做法是調(diào)用前預(yù)扣、調(diào)用后按實(shí)際用量結(jié)算。3.2 Skill 注冊(cè)中心從定義到執(zhí)行Skill 注冊(cè)中心要解決四個(gè)問(wèn)題定義、存儲(chǔ)、發(fā)現(xiàn)、執(zhí)行。定義用 JSON Schema存儲(chǔ)用數(shù)據(jù)庫(kù)或配置中心發(fā)現(xiàn)靠 namespace 過(guò)濾執(zhí)行靠沙箱隔離。執(zhí)行環(huán)節(jié)是最需要小心的。Skill 本質(zhì)上是執(zhí)行任意代碼或調(diào)用外部系統(tǒng)如果不隔離一個(gè)惡意 Skill 就能拿到整個(gè)底座的權(quán)限。我的方案是進(jìn)程級(jí)隔離 能力白名單每個(gè) Skill 在獨(dú)立進(jìn)程或容器里跑只能訪問(wèn)白名單里的資源比如指定的數(shù)據(jù)庫(kù)連接、指定的 API 域名。# Skill 執(zhí)行的沙箱包裝 class SkillExecutor: def execute(self, skill_name, params, context): skill self.registry.get(skill_name, context.product_id) if not self.check_permission(skill, context.user): raise PermissionDenied() # 在隔離環(huán)境中執(zhí)行 with self.sandbox(skill.timeout_ms, skill.resource_limits): result skill.handler(params) # 記錄審計(jì)日志 self.audit_log(skill_name, params, context) return result審計(jì)日志這塊我要多說(shuō)一句。熱詞里有agent安全企業(yè)級(jí) Agent 的安全審計(jì)不是可選項(xiàng)。每次 Skill 調(diào)用都要記錄誰(shuí)調(diào)的、調(diào)了什么、參數(shù)是什么、結(jié)果是什么、耗時(shí)多少。出安全事件時(shí)這份日志是唯一的追溯依據(jù)。3.3 會(huì)話管理跨產(chǎn)品的上下文連續(xù)性會(huì)話管理的核心數(shù)據(jù)結(jié)構(gòu)是 Session。一個(gè) Session 包含會(huì)話 ID、租戶 ID、參與的產(chǎn)品列表、消息歷史、結(jié)構(gòu)化記憶、創(chuàng)建和更新時(shí)間。跨產(chǎn)品連續(xù)性的實(shí)現(xiàn)關(guān)鍵是Session 與 Product 解耦。Session 屬于用戶不屬于產(chǎn)品。用戶在產(chǎn)品 A 創(chuàng)建的 Session切到產(chǎn)品 B 時(shí)可以通過(guò) Session ID 繼續(xù)。產(chǎn)品 B 拿到 Session 后按自己的系統(tǒng)提示詞重新組裝上下文。class Session: def __init__(self, session_id, tenant_id, user_id): self.session_id session_id self.tenant_id tenant_id self.user_id user_id self.messages [] # 全量消息 self.summary # 歷史摘要 self.entities {} # 結(jié)構(gòu)化記憶 self.products set() # 參與過(guò)的產(chǎn)品 def add_message(self, role, content, product_id): self.messages.append({ role: role, content: content, product_id: product_id, ts: now() }) # 超過(guò)閾值觸發(fā)摘要 if len(self.messages) 50: self.compress()上下文壓縮的觸發(fā)閾值需要調(diào)。太小頻繁壓縮丟信息太大token 成本高。我的經(jīng)驗(yàn)值是保留最近 20 到 30 輪全量更早的做摘要。摘要用便宜的小模型做成本可控。3.4 OpenAPI 暴露讓第三方接入底座熱詞里OpenAPI出現(xiàn)多次說(shuō)明對(duì)外暴露標(biāo)準(zhǔn)接口是剛需。底座的能力要通過(guò) OpenAPI 暴露給第三方系統(tǒng)讓它們能像調(diào)用普通 API 一樣調(diào)用 Agent。OpenAPI 設(shè)計(jì)有三個(gè)要點(diǎn)。第一認(rèn)證用標(biāo)準(zhǔn)方案比如 OAuth2 或 API Key不要自創(chuàng)。第二接口要冪等Agent 調(diào)用可能重試非冪等接口會(huì)出問(wèn)題。第三流式響應(yīng)要支持Agent 的輸出是逐字生成的用 SSE 或 WebSocket 推送體驗(yàn)最好。# OpenAPI 片段示例 paths: /v1/agent/chat: post: summary: 發(fā)起一次 Agent 對(duì)話 security: - ApiKeyAuth: [] requestBody: content: application/json: schema: type: object properties: session_id: {type: string} message: {type: string} product_id: {type: string} stream: {type: boolean, default: true} responses: 200: description: 流式返回 Agent 響應(yīng)注意OpenAPI 暴露的接口一定要做速率限制和配額綁定。第三方系統(tǒng)可能寫(xiě)出死循環(huán)調(diào)用沒(méi)有限流會(huì)把底座打垮。每個(gè) API Key 綁定一個(gè)配額池超限直接拒絕。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄套件化落地過(guò)程中問(wèn)題往往不在設(shè)計(jì)階段而在聯(lián)調(diào)和運(yùn)維階段。我把踩過(guò)的坑整理成速查表覆蓋模型、Skill、會(huì)話、性能四類(lèi)問(wèn)題。4.1 模型接入類(lèi)問(wèn)題問(wèn)題現(xiàn)象可能原因排查方法解決某產(chǎn)品突然大量 429配額被其他產(chǎn)品搶占查配額池實(shí)時(shí)用量按產(chǎn)品設(shè)獨(dú)立配額上限響應(yīng)變慢但無(wú)報(bào)錯(cuò)路由到了慢模型查路由日志的模型選擇調(diào)整路由權(quán)重或加超時(shí)成本突然飆升上下文沒(méi)壓縮查平均 token 數(shù)調(diào)低壓縮閾值模型返回格式錯(cuò)亂提示詞與模型不匹配對(duì)比不同模型的輸出按模型定制提示詞模板這里重點(diǎn)說(shuō) 429 問(wèn)題。多產(chǎn)品共享配額池最容易出現(xiàn)的就是“一個(gè)產(chǎn)品把配額跑滿其他產(chǎn)品餓死”。解決辦法不是簡(jiǎn)單加配額而是分級(jí)配額給每個(gè)產(chǎn)品設(shè)保底配額保證基本可用和彈性配額空閑時(shí)可用。保底配額之和不超過(guò)總配額彈性配額按優(yōu)先級(jí)分配。4.2 Skill 調(diào)用類(lèi)問(wèn)題Skill 相關(guān)的問(wèn)題最隱蔽因?yàn)槟P涂赡堋办o默失敗”——它調(diào)用了 Skill 但沒(méi)告訴用戶。常見(jiàn)問(wèn)題包括Skill 不被調(diào)用description 寫(xiě)得太差模型沒(méi)理解。解決是把 description 改成業(yè)務(wù)語(yǔ)言并加 few-shot 示例。Skill 被錯(cuò)誤調(diào)用多個(gè) Skill 的 description 太相似模型分不清。解決是明確每個(gè) Skill 的邊界在 description 里寫(xiě)“僅用于 X不用于 Y”。Skill 超時(shí)外部依賴慢。解決是設(shè)合理超時(shí)超時(shí)后返回降級(jí)結(jié)果而不是報(bào)錯(cuò)。Skill 權(quán)限報(bào)錯(cuò)產(chǎn)品沒(méi)聲明對(duì)應(yīng) namespace。解決是檢查產(chǎn)品的 Skill 聲明配置。實(shí)操心得調(diào)試 Skill 調(diào)用時(shí)一定要打開(kāi)模型的 function calling 日志。很多時(shí)候模型“看起來(lái)沒(méi)調(diào) Skill”其實(shí)是調(diào)了但參數(shù)錯(cuò)了。日志里能看到模型生成的原始參數(shù)這是定位問(wèn)題的關(guān)鍵。4.3 會(huì)話與上下文類(lèi)問(wèn)題跨產(chǎn)品會(huì)話最容易出的問(wèn)題是上下文污染。產(chǎn)品 A 的系統(tǒng)提示詞被帶到了產(chǎn)品 B 的對(duì)話里導(dǎo)致 Agent 行為異常。根因是上下文組裝時(shí)沒(méi)做來(lái)源過(guò)濾。解決辦法是給每條消息打 product_id 標(biāo)簽組裝時(shí)只保留當(dāng)前產(chǎn)品的系統(tǒng)提示詞歷史消息按需保留。另外結(jié)構(gòu)化記憶要做租戶隔離不同租戶的實(shí)體不能混。還有一個(gè)坑是會(huì)話過(guò)期策略。會(huì)話不能永久保留否則存儲(chǔ)爆炸。我的方案是活躍會(huì)話保留 30 天過(guò)期會(huì)話歸檔到冷存儲(chǔ)只保留摘要。用戶主動(dòng)刪除的會(huì)話立即清除。4.4 性能與穩(wěn)定性問(wèn)題套件化之后底座成了單點(diǎn)。底座掛了五個(gè)產(chǎn)品全掛。所以高可用是硬要求。關(guān)鍵措施有三個(gè)。第一無(wú)狀態(tài)化底座的服務(wù)實(shí)例不保存狀態(tài)狀態(tài)全放 Redis 或數(shù)據(jù)庫(kù)這樣實(shí)例可以隨意擴(kuò)縮容。第二熔斷降級(jí)某個(gè)模型供應(yīng)商掛了自動(dòng)切備用某個(gè) Skill 超時(shí)率高自動(dòng)熔斷。第三限流保護(hù)入口做全局限流防止突發(fā)流量打垮底座。# 熔斷器簡(jiǎn)化實(shí)現(xiàn) class CircuitBreaker: def __init__(self, failure_threshold5, recovery_time60): self.failures 0 self.threshold failure_threshold self.recovery_time recovery_time self.opened_at None def call(self, func, *args, **kwargs): if self.is_open(): raise CircuitOpen(熔斷中請(qǐng)稍后重試) try: result func(*args, **kwargs) self.failures 0 return result except Exception as e: self.failures 1 if self.failures self.threshold: self.opened_at now() raise注意熔斷閾值不要設(shè)得太敏感。Agent 調(diào)用本身就有一定失敗率模型超時(shí)、Skill 抖動(dòng)閾值太低會(huì)導(dǎo)致頻繁熔斷反而影響可用性。我的經(jīng)驗(yàn)是連續(xù) 5 次失敗才熔斷恢復(fù)時(shí)間 60 秒起步。5. 套件化的邊界與擴(kuò)展什么時(shí)候該拆什么時(shí)候該合寫(xiě)到這兒我想聊聊套件化的邊界問(wèn)題。因?yàn)椤耙粋€(gè)底座統(tǒng)管五個(gè)產(chǎn)品”聽(tīng)起來(lái)很美好但不是所有團(tuán)隊(duì)都適合。我見(jiàn)過(guò)強(qiáng)行套件化最后失敗的案例也見(jiàn)過(guò)該合沒(méi)合、維護(hù)成本爆炸的案例。判斷標(biāo)準(zhǔn)其實(shí)就一條產(chǎn)品之間的共享收益是否大于耦合成本。5.1 適合套件化的三個(gè)信號(hào)信號(hào)一產(chǎn)品間共享大量 Skill。如果五個(gè)產(chǎn)品里有 60% 以上的 Skill 是重疊的套件化收益巨大。反之如果每個(gè)產(chǎn)品的 Skill 都是獨(dú)有的共享底座的價(jià)值就只剩模型接入和會(huì)話管理收益有限。信號(hào)二有統(tǒng)一的租戶和權(quán)限體系。企業(yè)客戶買(mǎi)的是“一套 WorkBuddy”而不是“五個(gè)獨(dú)立工具”。如果產(chǎn)品各自有獨(dú)立的賬號(hào)體系客戶要管理五套權(quán)限體驗(yàn)很差。套件化能統(tǒng)一身份這是企業(yè)版的剛需。信號(hào)三團(tuán)隊(duì)有能力維護(hù)底座。底座是一個(gè)長(zhǎng)期投入的基礎(chǔ)設(shè)施需要專(zhuān)門(mén)的團(tuán)隊(duì)維護(hù)。如果團(tuán)隊(duì)規(guī)模小五個(gè)產(chǎn)品都靠同一批人開(kāi)發(fā)套件化反而增加協(xié)調(diào)成本。這種情況下先做“共享庫(kù)”而不是“共享底座”更務(wù)實(shí)。5.2 底座不該管的三件事套件化最容易犯的錯(cuò)是底座管太多。有三件事底座不該管第一產(chǎn)品的業(yè)務(wù)邏輯。底座提供 Skill 和編排原語(yǔ)但“這個(gè)產(chǎn)品的 Agent 該怎么回復(fù)用戶”是產(chǎn)品的事。底座一旦開(kāi)始關(guān)心業(yè)務(wù)語(yǔ)義就會(huì)變成改不動(dòng)的巨石。第二產(chǎn)品的 UI 和交互。底座只提供 API不提供界面。界面是產(chǎn)品差異化的核心底座不該碰。第三產(chǎn)品的專(zhuān)屬數(shù)據(jù)。底座管會(huì)話和記憶但產(chǎn)品自己的業(yè)務(wù)數(shù)據(jù)比如代碼產(chǎn)品的代碼庫(kù)索引應(yīng)該產(chǎn)品自己管。底座只提供存儲(chǔ)抽象不提供具體存儲(chǔ)。5.3 擴(kuò)展新產(chǎn)品的標(biāo)準(zhǔn)流程套件化的最大價(jià)值是降低新增產(chǎn)品的成本。我總結(jié)了一個(gè)標(biāo)準(zhǔn)流程新增一個(gè)產(chǎn)品大概分四步定義產(chǎn)品畫(huà)像這個(gè)產(chǎn)品面向什么場(chǎng)景、用什么模型、需要哪些 Skill。配置 Skill 組合從 Skill 注冊(cè)中心挑選需要的 Skill聲明 namespace。編寫(xiě)系統(tǒng)提示詞這是產(chǎn)品差異化的核心決定 Agent 的行為風(fēng)格。接入 OpenAPI用底座的 OpenAPI 實(shí)現(xiàn)產(chǎn)品后端前端自己開(kāi)發(fā)。這四步里系統(tǒng)提示詞是最花時(shí)間的。我見(jiàn)過(guò)有團(tuán)隊(duì)以為套件化之后新產(chǎn)品一周就能上線結(jié)果提示詞調(diào)了兩周。提示詞不是寫(xiě)一次就完要反復(fù)測(cè)試、迭代。建議給每個(gè)產(chǎn)品建一個(gè)提示詞測(cè)試集每次改動(dòng)都跑一遍回歸。5.4 一個(gè)真實(shí)的擴(kuò)展案例假設(shè)要新增一個(gè)“科研文獻(xiàn)助手”產(chǎn)品熱詞里有workbuddy 科研。按套件化流程產(chǎn)品畫(huà)像面向科研人員需要文獻(xiàn)檢索、摘要生成、引用格式化能力。Skill 組合復(fù)用底座的“通用搜索”Skill新增“文獻(xiàn)庫(kù)檢索”“引用格式化”兩個(gè)專(zhuān)屬 Skill。系統(tǒng)提示詞強(qiáng)調(diào)學(xué)術(shù)嚴(yán)謹(jǐn)性要求引用必須標(biāo)注來(lái)源不確定的內(nèi)容要明確說(shuō)明。OpenAPI 接入用底座的 chat 接口前端做一個(gè)文獻(xiàn)管理界面。整個(gè)過(guò)程底座代碼零改動(dòng)只新增了兩個(gè) Skill 和一套提示詞。這就是套件化的威力——新增產(chǎn)品從“造輪子”變成“拼積木”。6. 我在這套體系里踩過(guò)的坑和總結(jié)的經(jīng)驗(yàn)最后這部分我想拋開(kāi)架構(gòu)聊點(diǎn)更實(shí)在的東西。套件化這件事技術(shù)方案可以抄但經(jīng)驗(yàn)抄不來(lái)。我把自己踩過(guò)的坑列出來(lái)希望能幫你少走彎路。第一個(gè)坑過(guò)早抽象。項(xiàng)目剛開(kāi)始就想著“要統(tǒng)管五個(gè)產(chǎn)品”把底座抽象做得極其寬泛結(jié)果每個(gè)產(chǎn)品接入時(shí)都要寫(xiě)一堆適配代碼。正確做法是先讓兩個(gè)產(chǎn)品跑通再抽象。兩個(gè)產(chǎn)品的共性才是真共性五個(gè)產(chǎn)品的共性往往是想象出來(lái)的。第二個(gè)坑Skill 沒(méi)有版本管理。早期覺(jué)得 Skill 改了就改了結(jié)果一個(gè)產(chǎn)品依賴舊行為另一個(gè)依賴新行為互相打架。后來(lái)加了版本字段產(chǎn)品鎖定版本問(wèn)題才解決。Skill 一旦發(fā)布就不能改行為只能發(fā)新版本。第三個(gè)坑忽略可觀測(cè)性。上線初期沒(méi)做 Trace出問(wèn)題只能靠猜。后來(lái)補(bǔ)了全鏈路 Trace才發(fā)現(xiàn)很多問(wèn)題出在上下文組裝而不是模型本身??捎^測(cè)性不是上線后補(bǔ)的是設(shè)計(jì)時(shí)就要留的。第四個(gè)坑配額沒(méi)做預(yù)扣。并發(fā)請(qǐng)求同時(shí)通過(guò)配額檢查實(shí)際消耗超預(yù)算。改成預(yù)扣 結(jié)算后解決。這個(gè)坑很隱蔽因?yàn)閱握?qǐng)求測(cè)試永遠(yuǎn)發(fā)現(xiàn)不了。第五個(gè)坑會(huì)話沒(méi)做租戶隔離。測(cè)試時(shí)用同一個(gè)租戶沒(méi)發(fā)現(xiàn)問(wèn)題。上線后多租戶發(fā)現(xiàn)結(jié)構(gòu)化記憶串了。所有涉及數(shù)據(jù)的地方都要先問(wèn)一句“租戶隔離了嗎”。這套體系跑下來(lái)我最大的體會(huì)是套件化的難點(diǎn)不在技術(shù)而在邊界。技術(shù)方案網(wǎng)上都能搜到但“什么該共享、什么該獨(dú)立”這個(gè)判斷只能靠對(duì)業(yè)務(wù)的深刻理解。底座做得太厚產(chǎn)品失去靈活性做得太薄共享價(jià)值不足。這個(gè)平衡點(diǎn)每個(gè)團(tuán)隊(duì)都不一樣只能自己摸索。如果讓我給正在考慮套件化的團(tuán)隊(duì)一個(gè)建議那就是先從共享模型接入和 Skill 注冊(cè)中心開(kāi)始這兩塊收益最明確、風(fēng)險(xiǎn)最低。會(huì)話管理和身份體系可以第二步做。至于產(chǎn)品專(zhuān)屬邏輯永遠(yuǎn)不要往底座里塞。守住這條線底座就能活得久。