智能體側(cè)掛架構(gòu):獨(dú)立服務(wù)、獨(dú)立數(shù)據(jù)庫(kù)與主線零侵入落地)
企業(yè)里一接大模型智能體最扎眼的矛盾就來(lái)了既要 Agent 快速見(jiàn)效又不能動(dòng)已經(jīng)穩(wěn)定跑了三年的業(yè)務(wù)主線??涩F(xiàn)實(shí)常常是對(duì)話記錄、向量切片、任務(wù)流水一股腦塞進(jìn)主庫(kù)模型一超時(shí)整條下單鏈路跟著抖。常規(guī)做法之所以不夠用在主服務(wù)里直接寫(xiě) LLM 調(diào)用、復(fù)用主庫(kù)表存會(huì)話、同步等待模型返回會(huì)讓依賴膨脹、事務(wù)邊界被打穿Agent 每迭代一次就得帶著整個(gè)系統(tǒng)重新發(fā)版。本文分享一套可直接落地的側(cè)掛式方案獨(dú)立 Agent 服務(wù) 獨(dú)立數(shù)據(jù)庫(kù) 主線零侵入的事件契約前端組件松耦合掛載、隨拆隨上。一、架構(gòu)選型智能體側(cè)掛而不是嵌入主干先做一次選型對(duì)照再?zèng)Q定 Agent 到底落在哪一側(cè)維度嵌入主服務(wù)側(cè)掛獨(dú)立服務(wù)發(fā)版節(jié)奏隨業(yè)務(wù)系統(tǒng)全量發(fā)布獨(dú)立灰度、獨(dú)立回滾依賴引入主工程引入模型 SDK主線僅留一個(gè)出站接口故障半徑模型超時(shí)拖垮業(yè)務(wù)線程池Agent 掛掉后主線無(wú)感數(shù)據(jù)歸屬會(huì)話與業(yè)務(wù)表混放獨(dú)立庫(kù)獨(dú)立生命周期側(cè)掛定義Agent 作為旁路服務(wù)存在主線只認(rèn)「事件進(jìn)、結(jié)果回」兩條通道。主線保留只留一個(gè)輕量出站適配器代碼里不出現(xiàn)任何模型 SDK、提示詞與解析邏輯。判定標(biāo)準(zhǔn)把 Agent 目錄整個(gè)刪掉主線仍能正常下單收款才算真正零侵入。核心結(jié)論把智能體當(dāng)外部協(xié)作方接入而不是當(dāng)業(yè)務(wù)代碼的延伸。二、服務(wù)邊界網(wǎng)關(guān)與業(yè)務(wù)域各管一段拆分之前先把職責(zé)切干凈邊界模糊比跑得慢更致命業(yè)務(wù)服務(wù)只負(fù)責(zé)產(chǎn)生事實(shí)數(shù)據(jù)發(fā)出order.paid之類的領(lǐng)域事件完全不關(guān)心誰(shuí)來(lái)消費(fèi)。Agent 網(wǎng)關(guān)承接鑒權(quán)、會(huì)話路由、模型適配與限流對(duì)內(nèi)統(tǒng)一暴露POST /agent/run。結(jié)果回流通過(guò)回調(diào)或事件寫(xiě)回業(yè)務(wù)側(cè)主線只按任務(wù)號(hào)冪等落賬不做二次加工。事件進(jìn) → 網(wǎng)關(guān)編排 → 模型執(zhí)行 → 結(jié)果回流 → 主線落賬核心結(jié)論邊界越硬后期換模型、換向量庫(kù)的代價(jià)就越低。三、數(shù)據(jù)隔離會(huì)話與向量落獨(dú)立庫(kù)智能體的數(shù)據(jù)有自己的生命周期先列清單再?zèng)Q定建幾個(gè)庫(kù)數(shù)據(jù)類別歸屬庫(kù)保留策略會(huì)話與消息agent_db90 天滾動(dòng)清理向量與切片agent_vector隨文檔版本重建任務(wù)流水a(chǎn)gent_db按審計(jì)要求歸檔業(yè)務(wù)事實(shí)數(shù)據(jù)原業(yè)務(wù)庫(kù)不復(fù)制、不冗余不跨庫(kù)事務(wù)主線與 Agent 之間只追求最終一致靠taskId做對(duì)賬與補(bǔ)償。只讀共享確需業(yè)務(wù)上下文時(shí)用只讀賬號(hào)同步一份快照表嚴(yán)禁 Agent 反向?qū)懼鲙?kù)。核心結(jié)論數(shù)據(jù)一旦同庫(kù)所謂零侵入就只剩一句口號(hào)。四、零侵入對(duì)接事件驅(qū)動(dòng)與異步回調(diào)解耦主線要的從來(lái)不是能力而是穩(wěn)定接入方式直接決定侵入程度同步直調(diào)模型動(dòng)輒十幾秒長(zhǎng)期占用業(yè)務(wù)線程池一次抖動(dòng)會(huì)被放大成全局故障。事件異步主線發(fā)完事件即可返回Agent 慢、掛、重試都不影響主流程的響應(yīng)時(shí)間?;卣{(diào)冪等回寫(xiě)結(jié)果必須帶taskId上游重復(fù)投遞時(shí)按狀態(tài)機(jī)去重避免重復(fù)落賬。領(lǐng)域事件 → 消息隊(duì)列 → Agent 消費(fèi) → 執(zhí)行任務(wù) → 回調(diào)主線 → 冪等落庫(kù)核心結(jié)論主線代碼里只出現(xiàn)「發(fā)」和「收」兩個(gè)動(dòng)作這就是零侵入的可驗(yàn)證標(biāo)準(zhǔn)。五、接口契約三類端點(diǎn)撐起前后端約定前后端能并行開(kāi)發(fā)靠的是一張穩(wěn)定的契約表端點(diǎn)方法用途關(guān)鍵參數(shù)/agent/sessionPOST創(chuàng)建會(huì)話bizType、bizId/agent/runPOST觸發(fā)任務(wù)taskId、prompt、stream/agent/task/{id}GET查詢進(jìn)度status、resultUrl契約穩(wěn)定字段只增不改后端升級(jí)模型版本不會(huì)波及任何前端代碼。狀態(tài)可查任務(wù)永不阻塞請(qǐng)求前端拿到taskId后按節(jié)奏輪詢。下面這段是 Vue3 Vite 前端里觸發(fā)任務(wù)并輪詢狀態(tài)的最小可用封裝// 觸發(fā)智能體任務(wù)并輪詢其狀態(tài)適配 Vue3 瀏覽器環(huán)境asyncfunctionrunAgent(bizType,bizId){constresawaitfetch(/agent/run,{method:POST,headers:{Content-Type:application/json},body:JSON.stringify({bizType,bizId,prompt:生成本周經(jīng)營(yíng)簡(jiǎn)報(bào)})});const{taskId}awaitres.json();returnpollTask(taskId,2000);}發(fā)任務(wù)拿 taskId → 定時(shí)輪詢 → 狀態(tài)變 SUCCESS 取 resultUrl核心結(jié)論契約一旦凍結(jié)前后端就能各自獨(dú)立發(fā)版。六、前端掛載側(cè)邊欄組件松耦合接入組件接入要做到拔掉就恢復(fù)原樣成本只有一行代碼獨(dú)立目錄Agent 組件單獨(dú)放components/agent-panel主頁(yè)面只保留一行引用。props 傳上下文業(yè)務(wù)方只傳bizType與bizId組件內(nèi)部自己建會(huì)話、自己拉狀態(tài)。事件回拋需要主線刷新時(shí)用emit(done)組件里不 import 任何業(yè)務(wù) store。業(yè)務(wù)頁(yè)面里唯一的接入代碼刪掉這一行即可整塊下線template AgentPanel v-ifagentEnabled :biz-typeorder :biz-idorder.id donereload / /template核心結(jié)論一個(gè)v-if開(kāi)關(guān)加一次emit就是前端側(cè)零侵入的全部成本。七、任務(wù)編排狀態(tài)機(jī)保證可重試可追蹤任務(wù)一旦異步化就必須有明確的狀態(tài)流轉(zhuǎn)與落庫(kù)記錄-- agent_db 中的任務(wù)主表status 字段驅(qū)動(dòng)重試與補(bǔ)償CREATETABLEagent_task(task_idVARCHAR(64)PRIMARYKEY,statusTINYINTNOTNULLDEFAULT0,-- 0待執(zhí)行 1執(zhí)行中 2成功 3失敗 4補(bǔ)償中retryINTNOTNULLDEFAULT0,created_atDATETIMENOTNULL);狀態(tài)機(jī)PENDING → RUNNING → SUCCESS / FAILED連續(xù)失敗超閾值進(jìn)入COMPENSATING自動(dòng)補(bǔ)償。防雙跑同一task_id只允許一個(gè)執(zhí)行者搶鎖靠數(shù)據(jù)庫(kù)行鎖避免并發(fā)重復(fù)調(diào)用模型。核心結(jié)論有狀態(tài)機(jī)才有可追責(zé)的執(zhí)行鏈?zhǔn)∪蝿?wù)才能被自動(dòng)撿起來(lái)重跑。八、安全配額密鑰隔離、限流與審計(jì)留痕能力放開(kāi)之前先把風(fēng)險(xiǎn)面收住這三件事缺一不可密鑰隔離模型 Key 只存在 Agent 服務(wù)的配置中心業(yè)務(wù)側(cè)與前端永遠(yuǎn)拿不到明文。調(diào)用配額按bizType 租戶統(tǒng)計(jì) token 消耗超閾值自動(dòng)降級(jí)為規(guī)則模板回答。審計(jì)留痕每次執(zhí)行落prompt 摘要、模型版本、耗時(shí)、token 數(shù)供事后復(fù)盤(pán)與追責(zé)。核心結(jié)論沒(méi)有配額與審計(jì)的智能體上線那天就是失控那天。九、部署排錯(cuò)容器拆分與高頻故障對(duì)照部署形態(tài)直接決定回滾速度先看拓?fù)湓倏垂收锨鍐? docker-compose 片段Agent 獨(dú)立成組可單獨(dú)重啟與回滾services:agent-svc:image:registry.local/agent-svc:1.4.0environment:-SPRING_PROFILES_ACTIVEproddepends_on:[agent-db]現(xiàn)象可能原因處置動(dòng)作任務(wù)長(zhǎng)期 PENDING消費(fèi)者未啟動(dòng)或隊(duì)列積壓查消費(fèi)者實(shí)例數(shù)與積壓量回調(diào)重復(fù)落庫(kù)上游重復(fù)投遞校驗(yàn) taskId 冪等鍵主線接口變慢誤改回同步調(diào)用恢復(fù)事件異步并加超時(shí)核心結(jié)論服務(wù)與庫(kù)都獨(dú)立排錯(cuò)時(shí)才能做到單點(diǎn)重啟、整體無(wú)感。十、可觀測(cè)性鏈路追蹤與效果回歸評(píng)估上線只是開(kāi)始還得能拿出證據(jù)說(shuō)明它真的有用鏈路串聯(lián)事件、任務(wù)、回調(diào)統(tǒng)一攜帶traceId taskId把主線與 Agent 兩段日志串成一條鏈。指標(biāo)看板盯住任務(wù)成功率、平均耗時(shí)、token 成本、降級(jí)次數(shù)四條曲線異常自動(dòng)告警。效果回歸固定一批樣例問(wèn)題每周跑一遍回答質(zhì)量掉檔就直接攔住發(fā)版。核心結(jié)論可觀測(cè)做到位智能體才從演示效果變成可運(yùn)營(yíng)能力。結(jié)語(yǔ)這套側(cè)掛架構(gòu)把智能體的改動(dòng)收斂在三處一個(gè)獨(dú)立 Agent 服務(wù)、一組獨(dú)立數(shù)據(jù)庫(kù)、一個(gè)前端掛載組件。主線只保留事件與回調(diào)兩條通道既拿到了大模型的能力又不必承擔(dān)它的不穩(wěn)定性要下線時(shí)關(guān)掉一個(gè)開(kāi)關(guān)、停掉一個(gè)容器組即可業(yè)務(wù)代碼一行不改。真正難的從來(lái)不是調(diào)通一次模型而是讓智能體在企業(yè)里長(zhǎng)期可控地跑下去——可回滾、可對(duì)賬、可限流、可追責(zé)。獨(dú)立服務(wù)、獨(dú)立數(shù)據(jù)庫(kù)、事件契約三件事湊齊智能體才算真正接進(jìn)了企業(yè)系統(tǒng)。