戰(zhàn):構(gòu)建大模型觸達(dá)層,讓Agent真正調(diào)用工具與系統(tǒng))
我最早關(guān)注到“Agent-Reach”這個(gè)名字倒不是因?yàn)樗壎耸裁创髲S背景而是這個(gè)名字把一件事說透了reach觸達(dá)。做AI應(yīng)用折騰得久的人都清楚模型再聰明如果夠不到真實(shí)世界里的數(shù)據(jù)和工具它就只能做一個(gè)答錄機(jī)式的學(xué)霸——你說一句它回一句但什么實(shí)際的事都干不了。Agent-Reach核心在做的事就是把LLM從“會說話”推到“會動手”讓Agent去調(diào)用API、查數(shù)據(jù)庫、操作內(nèi)部系統(tǒng)、觸發(fā)工作流。這一層能力業(yè)內(nèi)通常叫“觸達(dá)層”或者“行動層”是Agent從Demo走向業(yè)務(wù)場景最被低估的一環(huán)。這篇文章我想以自己動手搭建和調(diào)優(yōu)這個(gè)系統(tǒng)時(shí)的視角把Agent-Reach的項(xiàng)目思路、模塊設(shè)計(jì)、最小復(fù)現(xiàn)步驟、踩坑實(shí)錄和落地建議從頭到尾講一遍。適合正在做Agent應(yīng)用、想做AI自動化或者準(zhǔn)備把智能體接到公司內(nèi)部系統(tǒng)里的朋友參考。我會盡量把參數(shù)、邏輯和“為什么這么做”都拆開講不寫那種看著高大上但回去根本跑不起來的偽教程。1. Agent-Reach到底在解決什么問題1.1 Agent的“腦”和“手”為什么總是脫節(jié)先聊一個(gè)很基礎(chǔ)的觀察。拿大模型本身的能力來說無論是文本生成、代碼補(bǔ)全還是復(fù)雜推理最近幾年的進(jìn)步其實(shí)都超出了絕大多數(shù)人的日常需求。但你真讓一個(gè)純模型去“幫我訂一間明天下午的會議室”它大概率能寫出一段Python腳本卻沒法真的打開公司的會議室系統(tǒng)去下單。問題不在模型而在它沒有通道、沒有授權(quán)、沒有方法去觸碰外部系統(tǒng)。這就是Agent和聊天機(jī)器人的本質(zhì)差異聊天機(jī)器人追求的是回答質(zhì)量Agent追求的是任務(wù)完成度。而完成一個(gè)任務(wù)尤其是企業(yè)場景里的任務(wù)必然涉及系統(tǒng)調(diào)用、權(quán)限校驗(yàn)、數(shù)據(jù)回寫、異常處理。Agent-Reach就是這一層的定位它不負(fù)責(zé)模型的推理能力只負(fù)責(zé)讓模型產(chǎn)出的“意圖”變成真實(shí)的“動作”再把動作的結(jié)果回喂給模型支撐下一步?jīng)Q策。用生活化的方式理解模型是大腦工具是手腳Agent-Reach就像是神經(jīng)系統(tǒng)和血管系統(tǒng)。大腦決定“我要倒一杯水”但你得有一條通路讓信號到達(dá)手指手指還得真的能握住杯子并且把杯子拿回來。沒有這條通路大腦想再多也沒用。1.2 真正值得做Agent的場景長什么樣聊幾個(gè)我在實(shí)際項(xiàng)目里看到的高價(jià)值場景你會發(fā)現(xiàn)它們有一個(gè)共同點(diǎn)不是在聊天窗口里陪你聊而是要操作某個(gè)系統(tǒng)并且要對自己的操作負(fù)責(zé)。第一個(gè)場景是客服工單處理。用戶說“我上個(gè)月買的東西壞了想申請退貨”Agent要做的不是回答“請聯(lián)系客服”而是先去訂單系統(tǒng)里查訂單是否存在確認(rèn)是否在退貨期內(nèi)再調(diào)用售后接口創(chuàng)建退款單并把工單號返回給用戶。整個(gè)過程涉及到查詢、判斷、寫操作和狀態(tài)回傳每一個(gè)動作都依賴觸達(dá)層。第二個(gè)場景是運(yùn)營自動化。比如社群運(yùn)營Agent它需要定時(shí)去數(shù)據(jù)后臺拉取昨日的轉(zhuǎn)化率對比目標(biāo)值決定是否觸發(fā)一次優(yōu)惠券發(fā)放再調(diào)用消息推送系統(tǒng)把文案發(fā)出去。這個(gè)鏈路里如果沒有觸達(dá)層Agent就只是一個(gè)“分析顧問”而不是“執(zhí)行者”。第三個(gè)場景是內(nèi)部知識庫助理。企業(yè)里的知識庫散落在Wiki、文件夾、IM聊天記錄里助理Agent要能精確檢索特定權(quán)限范圍內(nèi)的資料同時(shí)遵守“某些文檔只能總監(jiān)以上查看”這類規(guī)則。觸達(dá)層在這里不僅是調(diào)API還要負(fù)責(zé)權(quán)限判斷和數(shù)據(jù)隔離。這些場景的共同點(diǎn)決定了Agent-Reach必須是一個(gè)“基礎(chǔ)設(shè)施”性質(zhì)的系統(tǒng)而不是某個(gè)業(yè)務(wù)里的補(bǔ)丁。它需要有清晰的接口規(guī)范、工具注冊機(jī)制、記憶管理、權(quán)限控制和可觀測性。這也是我寫這篇文章的動因真正值得參考的Agent項(xiàng)目技術(shù)含量往往不在花哨的提示詞上而在這一層層連接真實(shí)世界的“管道工程”里。2. 系統(tǒng)架構(gòu)拆解Agent-Reach的四個(gè)核心模塊2.1 調(diào)度核心誰來決定Agent先動哪只手Agent-Reach的第一個(gè)核心模塊是確定性調(diào)度器也就是Orchestrator。它負(fù)責(zé)把模型的輸出拆解為一系列“意圖-參數(shù)-工具”三元組然后決定執(zhí)行順序和依賴關(guān)系。整個(gè)流程一般走四步意圖識別把用戶輸入交給LLM要求它輸出一個(gè)結(jié)構(gòu)化的JSON內(nèi)容包括意圖名、關(guān)鍵參數(shù)和置信度。路由匹配調(diào)度器拿到JSON后去工具注冊中心里找匹配的工具。匹配依據(jù)不光是名字還有參數(shù)schema是否吻合。執(zhí)行編排如果任務(wù)需要多個(gè)工具協(xié)作比如“先查訂單再申請退款”調(diào)度器要維護(hù)一個(gè)執(zhí)行隊(duì)列前一個(gè)工具的輸出作為后一個(gè)工具的輸入。結(jié)果回寫每步執(zhí)行結(jié)果都會作為一個(gè)“觀察”重新填入上下文讓模型知道當(dāng)前狀態(tài)以便決定下一步。我在實(shí)際搭建時(shí)有一個(gè)體會調(diào)度核心的設(shè)計(jì)不要一開始就做得很復(fù)雜。很多框架喜歡引入復(fù)雜的規(guī)劃器、任務(wù)分解器、多輪自省循環(huán)但真實(shí)業(yè)務(wù)場景里80%的任務(wù)其實(shí)是單工具調(diào)用或者兩三個(gè)工具的簡單串聯(lián)。做得太重反而延遲高、調(diào)試難。比較好的起步做法是給調(diào)度器配一個(gè)“路由優(yōu)先級”策略——能匹配到單一工具就絕不走多工具編排多工具場景先用模板化鏈路跑等積累了足夠的成功案例再考慮引入模型自規(guī)劃。這個(gè)優(yōu)先級策略能顯著降低最初幾個(gè)月的故障率。2.2 工具注冊中心給Agent一張“可用的物清單”如果說調(diào)度核心是大腦的決策層那工具注冊中心就是Agent的“目錄頁”。它讓Agent知道自己能做什么、每個(gè)工具有什么參數(shù)、調(diào)用之后會返回什么。設(shè)計(jì)工具注冊中心時(shí)最關(guān)鍵的一個(gè)概念是工具描述Tool Schema。每個(gè)工具都要被描述成模型能讀懂的元數(shù)據(jù)通常包含字段作用示例name工具唯一標(biāo)識用于路由匹配order_querydescription一句話說明工具能做什么給LLM判斷用根據(jù)訂單ID查詢訂單狀態(tài)和物流信息parametersJSON Schema格式的參數(shù)聲明{order_id: string(required)}return_schema返回結(jié)果的字段結(jié)構(gòu)方便解析{status, logistics, eta}permission_level調(diào)用此工具所需的最小權(quán)限r(nóng)ead_only/write這一段看起來很簡單但實(shí)操里我踩過最大的坑就是description寫得太含糊。LLM是用語義來匹配工具的你寫“查詢訂單”和寫“根據(jù)訂單號返回訂單當(dāng)前狀態(tài)、是否可退貨、物流單號”后者在意圖識別階段的命中率會明顯更高。所以工具描述不是給人看的文檔而是給模型看的路標(biāo)寫得越具體、越帶邊界條件路由越準(zhǔn)。另一個(gè)實(shí)用的設(shè)計(jì)是工具分組與別名機(jī)制。同一類工具加一個(gè)前綴分組比如order_query、order_create、order_refund都屬于order域調(diào)度器在意圖模糊時(shí)可以先鎖定“域”縮小候選集再在域內(nèi)做精確匹配。這個(gè)分層匹配策略在工具數(shù)量超過20個(gè)之后價(jià)值會越來越明顯。2.3 雙棧記憶結(jié)構(gòu)化短期與長期如何分工Agent的觸達(dá)能力不僅取決于當(dāng)下一次調(diào)用還取決于它能不能記住歷史。Agent-Reach的記憶模塊我設(shè)計(jì)成“雙棧”短期棧運(yùn)行在上下文窗口內(nèi)長期棧落到向量數(shù)據(jù)庫里。短期棧處理的是當(dāng)前任務(wù)會話的即時(shí)信息比如用戶剛說的訂單號、上一步查詢返回的關(guān)鍵字段。這些內(nèi)容會隨著每輪工具調(diào)用動態(tài)更新。需要注意的是短期棧必須做裁剪控制不能把所有歷史都塞給LLM。我的做法是只保留最后兩輪對話摘要本輪所有工具調(diào)用的結(jié)果摘要其他內(nèi)容壓縮成一個(gè)短句放在上下文最前面。這么做一是省token二是能顯著降低模型被無關(guān)信息干擾的概率。長期棧存的是跨會話的“常識性狀態(tài)”比如用戶的偏好、某個(gè)訂單的歷史溝通記錄、某些主數(shù)據(jù)字典。它的作用在于當(dāng)Agent面對一個(gè)全新會話時(shí)不需要用戶重復(fù)所有背景信息。長期棧的寫入時(shí)機(jī)也很有講究不是每次工具調(diào)用都值得寫長期記憶而是在一個(gè)任務(wù)閉環(huán)結(jié)束成功或者確認(rèn)失敗后把關(guān)鍵結(jié)論寫入。記憶模塊單獨(dú)提出來講是因?yàn)樗钊菀妆怀鯇W(xué)者忽略。很多人覺得只要把上下文窗口拉長、歷史消息全部塞進(jìn)去就行。結(jié)果實(shí)際跑起來要么成本爆炸要么模型開始被舊信息帶偏在關(guān)鍵參數(shù)上張冠李戴。好的Agent不是“記得多”而是“記得準(zhǔn)”。2.4 權(quán)限門禁Agent可以亂跑嗎任何允許Agent執(zhí)行寫操作的場景權(quán)限門禁都是必須做的。Agent-Reach里權(quán)限控制不只是在工具層加一個(gè)token而是要形成“三重門”機(jī)制。第一重是身份識別。Agent當(dāng)前是替哪個(gè)用戶或哪個(gè)系統(tǒng)身份在執(zhí)行操作不同的身份能調(diào)用的工具范圍不一樣。比如普通員工身份的Agent能查自己的訂單但不能查別人的訂單。第二重是操作分級。所有工具按影響程度分為三檔只讀操作、普通寫操作、高危操作。只讀操作直接執(zhí)行普通寫操作需要檢查是否有明確授權(quán)高危操作比如退款、刪除、批量發(fā)消息必須額外走一次“用戶確認(rèn)”或“二次規(guī)則校驗(yàn)”的環(huán)節(jié)。第三重是審計(jì)留痕。每一次觸達(dá)動作都要記錄時(shí)間、工具、參數(shù)、返回碼、調(diào)用者身份。這不僅是為了出問題后排查更是為了持續(xù)優(yōu)化路由策略——你積累了三個(gè)月日志后會發(fā)現(xiàn)哪些工具經(jīng)常匹配錯(cuò)、哪些參數(shù)經(jīng)常傳錯(cuò)這比任何評測集都更接近真實(shí)業(yè)務(wù)。有一點(diǎn)特別提醒權(quán)限門禁一開始就設(shè)計(jì)比后期補(bǔ)要容易得多。我有一次在一個(gè)演示項(xiàng)目里偷懶先只接了只讀接口后來想加一個(gè)寫接口時(shí)發(fā)現(xiàn)好幾個(gè)地方都得改包括Prompt里的工具說明、路由層的白名單、審計(jì)日志字段。補(bǔ)這三處改造的維護(hù)成本遠(yuǎn)高于最初花半天時(shí)間把門禁搭好。3. 30分鐘跑通一個(gè)Agent-Reach最小鏈路3.1 準(zhǔn)備最小環(huán)境紙上談兵沒意思我直接演示一下怎么從零跑通一個(gè)最小可用的Agent-Reach鏈路。這里我用Python來實(shí)現(xiàn)核心依賴只有三個(gè)一個(gè)用來調(diào)用LLM的客戶端這里用OpenAI兼容接口、一個(gè)輕量HTTP框架FastAPI或者Flask都行、一個(gè)最簡單的內(nèi)存數(shù)據(jù)庫用來模擬訂單系統(tǒng)。整個(gè)Demo要完成的任務(wù)是用戶輸入“幫我查一下訂單B1024現(xiàn)在到哪了”Agent自動判斷意圖調(diào)用訂單查詢工具返回物流狀態(tài)信息。代碼結(jié)構(gòu)分成兩層外層是工具定義與注冊模塊內(nèi)層是調(diào)度核心。這里我刻意不用LangGraph這類重框架就是為了讓你看清每一行代碼到底在做決策而不是被框架的高層抽象掩蓋掉細(xì)節(jié)。3.2 先定義兩個(gè)工具查詢訂單和創(chuàng)建工單我們先用Python定義一個(gè)查詢訂單的工具并且把它注冊到工具注冊中心。為了模擬真實(shí)場景我同時(shí)列一個(gè)風(fēng)險(xiǎn)更高的“創(chuàng)建退款工單”工具用來演示權(quán)限門禁。# tools/order_tools.py from pydantic import BaseModel class OrderQueryParams(BaseModel): order_id: str include_logistics: bool True class OrderQueryTool: name order_query description 根據(jù)訂單ID查詢訂單當(dāng)前狀態(tài)、物流進(jìn)度、預(yù)計(jì)送達(dá)時(shí)間。適合用戶詢問訂單到哪了有沒有發(fā)貨什么時(shí)候到等意圖。 parameters { type: object, properties: { order_id: {type: string, description: 用戶的訂單編號}, include_logistics: {type: boolean, description: 是否同時(shí)返回物流軌跡} }, required: [order_id] } permission_level read_only def run(self, params: dict): # 這里模擬真實(shí)查詢 order_id params[order_id] fake_db { B1024: {status: 已發(fā)貨, logistics: 杭州轉(zhuǎn)運(yùn)中心, eta: 明天18:00前} } return fake_db.get(order_id, {status: 未找到, logistics: , eta: })第二個(gè)工具是寫操作示例創(chuàng)建退款工單class RefundTicketTool: name refund_ticket_create description 為用戶創(chuàng)建退款申請工單需要調(diào)用售后系統(tǒng)會進(jìn)入審批流程。僅當(dāng)用戶明確表示要退款或退貨時(shí)才能調(diào)用。 parameters { type: object, properties: { order_id: {type: string}, reason: {type: string} }, required: [order_id, reason] } permission_level high_risk def run(self, params: dict): return {ticket_id: TKT20250611001, status: pending_review}注意一下兩個(gè)工具description的寫法我把用戶可能怎么問的話也融進(jìn)去了這個(gè)細(xì)節(jié)在后面路由測試時(shí)會直接影響意圖識別的命中率。3.3 用一段路由腳本把模型輸出變成真實(shí)調(diào)用工具定義好之后核心的調(diào)度腳本登場。這段腳本的邏輯很直白先把用戶輸入交給LLM要求它輸出一個(gè)包含tool_name和arguments的JSON然后根據(jù)工具注冊表做匹配最后執(zhí)行并返回結(jié)果。這里的關(guān)鍵技巧是不要用自由文本通信給LLM一個(gè)嚴(yán)格的結(jié)構(gòu)化輸出約束。# scheduler.py import json from openai import OpenAI from tools.order_tools import OrderQueryTool, RefundTicketTool client OpenAI(base_urlhttp://localhost:8000/v1, api_keylocal) TOOL_REGISTRY { order_query: OrderQueryTool, refund_ticket_create: RefundTicketTool, } SYSTEM_PROMPT 你是一個(gè)任務(wù)路由助手。你的工作是根據(jù)用戶輸入判斷要調(diào)用哪個(gè)工具。 工具清單如下 - order_query: 根據(jù)訂單ID查詢訂單狀態(tài)和物流信息 - refund_ticket_create: 為用戶創(chuàng)建退款工單進(jìn)入審批流程 請輸出嚴(yán)格JSON格式為 {tool_name: 工具名, arguments: {參數(shù)名: 參數(shù)值}} 如果用戶輸入無法匹配任何工具輸出 {tool_name: no_match, arguments: {}} 注意只有用戶明確表達(dá)退款意愿時(shí)才能選refund_ticket_create。 def route_and_execute(user_input: str): resp client.chat.completions.create( modelgpt-4o-mini, # 可用任何兼容接口的模型 messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_input} ], response_format{type: json_object} ) parsed json.loads(resp.choices[0].message.content) tool_name parsed[tool_name] if tool_name no_match: return {action: clarify, message: 請問您想查詢訂單還是申請退款} if tool_name not in TOOL_REGISTRY: return {action: error, message: 未知工具} tool_cls TOOL_REGISTRY[tool_name] tool tool_cls() # 這里是權(quán)限門禁的最簡實(shí)現(xiàn) if getattr(tool, permission_level, read_only) high_risk: return { action: confirmation_required, message: f您確認(rèn)要執(zhí)行{tool.description}嗎請回復(fù)確認(rèn)。 } result tool.run(parsed[arguments]) return {action: success, tool: tool_name, result: result} # 模擬一次調(diào)用 if __name__ __main__: print(route_and_execute(幫我查一下B1024現(xiàn)在到哪了))這整個(gè)腳本沒有用到任何Agent框架但它已經(jīng)具備了一個(gè)真實(shí)推理系統(tǒng)最重要的三條鏈路意圖識別、工具路由、權(quán)限檢查。我覺得看這段代碼比看一堆框架文檔更直觀。3.4 實(shí)測一輪完整鏈路并記錄輸出我本地跑了一次完整流程模型返回了下面這段中間結(jié)果{tool_name: order_query, arguments: {order_id: B1024, include_logistics: true}}調(diào)度器拿到這個(gè)JSON后在工具注冊表里查到了order_query檢查權(quán)限級別是read_only直接放行。工具執(zhí)行后返回{status: 已發(fā)貨, logistics: 杭州轉(zhuǎn)運(yùn)中心, eta: 明天18:00前}我再把這段結(jié)果和一句摘要回寫給LLM讓它組織成用戶能看懂的話“您的訂單B1024已經(jīng)發(fā)貨目前到達(dá)杭州轉(zhuǎn)運(yùn)中心預(yù)計(jì)明天18:00前送達(dá)?!边@個(gè)鏈路里最值得注意的點(diǎn)在于工具執(zhí)行的實(shí)際結(jié)果沒有直接暴露給用戶而是先回傳給了LLM由LLM根據(jù)結(jié)果生成最終回答。這樣做的好處是即使工具返回的是結(jié)構(gòu)化但晦澀的數(shù)據(jù)用戶也能得到自然語言層面的清晰反饋。我還專門測了一下“用戶沒說清楚訂單號但提到退款”的場景。輸入是“那單我想退了”模型在路由階段的判斷是調(diào)用refund_ticket_create但因?yàn)閰?shù)里沒有order_id它返回的JSON里arguments是空的。這時(shí)候調(diào)度器應(yīng)該再做一次參數(shù)校驗(yàn)發(fā)現(xiàn)必填參數(shù)缺失就回問用戶具體單號。這個(gè)參數(shù)校驗(yàn)環(huán)節(jié)在Demo腳本里被我簡化掉了但實(shí)際上生產(chǎn)環(huán)境里一定要在路由腳本里加一段“參數(shù)完整性檢查”否則模型生成一個(gè)殘缺的參數(shù)任務(wù)時(shí)工具層會直接報(bào)500錯(cuò)誤。4. 踩坑實(shí)錄Agent-Reach實(shí)戰(zhàn)中的常見問題4.1 工具命中率低先從這五個(gè)方向查工具路由的命中率是Agent-Reach這類系統(tǒng)最核心的指標(biāo)。我最早調(diào)試時(shí)命中率只有六成左右一開始以為是模型能力不行后來逐個(gè)案例排查才發(fā)現(xiàn)原因五花八門。這里整理成一張速查表癥狀最常見原因排查方法相同問題有時(shí)路由對有時(shí)不對Prompt里工具描述不夠具體模型產(chǎn)生語義搖擺在工具description里加入用戶典型問法示例總選錯(cuò)同類工具兩個(gè)工具描述高度相似邊界條件沒寫清在description里明確“什么情況絕對不能選我”參數(shù)總是多傳或少傳參數(shù)的JSON Schema缺少required約束或缺少默認(rèn)值聲明詳細(xì)檢查parameters定義補(bǔ)充example字段低危工具被要求二次確認(rèn)權(quán)限分級太粗把只讀工具誤標(biāo)為write檢查permission_level賦值最好做一次工具全量復(fù)審長句子輸入頻繁誤判調(diào)度器沒有做意圖分域所有工具一把梭改為“域內(nèi)匹配”先用關(guān)鍵詞鎖定業(yè)務(wù)域再選工具我強(qiáng)烈建議你給自己搭一個(gè)回歸測試集準(zhǔn)備30到50條歷史真實(shí)用戶輸入每一條都標(biāo)注好期望路由到哪個(gè)工具。每次修改Prompt或者工具描述后跑一遍全量回歸對比命中率變化。這一步幾乎不花多少成本但能攔住大量看起來沒問題的改動。4.2 模型幻覺調(diào)用工具怎么兜底在Agent-Reach這種觸達(dá)系統(tǒng)里有一類事故比普通LLM幻覺更危險(xiǎn)模型在參數(shù)上“編造”。比如它只猜到了一個(gè)order_id的值就當(dāng)成真實(shí)參數(shù)傳給了系統(tǒng)。這類問題無法100%靠模型自我檢查解決必須靠系統(tǒng)層兜底。我的處理方式分三層第一層是參數(shù)格式校驗(yàn)不符合格式規(guī)范的請求直接拒絕。第二層是存在性校驗(yàn)在調(diào)用真實(shí)工具前先跑一個(gè)只讀的預(yù)檢接口確認(rèn)訂單號、用戶ID這類關(guān)鍵外鍵是否真實(shí)存在。第三層是降級確認(rèn)如果預(yù)檢失敗或者參數(shù)置信度低于預(yù)設(shè)閾值就把任務(wù)狀態(tài)轉(zhuǎn)為“需要二次確認(rèn)”不讓Agent硬著頭皮執(zhí)行。這套兜底邏輯在營銷場景里尤其重要。比如Agent自動給用戶發(fā)放優(yōu)惠券一旦用了編造出來的用戶ID去調(diào)用優(yōu)惠系統(tǒng)輕則發(fā)錯(cuò)人重則造成資損。安全邊際永遠(yuǎn)要畫在系統(tǒng)層而不是寄托于模型“這次應(yīng)該不會騙我”。4.3 記憶串頻短期上下文被無關(guān)信息撐爆另一個(gè)高頻問題發(fā)生在記憶模塊。最開始我為了追求“Agent能記住所有上下文”把所有工具返回的原始JSON都直接塞進(jìn)歷史消息里。結(jié)果跑了二十多輪后上下文里堆滿了時(shí)間戳、無意義的字段名和重復(fù)的中間結(jié)果。模型在處理新任務(wù)時(shí)經(jīng)常把這些歷史殘留當(dāng)成當(dāng)前任務(wù)的數(shù)據(jù)導(dǎo)致參數(shù)提取錯(cuò)誤。后來我改成“摘要優(yōu)先”策略工具返回的完整JSON只保留在內(nèi)部瞬時(shí)日志里不進(jìn)上下文。進(jìn)入上下文的是模型針對工具輸出生成的“觀察摘要”比如“訂單B1024狀態(tài)已發(fā)貨預(yù)計(jì)明天送達(dá)”。超過兩輪的對話信息只保留一句話級別的會話小結(jié)。這一個(gè)改動讓路由準(zhǔn)確率回升了不少而且token消耗下降了將近40%。記憶管理不是越存越多越好而是要讓模型在當(dāng)下每一步都能看到“最新、最必要”的狀態(tài)。4.4 外部服務(wù)一卡Agent就卡死觸達(dá)系統(tǒng)的穩(wěn)定性瓶頸經(jīng)常不在模型而在被調(diào)用的外部服務(wù)。我遇到過第三方物流查詢接口超時(shí)也遇到過內(nèi)部數(shù)據(jù)庫連接池被占滿Agent在等結(jié)果時(shí)直接把整個(gè)調(diào)度線程卡住的情況。解決辦法是給每一個(gè)工具調(diào)用加“三層防護(hù)”超時(shí)、重試、降級。先說超時(shí)。每個(gè)工具調(diào)用必須設(shè)置合理的超時(shí)時(shí)間我一般默認(rèn)5秒高延遲的報(bào)表類工具可以放寬到15秒。超時(shí)后不是傻等而是直接進(jìn)入異常隊(duì)列。再說重試。對于冪等類的查詢接口重試是安全的我采用“指數(shù)退避抖動”策略第一次失敗等1秒第二次等2秒第三次等4秒最多3次。寫操作接口則不做自動重試避免因?yàn)榫W(wǎng)絡(luò)分區(qū)導(dǎo)致同一操作被重復(fù)提交。最后是降級。外部服務(wù)不可用時(shí)Agent不能只回一句“系統(tǒng)繁忙”而要將任務(wù)標(biāo)記為“待恢復(fù)”同時(shí)把上下文狀態(tài)完整暫存。等服務(wù)恢復(fù)后可以允許用戶用一句話繼續(xù)任務(wù)“再幫我查一下剛才那個(gè)訂單?!比绻麤]有降級設(shè)計(jì)用戶只能從頭再來一遍體驗(yàn)很差。5. 從Demo到生產(chǎn)把Agent-Reach接入業(yè)務(wù)系統(tǒng)時(shí)我的建議5.1 先接只讀場景別一上來就開寫權(quán)限如果要我把這套系統(tǒng)接到公司內(nèi)部業(yè)務(wù)里去我的第一個(gè)建議永遠(yuǎn)是先做只讀場景上線。只讀工具體系里最安全查詢訂單、查庫存、搜文檔、拉報(bào)表出了問題最多是數(shù)據(jù)展示錯(cuò)誤不至于造成資損或者其他不可逆的影響。只讀場景跑一到兩個(gè)月積累足夠的日志后你才能摸清楚模型在當(dāng)前業(yè)務(wù)語境下的路由規(guī)律。比如哪些工具描述徹底解決歧義、哪些業(yè)務(wù)術(shù)語模型總是理解偏。當(dāng)只讀場景的命中率穩(wěn)定在可接受范圍再逐步加入“有確認(rèn)機(jī)制”的寫操作最后才考慮自動化程度更高的高危操作。5.2 可觀測性平臺一定是先行的生產(chǎn)環(huán)境里Agent-Reach這類觸達(dá)系統(tǒng)的故障定位難度遠(yuǎn)高于傳統(tǒng)API服務(wù)。因?yàn)橐淮问】赡苁悄P驼`判、路由錯(cuò)誤、參數(shù)缺失、外部接口異常、權(quán)限不足這五類原因中的任意一種。沒有好的觀測手段排查會變成一場災(zāi)難。我在生產(chǎn)部署時(shí)至少會記錄四類日志用戶輸入原文、模型輸出的JSON中間結(jié)果、調(diào)度器路由決策含優(yōu)先級、工具執(zhí)行的輸入輸出和耗時(shí)。每一類日志帶上唯一請求ID用這個(gè)ID可以把整條鏈路串起來。有了這個(gè)請求追蹤協(xié)議用戶說“剛才查的東西卡了”你就能順著時(shí)間線把所有環(huán)節(jié)還原一遍而不是靠猜。5.3 規(guī)則兜底比模型兜底更可靠最后一條建議是方向性的在觸達(dá)系統(tǒng)里能用規(guī)則解決的就用規(guī)則解決不要什么都甩給模型。比如限制退款金額上限、限制單日操作次數(shù)、禁止批量調(diào)用寫接口這類邏輯屬于確定性約束直接寫在代碼里比在Prompt里反復(fù)強(qiáng)調(diào)可靠得多。我見過團(tuán)隊(duì)花兩個(gè)星期微調(diào)Prompt只為了“讓Agent不要連續(xù)調(diào)用同一個(gè)工具”其實(shí)代碼里加一個(gè)“同工具冷卻時(shí)間”計(jì)數(shù)器就能解決。模型是動態(tài)的、概率的規(guī)則是靜態(tài)的、確定的。Agent-Reach這類系統(tǒng)的最佳實(shí)踐是把確定性的部分全部下沉到規(guī)則里把模糊判斷的部分留給模型。你越早想清楚這個(gè)邊界系統(tǒng)就越穩(wěn)。我自己在反復(fù)迭代這套觸達(dá)系統(tǒng)的過程中最強(qiáng)烈的感受是讓Agent學(xué)會調(diào)用工具不難難的是讓它在一堆真實(shí)系統(tǒng)、真實(shí)權(quán)限、真實(shí)異常之間保持穩(wěn)定。Agent-Reach把這個(gè)“難”集中到觸達(dá)層來解決相當(dāng)于把原本散落在各個(gè)應(yīng)用里的“工具調(diào)用硬編碼”收攏成了一個(gè)具備通用性的基礎(chǔ)設(shè)施。如果你也在做Agent項(xiàng)目不妨從今天開始給你的Agent裝一只能真正“夠到世界”的手。