一Agent觸達(dá)層的架構(gòu)設(shè)計(jì)與實(shí)踐)
1. 為什么要做Agent-Reach三個(gè)Agent就已經(jīng)亂成一鍋粥1.1 每個(gè)Agent都在“自己找路”我最初接觸Agent-Reach這個(gè)概念不是因?yàn)榭戳耸裁葱驴蚣艿奈臋n而是被自己手里的多Agent系統(tǒng)整崩潰了。當(dāng)時(shí)我們的AI協(xié)作群里掛了三個(gè)Agent一個(gè)負(fù)責(zé)輿情監(jiān)控一個(gè)負(fù)責(zé)工單回復(fù)一個(gè)負(fù)責(zé)數(shù)據(jù)分析。聽起來分工明確但問題全藏在“觸達(dá)”這一步。輿情Agent要讀新聞RSS、要抓網(wǎng)頁快照、還要把結(jié)果寫進(jìn)數(shù)據(jù)庫工單Agent要調(diào)CRM接口、要發(fā)郵件、要回企業(yè)微信數(shù)據(jù)分析Agent更麻煩同時(shí)要連ClickHouse、要跑定時(shí)任務(wù)、還要把SQL結(jié)果推給BI系統(tǒng)。每個(gè)Agent都在用自己的方式做HTTP調(diào)用、做鑒權(quán)、做重試、做連接池管理。結(jié)果就是同一個(gè)CRM系統(tǒng)三個(gè)Agent各寫了一套Client同一個(gè)數(shù)據(jù)庫連接串在四個(gè)配置文件里反復(fù)出現(xiàn)某個(gè)內(nèi)網(wǎng)服務(wù)一抖動(dòng)三個(gè)Agent的告警群里同時(shí)響。這不是我不夠勤快而是這種“每個(gè)Agent自己找路”的模式在數(shù)量一旦超過兩三個(gè)之后復(fù)雜度是指數(shù)級上漲的。你每接入一個(gè)新系統(tǒng)就要在N個(gè)Agent里各寫一遍適配代碼每改一次連接參數(shù)就要去N個(gè)Agent的配置中心里各改一遍。真正讓我決定動(dòng)手做一個(gè)統(tǒng)一觸達(dá)層的觸發(fā)點(diǎn)是我發(fā)現(xiàn)排查一個(gè)“為什么工單Agent沒拿到用戶信息”的問題排查了整整兩個(gè)小時(shí)最后發(fā)現(xiàn)是數(shù)據(jù)分析Agent自己在重試時(shí)把目標(biāo)API打滿了。連坐效應(yīng)已經(jīng)完全失控了。1.2 連接不應(yīng)該由Agent自己負(fù)責(zé)“Agent-Reach”這個(gè)名字拆開看就是“Agent的觸達(dá)”。我當(dāng)時(shí)給自己定的目標(biāo)是從今往后任何Agent都不直接知道下游服務(wù)的地址、密鑰和超時(shí)參數(shù)。它只需要聲明“我要做什么”觸達(dá)層負(fù)責(zé)“怎么連到那個(gè)地方、怎么保證安全、怎么失敗的”。這個(gè)思路很像微服務(wù)網(wǎng)關(guān)在服務(wù)領(lǐng)域里的角色。以前我們做服務(wù)治理都會(huì)把熔斷、限流、鑒權(quán)從業(yè)務(wù)代碼里抽出來扔給網(wǎng)關(guān)和Service Mesh。但到了Agent時(shí)代大家反而退回了一步每個(gè)Agent又變成了一個(gè)“業(yè)務(wù)服務(wù)全能客戶端”的巨無霸。Agent-Reach本質(zhì)上就是把那些所有Agent都會(huì)反復(fù)用到的連接能力下沉成一個(gè)獨(dú)立服務(wù)層。這一層要做的事情很明確把下游系統(tǒng)抽象成一個(gè)個(gè)“連接器”Agent不需要知道它是REST、gRPC還是JDBC。統(tǒng)一管控所有出站流量誰來調(diào)、能調(diào)什么、配額是多少、峰值是多少。把可觀測性集中在一起所有Agent觸達(dá)外部系統(tǒng)的日志、監(jiān)控、鏈路追蹤都從這兒過。我并不是說Agent不能保留少數(shù)“私有連接”。但在做一個(gè)平臺級的產(chǎn)品或者一個(gè)公司內(nèi)部的數(shù)字員工體系時(shí)如果沒有一個(gè)統(tǒng)一觸達(dá)層那么每增加一個(gè)Agent都等于給整個(gè)系統(tǒng)增加一份新的維護(hù)債。1.3 Agent-Reach的邊界當(dāng)然Agent-Reach不是萬能的。我在設(shè)計(jì)之初就劃了一條邊界它只負(fù)責(zé)“觸達(dá)”不負(fù)責(zé)“思考”。大模型的調(diào)用、提示詞編排、決策邏輯這些仍然歸屬于Agent本身。Agent-Reach不會(huì)判斷“這個(gè)問題該不該回復(fù)”它只負(fù)責(zé)把Agent已經(jīng)決定要執(zhí)行的動(dòng)作安全、穩(wěn)定、可控地送到對應(yīng)的外部系統(tǒng)里。因?yàn)檫吔缜逦钥商鎿Q性也就強(qiáng)。如果某天我換了一個(gè)Agent框架只要這些Agent還說著同樣的觸達(dá)協(xié)議Agent-Reach這邊一行都不用改。反過來也一樣如果我把某個(gè)下游系統(tǒng)從自建工單換成第三方SaaS則只需要在Agent-Reach里面換一個(gè)連接器所有Agent都會(huì)自動(dòng)切過去。換句話說Agent-Reach想解決的核心矛盾是Agent本身是可折疊的今天用A框架明天用B框架下游系統(tǒng)也是可更換的今天用這家云服務(wù)明天用另一家。只有觸達(dá)層必須是穩(wěn)的。穩(wěn)到所有Agent都能依賴它而不是各自再想辦法繞過它。2. Agent-Reach的架構(gòu)設(shè)計(jì)與核心組件2.1 連接器注冊中心先把能力登記起來Agent-Reach的第一塊地基是連接器注冊中心。我把它理解成一個(gè)“能力超市”的貨架每個(gè)下游系統(tǒng)在接入時(shí)都會(huì)以連接器的身份在注冊中心里登記自己支持的動(dòng)作、支持的協(xié)議類型、需要的入?yún)⒏袷?、以及健康檢查的方式。注冊中心不存業(yè)務(wù)數(shù)據(jù)只存元數(shù)據(jù)。我使用了類似這樣的結(jié)構(gòu){ name: crm.contact.read, connector: crm-connector, protocol: http, endpoint: internal://contact-center/contacts/{id}, method: GET, auth_scheme: vault://secrets/crm/internal-token, timeout_ms: 1500, replay_policy: no-cache, health_check: { type: http_ping, path: /healthz, interval_ms: 30000 } }這個(gè)結(jié)構(gòu)里最關(guān)鍵的一條設(shè)計(jì)是“動(dòng)作名”與“物理接口”分離。Agent只認(rèn)識crm.contact.read這個(gè)語義化動(dòng)作它不需要關(guān)心背后是HTTP還是某個(gè)私有協(xié)議。注冊中心在運(yùn)行期根據(jù)動(dòng)作名找到對應(yīng)的連接器實(shí)例和物理端點(diǎn)然后完成真正的調(diào)用。每個(gè)連接器在啟動(dòng)時(shí)會(huì)向注冊中心發(fā)起心跳同時(shí)上報(bào)自己的版本、健康狀態(tài)、支持的動(dòng)作列表。注冊中心把這些信息緩存在內(nèi)存里同時(shí)持久化一份到關(guān)系庫方便后續(xù)做審計(jì)和回溯。我用了很輕的ETCD做實(shí)時(shí)路由表沒有引入特別重的服務(wù)網(wǎng)格。對于Agent-Reach當(dāng)前的體量ETCD已經(jīng)綽綽有余。2.2 統(tǒng)一請求協(xié)議讓所有Agent說同一種話在Agent-Reach里Agent發(fā)來的請求統(tǒng)一是這個(gè)格式{ request_id: ar_20250123_00000001, agent_id: agent-monitor-01, tenant: internal, action: crm.contact.read, params: {id: C-10086}, context: { trace_id: trace-7f9c123, user_stamp: batch_job|weekly-report, deadline_ms: 2000 } }看到?jīng)]有“上下文”里我不只帶了trace_id還帶了user_stamp。這很重要。因?yàn)锳gent的執(zhí)行往往是批量、異步的下游系統(tǒng)在審計(jì)時(shí)很想知道“這次操作是哪個(gè)Agent、由哪個(gè)上游事件觸發(fā)的、最終是為誰服務(wù)的”。如果這類信息不統(tǒng)一帶上以后出了問題根本不知道找誰。統(tǒng)一請求協(xié)議的價(jià)值不在于格式好看而在于所有通用能力都能圍繞這一個(gè)格式做。協(xié)議里帶了deadline_msAgent-Reach就能統(tǒng)一做超時(shí)控制帶了request_id就能做冪等和去重帶了trace_id就能把整條鏈路串進(jìn)日志系統(tǒng)。這些都是Agent以前各自為戰(zhàn)時(shí)做不到的。我最后選擇的是JSON而不是Protobuf作為線格式原因很樸素所有Agent的SDK都原生支持JSONDebug非常方便而且我們連接器的數(shù)量還不至于大到大流量高并發(fā)需要極致壓縮。等到以后如果真的出現(xiàn)性能瓶頸再在外層套一層二進(jìn)制協(xié)議也不遲。2.3 鑒權(quán)、限流與用量預(yù)算不能裸奔出去Agent-Reach的另一個(gè)核心組件是策略引擎負(fù)責(zé)在請求真正送出之前做最后一道把關(guān)。每個(gè)連接器都可以綁定獨(dú)立的鑒權(quán)方式。有的下游系統(tǒng)用的是靜態(tài)Token有的是AK/SK簽名有的走內(nèi)部SSO。在Agent-Reach里這些信用憑據(jù)統(tǒng)一從Vault拉取不落盤到任何Agent的配置里。Agent側(cè)只知道“我可以調(diào)這個(gè)動(dòng)作”至于密鑰是什么Agent不知道也不應(yīng)該知道。限流和用量預(yù)算則是另一道保障。我給每個(gè)Agent配了一個(gè)“月預(yù)算”例如“輿情監(jiān)控Agent每月最多調(diào)用TWITTER采集接口1萬次”。在注冊中心里這個(gè)配額被拆成了分鐘級令牌桶。一旦某個(gè)Agent的消耗速度超過預(yù)算Agent-Reach不會(huì)直接拒絕而是降級返回“預(yù)算不足請稍后再試”這樣Agent可以把自己的任務(wù)排隊(duì)或者拆分。這個(gè)設(shè)計(jì)參考了云廠商API Gateway的做法但做了一個(gè)針對Agent的調(diào)整我們不只按API Key來限制還按“Agent意圖”來限制。比如某個(gè)Agent發(fā)起的data.export動(dòng)作我們會(huì)同時(shí)檢查目標(biāo)表有沒有敏感字段、執(zhí)行時(shí)間段是否在允許窗口內(nèi)、以及這個(gè)導(dǎo)出的數(shù)據(jù)量是否超過單次上限。三道檢查都過了請求才會(huì)被放行。3. 從Agent調(diào)用到連接器執(zhí)行一個(gè)請求的完整旅程3.1 目錄路由是怎么匹配的Agent-Reach最核心的執(zhí)行鏈路是從接收請求到完成調(diào)用的那條“主徑”。我不畫復(fù)雜圖直接說實(shí)際運(yùn)行的步驟。Agent通過SDK向Agent-Reach的網(wǎng)關(guān)節(jié)點(diǎn)發(fā)送統(tǒng)一協(xié)議包。網(wǎng)關(guān)先解析請求的基本信息校驗(yàn)簽名和租戶身份然后把請求轉(zhuǎn)發(fā)給路由節(jié)點(diǎn)。路由節(jié)點(diǎn)以action字段為Key去注冊中心查連接器元數(shù)據(jù)。如果查不到直接返回“動(dòng)作不存在”。路由節(jié)點(diǎn)把params里的參數(shù)和連接器的參數(shù)Schema做一次校驗(yàn)缺參數(shù)或類型不符的在校驗(yàn)階段就打回不給下游系統(tǒng)添亂。參數(shù)校驗(yàn)通過后請求被包裝成內(nèi)部DAG節(jié)點(diǎn)交給執(zhí)行引擎。執(zhí)行引擎根據(jù)連接器協(xié)議類型選擇合適的調(diào)用器HTTP調(diào)用器、SQL調(diào)用器、消息隊(duì)列調(diào)用器并補(bǔ)全憑據(jù)和超時(shí)信息。這一步是整個(gè)鏈路里最容易出錯(cuò)的地方。調(diào)用完成后把下游系統(tǒng)的響應(yīng)轉(zhuǎn)成統(tǒng)一格式返回給Agent。如果調(diào)用失敗則根據(jù)策略決定是否重試、是否降級、是否返回錯(cuò)誤體。路由匹配看起來簡單真正麻煩的地方在于“模糊動(dòng)作”而不是“精確動(dòng)作”。比如Agent請求的是crm.contact.query但我們只注冊了crm.contact.read這時(shí)候要不要轉(zhuǎn)我的答案是“不要默認(rèn)轉(zhuǎn)”。寧可讓Agent明確說出自己的意圖也不能讓路由層自作聰明。自作聰明是各種詭異線上問題的主要來源。3.2 連接器的健康檢查與自動(dòng)摘除連接器的健康檢查是保證Agent不會(huì)在一根斷掉的管子上反復(fù)摩擦的關(guān)鍵。每個(gè)連接器實(shí)例每隔30秒向注冊中心上報(bào)一次健康狀態(tài)。上報(bào)信息包括最近成功率、平均延遲、當(dāng)前隊(duì)列長度、以及對該下游系統(tǒng)可用性的主觀判斷。注冊中心不只看實(shí)例自己的說法還會(huì)通過Agent-Reach自身發(fā)出的“探活請求”來交叉驗(yàn)證。這里有個(gè)細(xì)節(jié)值得拿出來說。早期我發(fā)現(xiàn)連接器的CPU很空閑但它實(shí)際依賴的那個(gè)下游系統(tǒng)已經(jīng)快不行了。如果只看連接器本身機(jī)器是健康的但看Agent-Reach發(fā)出的探測請求延遲已經(jīng)飆升到了原來10倍。所以后來我們改成雙層健康檢查第一層看連接器的計(jì)算資源第二層由Agent-Reach定時(shí)對下游系統(tǒng)發(fā)一個(gè)輕量級的探針請求。兩層都健康才標(biāo)記為“可用”。一旦某個(gè)連接器連續(xù)三次健康檢查失敗注冊中心會(huì)在路由表里把它自動(dòng)摘除。摘除不是粗暴地停用而是先把連接器的流量權(quán)重降為0讓新請求不再路由過去同時(shí)保留它處理在途請求的能力。這個(gè)做法在消息隊(duì)列連接器上特別重要因?yàn)槟悴荒馨岩粋€(gè)還有積壓消息的連接器直接殺掉。3.3 自定義連接器15分鐘接入一個(gè)新系統(tǒng)接入一個(gè)新系統(tǒng)是Agent-Reach日常迭代里最高頻的折騰。為了把這件事的復(fù)雜度降下來我定義了一套非常小的連接器接口。一個(gè)連接器本質(zhì)上是一個(gè)實(shí)現(xiàn)了三個(gè)方法的小服務(wù)class BaseConnector: def declare_actions(self): 返回這個(gè)連接器支持的語義動(dòng)作列表 pass def validate_params(self, action, params): 校驗(yàn)參數(shù)格式和必填字段 pass def invoke(self, action, params, context): 真正執(zhí)行下游系統(tǒng)的調(diào)用 pass只要實(shí)現(xiàn)這三個(gè)方法再在啟動(dòng)時(shí)連上注冊中心這個(gè)連接器就能被Agent-Reach使用了。我當(dāng)時(shí)用這個(gè)接口接一個(gè)內(nèi)部郵件系統(tǒng)從寫代碼到在測試環(huán)境調(diào)通整個(gè)流程大概花了15分鐘。當(dāng)然前提是我已經(jīng)對郵件系統(tǒng)的接口足夠熟悉否則主要的時(shí)間是花在看對方文檔上。自定義連接器最大的好處是你不必等Agent-Reach官方支持每一個(gè)系統(tǒng)。團(tuán)隊(duì)里任何人遇到一套新系統(tǒng)都可以按這個(gè)規(guī)范寫一個(gè)連接器獨(dú)立測試通過后注冊上線。寫得好不好另說至少不會(huì)污染Agent的核心邏輯。4. 上線后的三個(gè)大坑超時(shí)、重試風(fēng)暴與身份錯(cuò)亂4.1 超時(shí)時(shí)間設(shè)短了Agent全在“無效焦慮”Agent-Reach上線不久我設(shè)了一個(gè)自以為合理的默認(rèn)超時(shí)1.5秒。理由很簡單大部分內(nèi)部HTTP服務(wù)平時(shí)響應(yīng)都在幾百毫秒內(nèi)給1.5秒已經(jīng)算寬容了。結(jié)果第二天好幾個(gè)Agent同時(shí)開始報(bào)錯(cuò)。一查日志全是deadline_exceeded。連的那個(gè)工單系統(tǒng)很老某個(gè)查詢接口平時(shí)沒問題但每天早晨會(huì)有一次批量數(shù)據(jù)預(yù)熱在那個(gè)窗口里單次查詢可能要跑到5秒。Agent-Reach嚴(yán)格執(zhí)行了1.5秒的截止時(shí)間把那些本該成功的請求全攔了下來。更麻煩的是Agent一看超時(shí)就會(huì)啟動(dòng)自己的重試邏輯結(jié)果下游系統(tǒng)的壓力反而變大了。這個(gè)坑的根子在于“統(tǒng)一超時(shí)”這個(gè)想法本身。你說它不對吧全局設(shè)默認(rèn)超時(shí)確實(shí)重要你說它對又不能一刀切。后來我把超時(shí)拆成三個(gè)值連接器級默認(rèn)超時(shí)、動(dòng)作級超時(shí)、單次請求超時(shí)。Agent在請求的context.deadline_ms里可以覆蓋動(dòng)作級超時(shí)但必須池于連接器的可配置上限。上線前還專門跑了一遍“慢調(diào)用模擬”把下游服務(wù)的響應(yīng)時(shí)間人為拉長到各個(gè)檔位驗(yàn)證超時(shí)策略的表現(xiàn)在預(yù)期內(nèi)。4.2 重試風(fēng)暴好心辦了壞事Agent-Reach里一開始建了全局重試機(jī)制連接失敗或5xx錯(cuò)誤碼會(huì)自動(dòng)重試最多2次且采用簡單的固定間隔??雌饋砥狡綗o奇卻差點(diǎn)出了大事。某個(gè)周五下午數(shù)據(jù)分析Agent集中發(fā)起了一批報(bào)表導(dǎo)出任務(wù)。它先請求Agent-Reach去讀取一批歷史數(shù)據(jù)其中一個(gè)下游系統(tǒng)恰好在做全量索引重建響應(yīng)非常慢。Agent-Reach看到第一個(gè)請求超時(shí)觸發(fā)重試重試再超時(shí)再重試。其他Agent并不知道這個(gè)下游在抖也在同時(shí)發(fā)出大量類似請求。于是這個(gè)系統(tǒng)的入口網(wǎng)關(guān)被幾倍于平時(shí)的流量打垮索引重建因此也掛得更徹底最后變成了一場“越重試越失敗、越失敗越重試”的雪崩。教訓(xùn)很直接重試必須有上限上限之外必須慎重考慮目的。后來我把所有連接器分成了三類冪等寫類、非冪等寫類、讀類。讀類和冪等寫類允許有限重試但間隔使用指數(shù)退避并增加隨機(jī)抖動(dòng)非冪等寫類一律不自動(dòng)重試只上報(bào)需要人工介入的事件。另外我還加了一個(gè)“連接器熔斷”機(jī)制如果連接器的在途調(diào)用失敗率在1分鐘內(nèi)超過20%該連接器會(huì)自動(dòng)進(jìn)入半開狀態(tài)只允許少量探測請求通過其他請求直接快速失敗并緩存在Agent側(cè)。4.3 連接上下文丟失后端的身份全亂套了如果說前兩個(gè)坑是大流量帶來的那這個(gè)坑純粹是設(shè)計(jì)上的疏漏。我最初設(shè)計(jì)的統(tǒng)一協(xié)議里雖然有agent_id和tenant但某些老連接器在把請求轉(zhuǎn)發(fā)給下游系統(tǒng)時(shí)沒有把context里的身份信息透傳下去。也就是說下游系統(tǒng)看到的來源是Agent-Reach的通用IP而不是具體受哪個(gè)Agent在調(diào)用。后果很快顯現(xiàn)安全團(tuán)隊(duì)來找我說某個(gè)內(nèi)部系統(tǒng)的審計(jì)日志里所有Agent-Reach的訪問都顯示為同一來源無法區(qū)分是輿情監(jiān)控還是工單處理。更要命的是有些系統(tǒng)基于調(diào)用者身份做了權(quán)限隔離比如普通數(shù)據(jù)查詢只能拉脫敏數(shù)據(jù)但管理員工具能拉全量數(shù)據(jù)。由于Agent-Reach用的是一個(gè)高權(quán)限憑據(jù)透傳請求等于所有Agent都擁有了管理員權(quán)限而我自己卻渾然不知。修復(fù)方法是給每個(gè)連接器增加一層“身份映射”。當(dāng)Agent發(fā)起請求時(shí)Agent-Reach會(huì)查詢該Agent在這個(gè)連接器上被授予的最小權(quán)限身份然后使用這個(gè)身份去調(diào)用下游而不是一把共享Key打天下。我還在每個(gè)下游系統(tǒng)的響應(yīng)里強(qiáng)制注入X-Agent-Reach-Original-Caller頭方便安全團(tuán)隊(duì)追溯。這個(gè)改動(dòng)雖然又花了一輪回歸測試但我非常慶幸我們做了它。因?yàn)槿绻蛔龊竺娴暮弦?guī)審計(jì)這關(guān)根本過不了。5. Agent-Reach的實(shí)測數(shù)據(jù)與后續(xù)演進(jìn)5.1 一組來自生產(chǎn)環(huán)境的對比數(shù)字Agent-Reach在線上穩(wěn)定運(yùn)行了兩個(gè)多月后整個(gè)Agent集群的調(diào)用的整體面貌發(fā)生了明顯變化。為了讓你有個(gè)直觀感受我整理了上線前后同一業(yè)務(wù)周期內(nèi)的對比數(shù)據(jù)指標(biāo)上線前各Agent直接連接上線后統(tǒng)一走Agent-Reach下游系統(tǒng)平均調(diào)用成功率93.2%99.1%運(yùn)維排查一次故障的平均時(shí)間約40分鐘約8分鐘新增下游系統(tǒng)的平均接入時(shí)間按Agent數(shù)遞增約1~3天連接器注冊后當(dāng)天可用因重試導(dǎo)致的下游限流事件每周約5次一個(gè)月約1次全局謂詞錯(cuò)誤率4xx類誤調(diào)未能統(tǒng)計(jì)散落在各Agent日志0.68%且可逐條回溯數(shù)據(jù)漲得最猛的還不是成功率而是“排查效率”。以前一個(gè)請求出問題你得去Agent日志、下游系統(tǒng)日志、網(wǎng)絡(luò)代理日志里來回翻找現(xiàn)在所有從Agent發(fā)出的觸達(dá)請求在Agent-Reach的統(tǒng)一日志里都有完整記錄。搜索一個(gè)request_id就能看到它在Agent那邊的意圖、在Agent-Reach里的完整時(shí)間線、以及在下游系統(tǒng)上的響應(yīng)狀態(tài)。這40分鐘到8分鐘的縮并不夸張。連接成功率能提升到99%以上還有一個(gè)隱形原因是“共同防守”。過去A Agent把下游系統(tǒng)打滿了B Agent會(huì)莫名其妙跟著遭殃。現(xiàn)在所有流量都過同一個(gè)觸達(dá)層熔斷和限流是整個(gè)Agent集群共享的。一個(gè)Agent的異常流量不會(huì)拖垮其他Agent的正常工作這在本質(zhì)上改變了系統(tǒng)的故障邊界。5.2 我不建議你在這些場景硬套Agent-ReachAgent-Reach不是銀彈。我踩過這些甜頭之后也認(rèn)真想過它到底適合什么樣的團(tuán)隊(duì)以及哪些場景其實(shí)沒必要用。如果你的Agent只有一兩個(gè)并且它們調(diào)用的系統(tǒng)總數(shù)不超過三個(gè)那么Agent-Reach大概率是一層多余的東西。你連一個(gè)統(tǒng)一網(wǎng)關(guān)反而把鏈路拉長了增加了一次網(wǎng)絡(luò)跳轉(zhuǎn)和一層調(diào)度復(fù)雜度。在這種情況下直接在Agent內(nèi)部寫一個(gè)精簡的調(diào)用封裝就夠了。如果你的Agent主要是做純文本生成、內(nèi)部知識庫問答這種“讀自己人”的任務(wù)不涉及大量異構(gòu)系統(tǒng)觸達(dá)那么Agent-Reach的價(jià)值也有限。它的核心能力建立在“連接多個(gè)差異很大的外部系統(tǒng)”這個(gè)前提上沒了這個(gè)前提它就是一個(gè)帶鑒權(quán)的HTTP代理而已。還有就是團(tuán)隊(duì)規(guī)模的問題。如果只有一個(gè)人負(fù)責(zé)整個(gè)Agent平臺那么學(xué)一套新框架、維護(hù)一套新服務(wù)是有成本的。Agent-Reach這種服務(wù)層更適合兩三個(gè)人或以上的團(tuán)隊(duì)來共同維護(hù)。一個(gè)人用你可能會(huì)覺得它在給你增加工作量而不是減少工作量。5.3 下一步請求回放和自動(dòng)降級Agent-Reach目前還只是1.x版本下一步我最想做的兩件事是“請求回放”和“自動(dòng)降級”。請求回放指的是把每個(gè)連接器接收到的請求和響應(yīng)堆疊起來在測試環(huán)境里模擬用戶流量驗(yàn)證新發(fā)布的連接器版本不會(huì)出現(xiàn)兼容性問題。這件事已經(jīng)在手工做下一步想通過改造連接器的SDK在本地打一個(gè)快照文件然后有工具可以一鍵重放。這對做后端系統(tǒng)的開發(fā)同學(xué)來說應(yīng)該很熟悉道理跟HTTP流量回放工具是一樣的。自動(dòng)降級則要溫柔得多。當(dāng)某個(gè)連接器進(jìn)入半開狀態(tài)的時(shí)候我希望Agent-Reach可以自動(dòng)返回一個(gè)“能力降級”信號讓Agent選擇使用備用方案比如發(fā)站內(nèi)信而不是發(fā)郵件。我現(xiàn)在只實(shí)現(xiàn)了“快速失敗”還做不到“優(yōu)雅降級”。要讓Agent知道“現(xiàn)在這個(gè)渠道不行了你可以換個(gè)渠道”這需要Agent那邊配合做決策邏輯不是Agent-Reach單側(cè)能完成的。這個(gè)方向我會(huì)繼續(xù)做下去。到目前為止Agent-Reach教給我的最深刻的一件事是Agent本身的聰明程度最終會(huì)受限于它觸達(dá)世界的能力邊界。把觸達(dá)這條路修穩(wěn)了上面跑多少Agent心里都不慌。