戰(zhàn):從工具調(diào)用到安全護(hù)欄的Agent開發(fā)指南)
做了一年多 AI Agent 開發(fā)我越來越認(rèn)同一個(gè)判斷Agent 的真正差異不在模型多強(qiáng)而在它“夠得著”多少東西。模型再聰明如果連瀏覽器都沒法打開、文件沒法讀寫、外部服務(wù)沒法調(diào)用那它充其量是個(gè)高級(jí)聊天框。我最近在做的這個(gè)項(xiàng)目代號(hào)就叫 Agent-Reach核心理念很簡單——把 Agent 從對(duì)話里解放出來讓它通過工具、技能、記憶和安全邊界真正觸達(dá)外部世界并完成任務(wù)。這個(gè)項(xiàng)目做下來我把 Agent 開發(fā)里踩過的坑幾乎都重新踩了一遍架構(gòu)選型、工具調(diào)用、上下文管理、安全控制、評(píng)測閉環(huán)。這篇文章就圍繞 Agent-Reach 的記錄展開講清楚我在設(shè)計(jì) Agent 架構(gòu)、搭建 Agent 框架、處理 Agent 記憶和 Agent 安全時(shí)的具體做法。不管你是剛準(zhǔn)備入門 Agent 開發(fā)還是已經(jīng)在用 LangChain、Dify、CrewAI 這類框架搭過原型都應(yīng)該能從這篇文章里找到一些能直接抄作業(yè)的東西。1. 為什么是 Agent-Reach這個(gè)項(xiàng)目的起點(diǎn)和它想解決的問題1.1 一個(gè)容易被低估的問題Agent 到底“夠得著”什么在做 Agent-Reach 之前我做過一個(gè)內(nèi)部知識(shí)庫問答機(jī)器人效果不錯(cuò)但它不是 Agent因?yàn)樗粫?huì)“答”不會(huì)“做”。后來業(yè)務(wù)方提了個(gè)需求能不能讓機(jī)器人幫忙查詢訂單、導(dǎo)出報(bào)表、跟進(jìn)異常流程這就從 RAG 走到了 Agent 開發(fā)。我這才意識(shí)到真正的分水嶺不是對(duì)話能力而是“觸達(dá)能力”?!坝|達(dá)”是個(gè)很具體的工程問題Agent 要調(diào)用哪些外部能力參數(shù)怎么傳結(jié)果怎么回中間出錯(cuò)怎么辦操作會(huì)不會(huì)有危險(xiǎn)模型沒有手工具就是它的手而 Agent-Reach 的全部工作就是給模型配好這套手并且保證每一只手伸出去之后都能安全收回來。這也是項(xiàng)目名 Reach 的由來——不是“搜索”不是“回答”而是“到達(dá)”。一個(gè)任務(wù)無論多復(fù)雜最終都要落到某個(gè)具體動(dòng)作上讀寫文件、請(qǐng)求接口、生成圖片、更新數(shù)據(jù)庫。Agent 能不能到達(dá)那個(gè)動(dòng)作、完成那個(gè)動(dòng)作決定了它到底是玩具還是生產(chǎn)力工具。1.2 Agent-Reach 的項(xiàng)目定位與功能范圍Agent-Reach 不是一個(gè)從零自研框架的大工程而是一個(gè)以“任務(wù)可達(dá)”為目標(biāo)的 Agent 開發(fā)項(xiàng)目。它的目標(biāo)很樸素給定一個(gè)自然語言任務(wù)Agent 能自主完成規(guī)劃、執(zhí)行、驗(yàn)證、匯報(bào)四步閉環(huán)。這里我把功能范圍劃成五條主線工具與技能層Agent 能通過注冊(cè)機(jī)制調(diào)用外部工具每個(gè)工具都有清晰的名稱、描述、參數(shù)結(jié)構(gòu)和權(quán)限等級(jí)。任務(wù)編排層拆解復(fù)雜任務(wù)串聯(lián)多個(gè)步驟支持單 Agent 和多 Agent 協(xié)作。記憶層區(qū)分短期工作記憶和長期記憶避免上下文無限膨脹。安全與沙箱關(guān)鍵操作受限執(zhí)行超時(shí)、失敗、越權(quán)都有兜底。評(píng)測與觀測有可復(fù)跑的任務(wù)評(píng)測集有全鏈路日志能判斷每次改動(dòng)是變好還是變壞。這五條主線基本就是各大 Agent 框架都在解決的核心問題。我說得直白一點(diǎn)如果你能自己動(dòng)手實(shí)現(xiàn)一遍這五條主線再用某個(gè)框架重新組織一遍你對(duì) Agent 架構(gòu)的理解會(huì)比只看文檔深得多。Agent-Reach 就是我做這件事的載體。這個(gè)項(xiàng)目適合誰我按自己的經(jīng)驗(yàn)說兩類人最合適一種是已經(jīng)用現(xiàn)成框架搭過 Chatbot、想進(jìn)一步理解 Agent 原理的開發(fā)另一種是在做“Agent 應(yīng)用落地”時(shí)頻繁遇到工具調(diào)用、記憶、安全問題的工程師。至于零基礎(chǔ)的同學(xué)建議先把 Python 基礎(chǔ)和大模型 API 調(diào)用學(xué)明白再來看 Agent 架構(gòu)門檻會(huì)更低。2. Agent-Reach 的架構(gòu)取舍單Agent、多Agent和框架選擇背后的邏輯2.1 架構(gòu)設(shè)計(jì)的第一刀先想清楚任務(wù)邊界我見過很多 Agent 項(xiàng)目死于“一開始就搞多 Agent”。一上來就把一個(gè)任務(wù)拆成“主管 Agent 多個(gè)專家 Agent”聽起來很高端實(shí)際跑起來光協(xié)調(diào)消息就要占掉大量 token角色之間互相“踢皮球”的情況也時(shí)有發(fā)生。Agent-Reach 的第一版我堅(jiān)持用單 Agent 工具編排。單 Agent 的意思是一個(gè)大模型實(shí)例承擔(dān)整個(gè)任務(wù)的規(guī)劃與執(zhí)行它自己決定調(diào)用哪個(gè)工具、怎么處理工具返回的結(jié)果。這樣做的好處非常直接——調(diào)試路徑最短。一個(gè)任務(wù)就是“模型思考 - 調(diào)用工具 - 獲得結(jié)果 - 繼續(xù)思考”的循環(huán)任何一環(huán)出問題看 trace 就能定位。當(dāng)任務(wù)真正復(fù)雜到需要并行處理時(shí)我才會(huì)把它拆成多 Agent。比如“同時(shí)調(diào)研三個(gè)競爭對(duì)手的產(chǎn)品動(dòng)態(tài)”單 Agent 串行做太慢這時(shí)可以讓一個(gè)協(xié)調(diào)者 Agent 把任務(wù)廣播給三個(gè)執(zhí)行者 Agent等結(jié)果匯總后再由協(xié)調(diào)者統(tǒng)一輸出。多 Agent 適合的是“物理上可以并行”的任務(wù)而不是“聽起來很復(fù)雜”的任務(wù)這個(gè)判斷標(biāo)準(zhǔn)是我在這次項(xiàng)目里最重要的收獲之一。2.2 主流Agent框架橫向?qū)Ρ扰c我的選型結(jié)論做架構(gòu)選型時(shí)我把搜索熱度最高的幾個(gè)方案都試了一遍LangChain、Dify、CrewAI外加一個(gè)基于 Rust 的輕量 Agent 運(yùn)行時(shí)。說實(shí)話框架沒有絕對(duì)的好壞只有適不適合當(dāng)前階段。我整理了一張對(duì)比表框架擅長場景我實(shí)際踩到的問題LangChain代碼深度定制、鏈?zhǔn)骄幣?、生態(tài)齊全抽象層太多對(duì)新手不友好Debug 時(shí)容易陷入“把源碼翻穿”的困境Dify低代碼可視化、快速出 Demo、自帶 API 服務(wù)靈活度受限復(fù)雜條件分支不如代碼直觀定位更偏向運(yùn)營而非研發(fā)CrewAI多 Agent 角色扮演、協(xié)作任務(wù)、文檔清晰多 Agent 協(xié)調(diào)開銷大小任務(wù)用它是殺雞用牛刀Rust Agent性能敏感、端側(cè)部署、低資源占用生態(tài)仍在早期LLM 相關(guān)的 Python 庫用不了迭代效率低最終我的選型結(jié)論是Agent-Reach 的核心編排寫了一個(gè)輕量自研層同時(shí)保留 LangChain 的 Prompt 和模型封裝習(xí)慣并借鑒 CrewAI 的角色設(shè)計(jì)。說實(shí)話這個(gè)選擇也是被“逼”出來的。用現(xiàn)成框架時(shí)一旦遇到“工具返回格式不對(duì)導(dǎo)致模型反復(fù)調(diào)用”“上下文被塞滿后行為漂移”這類問題你很難在框架的抽象層里找到答案反而要自己去讀源碼、改回調(diào)。自研一個(gè)極簡編排層雖然代碼量多一點(diǎn)但每個(gè)環(huán)節(jié)都長在自己腦子里排錯(cuò)效率反而更高??蚣軕?yīng)當(dāng)是你的工具箱而不是你的天花板。2.3 為什么我把 Rust 放進(jìn)了備選方案“基于 Rust 語言 AI Agent”能進(jìn)入熱搜說明關(guān)注端側(cè) Agent 的人越來越多了。我也認(rèn)真調(diào)研過 Rust 路線Rust 的運(yùn)行時(shí)穩(wěn)定、內(nèi)存安全、部署方便在低資源設(shè)備上跑 Agent 有天然優(yōu)勢。如果 Agent-Reach 要往端側(cè)靠Rust 確實(shí)是一個(gè)值得押注的方向。但我最終沒有把核心 Agent 用 Rust 來寫原因很現(xiàn)實(shí)Agent 開發(fā)是典型的高速迭代場景今天的工具可能是文生圖明天可能是瀏覽器自動(dòng)化后天可能是訪問企業(yè)內(nèi)部系統(tǒng)。Python 生態(tài)里對(duì)應(yīng)的庫幾乎現(xiàn)成而 Rust 這邊很多能力要自己用 FFI 去綁綁一輪下來別家 Agent 已經(jīng)迭代了三個(gè)版本。所以我的處理方式是把 Rust 放在邊緣模塊做一些對(duì)性能敏感但又不需要頻繁改動(dòng)的公共組件比如大響應(yīng)內(nèi)容的解析、文件格式轉(zhuǎn)換、正則匹配這類活。核心的思考循環(huán)用 Python底層的“體力活”用 Rust 加速兩邊各取所長。如果你從頭開始做 Agent我的建議也是先用最快的方式跑通閉環(huán)再回頭看性能不要第一步就糾結(jié)語言。3. 工具調(diào)用與Skill機(jī)制讓Agent的手真正伸出去3.1 Skill系統(tǒng)設(shè)計(jì)的核心原則Agent 開發(fā)的第一個(gè)分水嶺是工具調(diào)用能不能做穩(wěn)。我在 Agent-Reach 里把“工具”封裝成“Skill”每個(gè) Skill 就是一個(gè)可復(fù)用的能力包。設(shè)計(jì) Skill 時(shí)我給自己定了三條硬原則名稱和描述必須讓模型一眼看懂什么時(shí)候該用。命名要具體描述要寫清楚輸入輸出和邊界條件。比如webpage_to_markdown比fetch_page好因?yàn)槟P涂吹胶笳邥?huì)困惑“fetch 回來之后呢是給我原文還是給我摘要”參數(shù)結(jié)構(gòu)必須嚴(yán)格校驗(yàn)。Agent 調(diào)用 Skill 時(shí)傳的參數(shù)來自模型生成經(jīng)常會(huì)出現(xiàn)缺字段、多了字段、類型不對(duì)的情況。Skill 入口必須做一層參數(shù)校驗(yàn)不合格就直接返回可讀的錯(cuò)誤信息而不是拋異常。執(zhí)行結(jié)果必須結(jié)構(gòu)化。我統(tǒng)一用“狀態(tài) 數(shù)據(jù) 錯(cuò)誤信息”三件套返回比如{status: ok, data: ...}或{status: error, message: timeout after 10s}。模型拿到結(jié)構(gòu)化的結(jié)果之后才能準(zhǔn)確判斷下一步該繼續(xù)還是該換個(gè)思路。這三條原則說起來簡單但每一步都有代價(jià)。寫完 Skill 注冊(cè)表之后我才感受到為什么很多框架把工具調(diào)用單獨(dú)做成一塊模型對(duì)工具的選擇本質(zhì)上是在做“模式匹配”你的工具描述寫得越像用戶真實(shí)需求模型選得越準(zhǔn)。描述不清晰后面一切優(yōu)化都是白搭。3.2 一個(gè)完整Skill示例網(wǎng)頁保存為MarkdownAgent-Reach 里我最常用的一個(gè) Skill 是把網(wǎng)頁保存成 Markdown。這個(gè)能力在文檔整理、競品調(diào)研、資料歸檔里都很實(shí)用。實(shí)現(xiàn)上我把它拆成四步抓取 HTML、解析主內(nèi)容、轉(zhuǎn)換 Markdown、保存到本地或上傳到知識(shí)庫。Skill 的注冊(cè)信息長這樣{ name: webpage_to_markdown, description: 抓取指定網(wǎng)頁并轉(zhuǎn)換為Markdown格式適用于保存網(wǎng)頁正文、整理資料、生成文檔, parameters: { type: object, properties: { url: { type: string, description: 需要轉(zhuǎn)換的網(wǎng)頁地址必須是 http/https 開頭的完整URL }, output_dir: { type: string, description: 保存目錄默認(rèn)使用當(dāng)前工作目錄下的 downloads 文件夾, default: downloads } }, required: [url] } }真正執(zhí)行時(shí)我要做三個(gè)額外保護(hù)第一只允許抓取白名單域名內(nèi)的頁面避免模型被誘導(dǎo)去訪問內(nèi)網(wǎng)地址第二控制單個(gè)頁面大小上限超過 2MB 就拒絕第三設(shè)置十秒超時(shí)避免一個(gè)壞 URL 卡住整個(gè)任務(wù)。這里有個(gè)細(xì)節(jié)輸出目錄這個(gè)參數(shù)我一開始沒加模型每次都會(huì)把結(jié)果放到當(dāng)前目錄導(dǎo)致文件滿天飛。后來我加了個(gè)默認(rèn)值并讓 Skill 返回包含完整路徑的結(jié)果問題立刻解決。別小看這些細(xì)節(jié)Agent 跑十幾個(gè)步驟時(shí)一個(gè)“文件去哪了”的小問題就可能讓整個(gè)任務(wù)失敗。3.3 沙箱與權(quán)限控制給Agent的“手”戴上手套工具調(diào)用一直是 Agent 安全的重災(zāi)區(qū)所以 Agent-Reach 從第一天起就把沙箱視為基礎(chǔ)設(shè)施而不是事后補(bǔ)丁。我的分層思路如下第一層是域名白名單和命令白名單。抓網(wǎng)頁只允許白名單域名執(zhí)行 shell 只允許注冊(cè)過的命令其它一律拒絕。第二層是環(huán)境隔離。凡是可能產(chǎn)生副作用的代碼比如安裝依賴、執(zhí)行腳本、讀寫系統(tǒng)目錄統(tǒng)一丟到子進(jìn)程或容器里跑宿主環(huán)境不暴露給模型。第三層是人工審批。對(duì)刪除操作、支付操作、外發(fā)消息這類高影響動(dòng)作Agent 不會(huì)直接執(zhí)行而是先生成一個(gè)“待確認(rèn)任務(wù)”等人在控制臺(tái)點(diǎn)確認(rèn)后才放行。這個(gè)“三明治”結(jié)構(gòu)看起來繁瑣但在真實(shí)場景里非常必要。我見過不少 Agent 項(xiàng)目在演示時(shí)很驚艷一上生產(chǎn)就把權(quán)限全部放開結(jié)果模型因?yàn)橐淮?Prompt 注入跑去調(diào)用了不該調(diào)用的接口。沙箱不是限制 Agent 的手腳而是讓它在可控范圍內(nèi)發(fā)揮能力。關(guān)于 Agent 安全我的態(tài)度一貫是寧可讓 Agent 少做一步也不能讓它多做錯(cuò)一步。4. 記憶與上下文Agent-Reach 的短期工作臺(tái)和長期倉庫4.1 三層記憶架構(gòu)Agent 記憶是 Agent 開發(fā)繞不開的話題。模型本身沒有記憶每次調(diào)用開始都是“失憶”狀態(tài)。Agent-Reach 里我設(shè)計(jì)了三層記憶對(duì)應(yīng)不同的讀寫頻次和數(shù)據(jù)量工作臺(tái)記憶當(dāng)前任務(wù)內(nèi)的關(guān)鍵信息。比如用戶剛說“幫我查一下上海到北京的航班”那出發(fā)地、目的地、日期就應(yīng)該在工作臺(tái)里后續(xù)每輪調(diào)用都能引用。摘要記憶當(dāng)對(duì)話太長時(shí)把前面的執(zhí)行過程壓縮成一段摘要取代原始對(duì)話原文保持上下文不無限膨脹。長期記憶跨任務(wù)的知識(shí)沉淀。比如用戶偏好、歷史任務(wù)結(jié)果、常用賬號(hào)信息這些會(huì)寫入向量庫或結(jié)構(gòu)化數(shù)據(jù)庫供后續(xù)任務(wù)檢索。這個(gè)分層最核心的價(jià)值是讓 Agent 分得清“哪些信息馬上要用”和“哪些信息以后可能有用”。工作臺(tái)里放太多垃圾模型會(huì)被噪聲干擾長期記憶里放太多臨時(shí)狀態(tài)檢索時(shí)又會(huì)命中一堆無關(guān)內(nèi)容。我的經(jīng)驗(yàn)是寧可在摘要記憶階段多花一次模型調(diào)用去整理也不要讓所有原始信息都堆在上下文里。4.2 Token預(yù)算與上下文管理實(shí)測Token 是 Agent 開發(fā)繞不開的成本指標(biāo)。很多初學(xué)者問“AI Agent token 是什么意思”簡單說Token 就是模型處理文本的最小單位中文通常一個(gè)字對(duì)應(yīng)一到兩個(gè) Token。Agent 每做一輪思考、每調(diào)用一次工具都要把歷史上下文重新發(fā)給模型所以 Token 消耗是呈“滾雪球”式增長的。我在 Agent-Reach 里跑過一次實(shí)際統(tǒng)計(jì)一個(gè)“調(diào)研三家競品并輸出報(bào)告”的任務(wù)原始輸入 1000 Token任務(wù)完成后累計(jì)消耗 28000 Token。其中模型思考占 40%工具返回結(jié)果占 45%系統(tǒng)提示詞和框架固定開銷占 15%。也就是說你看到的一小段網(wǎng)頁正文可能吃掉一大半成本。所以控制 Token 不是摳門而是 Agent 能不能持續(xù)跑下去的前提。我的具體做法有三個(gè)一是工具返回結(jié)果要做截?cái)嗪驼W(wǎng)頁抓下來先取前 500 字必要時(shí)再讓模型針對(duì)性讀取二是歷史對(duì)話超過一定輪數(shù)后用一次模型調(diào)用把舊內(nèi)容壓成摘要三是為每個(gè)任務(wù)設(shè) Token 上限超了就主動(dòng)終止避免“無限燒錢”式執(zhí)行。按這個(gè)配置跑下來單任務(wù)成本大概能省三成而且響應(yīng)速度也快了一圈。5. 安全護(hù)欄和穩(wěn)定性自主運(yùn)行的底線設(shè)計(jì)5.1 Agent安全最容易忽略的三個(gè)點(diǎn)我常說Agent 安全不是網(wǎng)絡(luò)安全課上的名詞而是每個(gè) Agent 開發(fā)者的日常手感。我自己在 Agent-Reach 里踩過三個(gè)典型坑第一個(gè)坑是“讀”和“寫”權(quán)限不分。很多 Demo 里工具能讀文件也能寫文件看起來方便但模型只要輸出一個(gè)錯(cuò)誤的路徑就可能覆蓋生產(chǎn)配置。我在權(quán)限模型里強(qiáng)制區(qū)分只讀和讀寫除非任務(wù)明確需要否則絕大多數(shù)工具默認(rèn)只讀。第二個(gè)坑是外部數(shù)據(jù)不可信。Agent 抓到的網(wǎng)頁、收到的郵件、讀到的文檔本質(zhì)上都是不可信輸入。如果這些輸入里包含惡意指令模型可能被“越獄”去執(zhí)行危險(xiǎn)操作。所以凡是外部文本要進(jìn)入 Prompt我都會(huì)做一道標(biāo)記和隔離比如在內(nèi)容前后加上“外部內(nèi)容開始/結(jié)束”的邊界提示并讓模型對(duì)這部分內(nèi)容保持懷疑。第三個(gè)坑是并發(fā)副作用。多 Agent 同時(shí)跑如果兩個(gè) Agent 同時(shí)寫同一個(gè)文件、調(diào)同一個(gè)接口會(huì)出現(xiàn)臟寫和請(qǐng)求錯(cuò)亂。我在任務(wù)執(zhí)行器里給每個(gè)寫操作加了鎖和版本號(hào)沖突時(shí)直接讓其中一個(gè)任務(wù)重試。這些設(shè)計(jì)不復(fù)雜但沒有的話Agent 越自主翻車方式就越五花八門。5.2 運(yùn)行錯(cuò)誤處理從終止異常到優(yōu)雅降級(jí)熱搜詞里有一條很扎眼“agent execution terminated due to error”翻譯過來就是“Agent 執(zhí)行因錯(cuò)誤被終止”。這不是什么神秘報(bào)錯(cuò)而是我的 Agent 在超時(shí)、接口返回異常、模型連續(xù)輸出無效操作時(shí)最常見的結(jié)局。我?guī)缀趺看味紩?huì)在日志里看到它。問題在于默認(rèn)處理方式是“直接終止”這等于把失敗完全甩給用戶。Agent-Reach 里我做了一個(gè)“三級(jí)降級(jí)”機(jī)制第一步遇到單步錯(cuò)誤先重試一次可能是網(wǎng)絡(luò)抖動(dòng)第二步重試還失敗就換一個(gè)思路比如從“抓取網(wǎng)頁”降級(jí)為“調(diào)用搜索 API 獲取摘要”第三步所有方案都失效才停止并生成一份“失敗報(bào)告”說明卡在哪個(gè) Skill、錯(cuò)誤是什么、可能的修復(fù)方向。這套機(jī)制讓 Agent-Reach 的“表面失敗”少了很多。我統(tǒng)計(jì)過加入三級(jí)降級(jí)后測試任務(wù)從“遇到錯(cuò)誤就終止”變?yōu)椤白罱K給出結(jié)果或明確診斷”的比例提高了約 35%。記住一個(gè)原則自主 Agent 的價(jià)值就在于碰到意外時(shí)能自己繞路而不是把每次異常都拋回給人類。6. 評(píng)測集與迭代如何證明Agent-Reach真的“到達(dá)”了目標(biāo)6.1 為什么通用評(píng)測集救不了你Agent 開發(fā)做到一定階段一定會(huì)遇到一個(gè)問題怎么判斷它變好了如果只看幾個(gè)手工測試的案例你根本分不清這次改動(dòng)是修復(fù)了一個(gè) bug 還是引入了三個(gè)新 bug。這也是為什么我堅(jiān)持為 Agent-Reach 建自己的評(píng)測集。市面上的通用 Agent 評(píng)測集可以作為參考但不能直接拿來用。原因是 Agent 任務(wù)高度依賴具體環(huán)境和工具你的 Agent 能調(diào)你公司的內(nèi)部系統(tǒng)別家的評(píng)測集里沒有這個(gè)環(huán)境你的任務(wù)是“整理會(huì)議紀(jì)要并發(fā)送郵件”評(píng)測集可能只會(huì)測“從網(wǎng)頁提取信息”。通用評(píng)測集的分?jǐn)?shù)高不代表你的業(yè)務(wù)場景里能跑通。我建議的做法是從真實(shí)需求里挑出 30 到 50 條代表性任務(wù)組成一個(gè)“個(gè)人評(píng)測集”。不用多但要覆蓋工具調(diào)用、多步規(guī)劃、信息提取、異常處理幾條主線。每次改代碼之后把這個(gè)評(píng)測集完整跑一遍看成功率變化這就是你的 Agent 專屬“回歸測試”。6.2 我的評(píng)測集構(gòu)建方法與指標(biāo)Agent-Reach 的評(píng)測集分四類任務(wù)信息獲取類查天氣、搜新聞、抓網(wǎng)頁、文件操作類格式轉(zhuǎn)換、批量重命名、內(nèi)容歸檔、編排類跨多個(gè)工具完成的復(fù)合任務(wù)、安全類遇到危險(xiǎn)操作時(shí)是否正確拒絕。每類 10 條左右總共 40 條。打分我不用“感覺”用四個(gè)硬指標(biāo)成功率最終結(jié)果是否滿足預(yù)期人工判定 0/1。成本單位任務(wù)消耗 Token 數(shù)和模型調(diào)用次數(shù)。延遲從任務(wù)開始到結(jié)束的總時(shí)長。穩(wěn)定性同一任務(wù)連跑五次成功次數(shù)是否穩(wěn)定。我會(huì)用“LLM as Judge”做初步評(píng)分即讓另一個(gè)模型按規(guī)則打分再抽一部分由人工復(fù)核。這里有個(gè)經(jīng)驗(yàn)LLM Judge 適合做初篩不適合當(dāng)唯一標(biāo)準(zhǔn)因?yàn)樗谡Z義判斷上容易給出“看著有道理但其實(shí)沒完成”的評(píng)分。關(guān)鍵是要把任務(wù)的成功標(biāo)準(zhǔn)寫進(jìn)評(píng)分規(guī)則里而不是讓它自由發(fā)揮。評(píng)測集跑定期之后Agent 開發(fā)就從一個(gè)“改完不知道結(jié)果”的盲盒變成了一條可迭代的流水線?,F(xiàn)在我的習(xí)慣是任何改動(dòng)先過評(píng)測集再看人工抽查最后才把改動(dòng)合入主線。這個(gè)過程可能讓每次迭代變慢但長期看它的效率遠(yuǎn)高于“改一行代碼跑五個(gè)隨機(jī)任務(wù)憑感覺判斷好壞”。7. Agent-Reach 開發(fā)過程中的踩坑清單7.1 工具描述寫不好Agent就變“瞎”這是我在 Agent 開發(fā)里最先遇到的坑。早期我在注冊(cè) Skill 時(shí)描述寫得很隨意比如“獲取網(wǎng)頁內(nèi)容”結(jié)果模型在用戶說“把這個(gè)頁面保存下來”時(shí)死活不選這個(gè) Skill反而去猜別的能力。后來我把描述改成“抓取指定網(wǎng)頁并轉(zhuǎn)換為Markdown格式適用于保存網(wǎng)頁正文、整理資料、生成文檔”模型的調(diào)用準(zhǔn)確率肉眼可見上升。寫工具描述時(shí)可以想象自己在給一個(gè)從不認(rèn)識(shí)這些函數(shù)的新同事寫說明文檔把它的用途、輸入、輸出、典型場景全部寫清楚。一個(gè)好的描述比你在 Prompt 里反復(fù)強(qiáng)調(diào)“請(qǐng)正確調(diào)用工具”有效得多。這也是為什么我在每個(gè)新 Skill 上線前都會(huì)要求先寫描述再寫代碼。7.2 長對(duì)話變慢、變貴、變笨的應(yīng)對(duì)第二個(gè)坑是長對(duì)話失控。Agent 在跑長任務(wù)時(shí)歷史上下文會(huì)越堆越長模型響應(yīng)變慢、成本飆升、行為漂移。我記得有一次 Agent 在第五步之后開始反復(fù)輸出“讓我回顧一下之前的操作”其實(shí)上下文里已經(jīng)擠滿了沒用的中間結(jié)果。解決辦法我在記憶那一節(jié)已經(jīng)提到截?cái)喙ぞ叻祷?、做歷史摘要、控制上下文窗口。這里再補(bǔ)充一個(gè)“上下文預(yù)算”的技巧每一步開始前先檢查當(dāng)前長度如果超過預(yù)算就先執(zhí)行一次摘要壓縮再讓模型繼續(xù)。這個(gè)檢查看起來多了一次模型調(diào)用但實(shí)際上減少了后續(xù)大量的重復(fù)思考和無效輸出整體成本反而更低。7.3 調(diào)試自主Agent的正確方式最后一個(gè)坑也是最容易被忽視的怎么調(diào)試一個(gè)“每一步都是模型自由發(fā)揮”的 Agent。傳統(tǒng)的 print 調(diào)試和斷點(diǎn)調(diào)試在這里基本失效因?yàn)槟銢]法預(yù)知模型會(huì)走哪條路。我的做法是給 Agent-Reach 加了一個(gè)“全鏈路追蹤”模塊每次模型調(diào)用、每次 Skill 調(diào)用、每次工具返回都記錄成結(jié)構(gòu)化日志包括輸入、輸出、耗時(shí)、成本。調(diào)試時(shí)把一次任務(wù)完整回放就像給 Agent 拍紀(jì)錄片一樣。一旦某一步的結(jié)果不對(duì)你就能順著 trace 找到是模型理解錯(cuò)了、工具傳參錯(cuò)了還是返回解析錯(cuò)了。這大概是整個(gè)項(xiàng)目里投入產(chǎn)出比最高的一件事。以前處理一個(gè)詭異 bug 可能要半天現(xiàn)在打開 trace 看五分鐘就能定位。如果你準(zhǔn)備自己搞 Agent 項(xiàng)目我強(qiáng)烈建議第一版就把日志和追蹤做進(jìn)去否則后面補(bǔ)的成本會(huì)是現(xiàn)在的三倍?;氐介_頭那句話Agent 的核心是“到達(dá)”。Agent-Reach 這個(gè)項(xiàng)目做到現(xiàn)在我最大的體會(huì)是能不能到達(dá)取決于你把工具、記憶、安全和評(píng)測這幾塊地基打得有多扎實(shí)。每一步都是笨功夫但沒有這些笨功夫再聰明的模型也只會(huì)原地打轉(zhuǎn)。如果你也有一個(gè)想做的 Agent 項(xiàng)目別急著堆新功能先從把“到達(dá)”練扎實(shí)開始。