級(jí) MultiAgent 落地實(shí)戰(zhàn):Plan 模式與主子 Agent 協(xié)作架構(gòu)全解析)
做企業(yè)級(jí) MultiAgent 落地這事我最開(kāi)始是拒絕的。不是因?yàn)榧夹g(shù)難而是當(dāng)時(shí)團(tuán)隊(duì)連單 Agent 都沒(méi)完全調(diào)明白Token 成本壓不下去輸出還不穩(wěn)定動(dòng)不動(dòng)就在長(zhǎng)鏈路任務(wù)里“迷路”。后來(lái)被逼著上了一套包含 Plan 模式和主子 Agent 協(xié)作的架構(gòu)才慢慢把這事從 demo 階段拖進(jìn)了生產(chǎn)環(huán)境。這篇文章就把我們方案選型、任務(wù)拆解、Agent 協(xié)作機(jī)制、穩(wěn)定性治理這些核心環(huán)節(jié)全部攤開(kāi)講包括當(dāng)時(shí)踩過(guò)的坑和現(xiàn)在還在用的排查手段。如果你是做 Agent 應(yīng)用落地的工程師或者正準(zhǔn)備把 MultiAgent 從玩具變成生產(chǎn)力工具這篇文章能把一些關(guān)鍵思路直接給你抄。1. 為什么企業(yè)級(jí)場(chǎng)景必須上 MultiAgent而不是一個(gè) Agent 硬撐先交代一下背景。我們面對(duì)的并不是“讓 AI 寫(xiě)一段文案”這種單點(diǎn)任務(wù)而是一套需要跨系統(tǒng)操作、多次決策、前后有依賴關(guān)系的長(zhǎng)鏈路業(yè)務(wù)比如自動(dòng)化巡檢、內(nèi)容生產(chǎn)審批流、供應(yīng)鏈異常處理等等。早期用單 Agent 硬寫(xiě) ReAct 模式效果很不穩(wěn)定。1.1 單 Agent 在長(zhǎng)鏈路任務(wù)里的三個(gè)致命傷第一個(gè)是上下文污染。Agent 每執(zhí)行一個(gè)步驟都要把這些步驟的歷史記錄、中間結(jié)果、工具返回都塞進(jìn)上下文里重新推理鏈路一長(zhǎng)前面的無(wú)用信息就會(huì)把真正關(guān)鍵的指令淹沒(méi)模型開(kāi)始“忘記”最初的目標(biāo)輸出質(zhì)量斷崖式下跌。第二個(gè)是 Token 成本失控。長(zhǎng)鏈路任務(wù)的每一步都要攜帶全量歷史調(diào)用次數(shù)越多每次的輸入 Token 就越大成本隨鏈路長(zhǎng)度指數(shù)膨脹。我們當(dāng)時(shí)有個(gè)巡檢任務(wù)跑到第 6 步時(shí)單次調(diào)用的 Token 量已經(jīng)是第一步的 8 倍左右老板看到賬單臉色都變了。第三個(gè)是錯(cuò)誤不可恢復(fù)。單 Agent 一旦在某一步產(chǎn)生幻覺(jué)、返回錯(cuò)誤結(jié)果整個(gè)鏈路就全部白費(fèi)沒(méi)有中間檢查點(diǎn)沒(méi)有局部重試機(jī)制只能從頭再來(lái)這在企業(yè)級(jí)場(chǎng)景里是不可接受的。1.2 MultiAgent 的核心思想分工、隔離、可恢復(fù)把一個(gè)大任務(wù)拆成多個(gè)小任務(wù)讓不同的 Agent 各自負(fù)責(zé)一段這就是 MultiAgent 的基本盤(pán)。本質(zhì)上就是把“一個(gè)人全干”變成“團(tuán)隊(duì)協(xié)作”有人負(fù)責(zé)拆解需求、制定步驟有人負(fù)責(zé)執(zhí)行具體動(dòng)作有人負(fù)責(zé)檢查結(jié)果各司其職。這樣做的好處很直接。首先是上下文隔離每個(gè)子 Agent 只需要關(guān)心自己這一小段任務(wù)的上下文不會(huì)被全局歷史淹沒(méi)模型輸出的穩(wěn)定性和準(zhǔn)確率會(huì)有明顯提升。其次是成本可控每個(gè)子任務(wù)單獨(dú)計(jì)費(fèi)不會(huì)因?yàn)殒溌吩鲩L(zhǎng)導(dǎo)致 Token 膨脹預(yù)算可以精細(xì)化管控。第三是可恢復(fù)性某個(gè)子任務(wù)失敗了只需要重跑那一個(gè)子任務(wù)不需要整個(gè)鏈路重來(lái)。我用一個(gè)生活化的類(lèi)比來(lái)說(shuō)明單 Agent 長(zhǎng)鏈路執(zhí)行就像一個(gè)人既當(dāng)項(xiàng)目經(jīng)理又當(dāng)程序員又當(dāng)測(cè)試一口氣寫(xiě)完整個(gè)項(xiàng)目后再交給客戶中間任何一步寫(xiě)錯(cuò)了都要推倒重來(lái)。MultiAgent 則是標(biāo)準(zhǔn)的項(xiàng)目組運(yùn)作項(xiàng)目經(jīng)理拆需求、程序員寫(xiě)代碼、測(cè)試提 bug每層的職責(zé)邊界清晰哪塊出錯(cuò)就修哪塊。1.3 什么時(shí)候才需要上 MultiAgent不是所有場(chǎng)景都適合 MultiAgent。這里有一個(gè)簡(jiǎn)單的判斷標(biāo)準(zhǔn)如果任務(wù)鏈路很短比如 2 到 3 步無(wú)復(fù)雜依賴一個(gè) Agent 加幾個(gè)工具就能搞定就別上 MultiAgent徒增系統(tǒng)復(fù)雜度還要多付幾倍的 Token 費(fèi)用。適合上 MultiAgent 的場(chǎng)景通常有這么幾個(gè)特征任務(wù)涉及多個(gè)獨(dú)立領(lǐng)域比如既要查庫(kù)存又要寫(xiě)文案又要審核合規(guī)鏈路長(zhǎng)且有明確的前后依賴需要對(duì)每個(gè)階段的結(jié)果做質(zhì)量檢查或者對(duì)失敗恢復(fù)有強(qiáng)要求。我們?cè)跊Q定哪些場(chǎng)景上 MultiAgent 之前會(huì)先跑一段單 Agent 的日志統(tǒng)計(jì)一下任務(wù)失敗率、平均 Token 消耗和失敗原因分布拿數(shù)據(jù)說(shuō)話。2. 企業(yè)級(jí) MultiAgent 的架構(gòu)核心Plan 模式怎么落地MultiAgent 架構(gòu)里最高決策者是一個(gè)“主 Agent”它不直接執(zhí)行具體操作而是負(fù)責(zé)理解用戶意圖、制定執(zhí)行計(jì)劃、調(diào)度子 Agent。這個(gè)模式在企業(yè)級(jí)場(chǎng)景里基本都會(huì)選擇 Plan 模式而非 ReAct 模式原因下面細(xì)說(shuō)。2.1 為什么是 Plan 模式而不是 ReAct 模式ReAct 模式是“邊想邊做”Agent 每走一步就觀察一次結(jié)果再?zèng)Q定下一步怎么走。這種模式在開(kāi)放域、探索性的任務(wù)里很靈活但在企業(yè)級(jí)場(chǎng)景里問(wèn)題很大過(guò)程不可控、中間步驟不可審計(jì)、消耗不可預(yù)算而且很容易在某個(gè)分支上繞圈出不來(lái)。Plan 模式則是“先想后做”主 Agent 在正式執(zhí)行之前先把整個(gè)任務(wù)的執(zhí)行計(jì)劃完整生成出來(lái)拆成若干個(gè)帶依賴關(guān)系的子任務(wù)然后再逐個(gè)調(diào)度執(zhí)行。這樣做最大的價(jià)值是把“思考”和“執(zhí)行”兩個(gè)階段徹底解耦。我舉個(gè)例子說(shuō)明這兩種模式的實(shí)際差別。比如任務(wù)是“生成一份 618 大促的商品盤(pán)點(diǎn)報(bào)告”ReAct 模式下的運(yùn)行路徑是Agent 看到任務(wù)先決定第一步去查哪個(gè)庫(kù)查到結(jié)果后根據(jù)結(jié)果再?zèng)Q定下一步完全走一步看一步。Plan 模式則會(huì)先列出一個(gè)明確的執(zhí)行計(jì)劃第一步獲取銷(xiāo)售數(shù)據(jù)第二步獲取庫(kù)存數(shù)據(jù)第三步分析缺貨風(fēng)險(xiǎn)第四步生成報(bào)告——這個(gè)計(jì)劃在執(zhí)行前就已經(jīng)確定每一步的目標(biāo)、輸入、輸出都寫(xiě)清楚了。兩種模式對(duì)比下來(lái)Plan 模式的優(yōu)勢(shì)非常明顯每個(gè)步驟在執(zhí)行前就定義了清晰的邊界審計(jì)容易、預(yù)算可控、支持分步重試。企業(yè)級(jí)場(chǎng)景里尤其是面對(duì) C 端業(yè)務(wù)時(shí)“可控”比“靈活”重要得多。靈活意味著不可預(yù)測(cè)不可預(yù)測(cè)意味著事故。2.2 一份合格的 Plan 應(yīng)該包含哪些字段在實(shí)際落地過(guò)程中我們會(huì)在系統(tǒng)里把 Plan 定義成一個(gè)結(jié)構(gòu)化的對(duì)象而不是一段純文本。純文本計(jì)劃的最大問(wèn)題是機(jī)器沒(méi)法解析、沒(méi)法做依賴管理、沒(méi)法做進(jìn)度跟蹤。我們最終定義的 Plan 核心字段如下{ plan_id: plan_20250114_001, goal: 生成每周商品缺貨風(fēng)險(xiǎn)報(bào)告, task_list: [ { task_id: task_001, name: 拉取庫(kù)存數(shù)據(jù), description: 從庫(kù)存系統(tǒng)獲取最近7天的庫(kù)存快照, dependencies: [], agent_type: data_agent, input_schema: {date_range: 2025-01-07~2025-01-14}, output_schema: {sku_count: integer, items: array}, timeout_seconds: 60, retry_count: 3 }, { task_id: task_002, name: 計(jì)算缺貨風(fēng)險(xiǎn), description: 基于庫(kù)存快照計(jì)算缺貨風(fēng)險(xiǎn)評(píng)分, dependencies: [task_001], agent_type: analysis_agent, input_schema: {inventory_items: task_001.output.items}, output_schema: {risk_items: array}, timeout_seconds: 90, retry_count: 2 } ] }這個(gè)結(jié)構(gòu)里有幾個(gè)關(guān)鍵設(shè)計(jì)。task_id 全鏈路唯一方便日志追蹤和結(jié)果對(duì)賬。dependencies 字段聲明了任務(wù)依賴關(guān)系執(zhí)行引擎靠它構(gòu)建執(zhí)行順序沒(méi)有依賴的任務(wù)可以并行執(zhí)行有依賴的必須等前置任務(wù)完成。input_schema 和 output_schema 嚴(yán)格約束了任務(wù)間的數(shù)據(jù)傳遞格式從機(jī)制上杜絕了子 Agent 返回“亂七八糟”格式的可能性。還有一個(gè)容易忽略的點(diǎn)是 timeout_seconds 和 retry_count這兩個(gè)字段必須在 Plan 定義時(shí)就明確而不是執(zhí)行時(shí)隨機(jī)應(yīng)變。企業(yè)級(jí)系統(tǒng)必須對(duì)最壞情況有預(yù)期不能讓一個(gè)子任務(wù)無(wú)限執(zhí)行下去。2.3 Plan 模式的執(zhí)行引擎設(shè)計(jì)Plan 生成之后需要一個(gè)執(zhí)行引擎來(lái)調(diào)度任務(wù)。我們用狀態(tài)機(jī)來(lái)管理整個(gè)計(jì)劃的生命周期核心狀態(tài)包括 PENDING待執(zhí)行、READY依賴已滿足可執(zhí)行、RUNNING執(zhí)行中、SUCCEEDED成功、FAILED失敗、TIMEOUT超時(shí)、CANCELLED取消。執(zhí)行引擎維護(hù)一個(gè)任務(wù)隊(duì)列每一輪循環(huán)做這幾件事掃描所有狀態(tài)為 READY 的任務(wù)按照配置的并發(fā)度派發(fā)給對(duì)應(yīng)的子 Agent監(jiān)聽(tīng)子 Agent 的執(zhí)行結(jié)果收到成功的回執(zhí)后更新?tīng)顟B(tài)并檢查后續(xù)任務(wù)的依賴是否全部滿足收到失敗的回執(zhí)后按照 retry_count 配置決定是重試還是標(biāo)記 FAILED。這里要特別注意并發(fā)控制。我們?cè)缙谥苯釉谝胬飳?xiě)死最大并發(fā)數(shù)是 10結(jié)果某次大促巡檢任務(wù)一下子把庫(kù)存系統(tǒng)打得超時(shí)從那以后就把并發(fā)度做成了可配置項(xiàng)并且加了一個(gè)令牌桶限流器所有子任務(wù)的請(qǐng)求統(tǒng)一走限流保護(hù)下游系統(tǒng)。另外執(zhí)行引擎必須把整個(gè) Plan 的進(jìn)度持久化到數(shù)據(jù)庫(kù)里而不是放在內(nèi)存里。內(nèi)存態(tài)最怕進(jìn)程重啟一旦重啟全鏈路狀態(tài)全部丟失用戶還得重新發(fā)起一次任務(wù)體驗(yàn)極差。我們后來(lái)把進(jìn)度表做成了一張 plan_instance每完成一個(gè)子任務(wù)就更新一次這樣就算執(zhí)行引擎掛了重啟后也能從數(shù)據(jù)庫(kù)恢復(fù)狀態(tài)繼續(xù)跑剩余任務(wù)。3. 主子 Agent 協(xié)作機(jī)制主 Agent 怎么管好一群子 AgentPlan 模式解決的是“先想后做”的問(wèn)題而主子 Agent 協(xié)作解決的是“想法怎么落地”的問(wèn)題。主 Agent 負(fù)責(zé)決策子 Agent 負(fù)責(zé)執(zhí)行中間要有一套清晰的協(xié)作協(xié)議不然整個(gè)系統(tǒng)就是一群 Agent 在亂打架。3.1 主 Agent 和子 Agent 職責(zé)怎么劃分先給主 Agent 和子 Agent 劃一條清晰的職責(zé)邊界。主 Agent 的職責(zé)范圍包括理解用戶原始請(qǐng)求、生成/調(diào)整 Plan、拆分任務(wù)、分配任務(wù)、校驗(yàn)子 Agent 返回的結(jié)果、匯總最終答案。子 Agent 的職責(zé)范圍則非常聚焦執(zhí)行主 Agent 派發(fā)的單個(gè)子任務(wù)、調(diào)用必要的工具、返回結(jié)構(gòu)化的執(zhí)行結(jié)果。用公司團(tuán)隊(duì)來(lái)類(lèi)比主 Agent 是項(xiàng)目經(jīng)理子 Agent 是工程師。項(xiàng)目經(jīng)理不做具體編碼但要對(duì)整個(gè)項(xiàng)目交付負(fù)責(zé)工程師不關(guān)心其他人在做什么只專(zhuān)注于自己那一塊任務(wù)。這里有一個(gè)很多團(tuán)隊(duì)會(huì)踩的坑容易把主 Agent 做成“傳話筒”說(shuō)大白話就是把主 Agent 變成子 Agent 結(jié)果的拼裝器子 Agent 返回什么就原樣拼什么。這會(huì)導(dǎo)致主 Agent 失去決策能力最終結(jié)果是所有子 Agent 的信息一股腦堆給用戶非常難用。正確做法是主 Agent 必須具備“結(jié)果消費(fèi)”能力。子 Agent 返回的是原始執(zhí)行結(jié)果主 Agent 要做二次加工比如多個(gè)子任務(wù)結(jié)果交叉驗(yàn)證、對(duì)比分析、提煉結(jié)論或者發(fā)現(xiàn)結(jié)果之間的沖突并決定是否讓某個(gè)子 Agent 補(bǔ)充執(zhí)行一次。3.2 子 Agent 的結(jié)果返回協(xié)議子 Agent 向主 Agent 返回結(jié)果的方式直接決定了整個(gè)系統(tǒng)的穩(wěn)定程度。我們?cè)缙跊](méi)有統(tǒng)一協(xié)議各個(gè)子 Agent 想返回什么返回什么結(jié)果主 Agent 推理時(shí)經(jīng)常被各種“自由格式”搞暈。后來(lái)我們統(tǒng)一了 Rollback 協(xié)議所有子 Agent 的返回結(jié)果必須包含以下三個(gè)核心部分{ task_id: task_001, status: success, data: { result_summary: 這是本次任務(wù)的結(jié)論摘要, raw_data: { ...: 原始數(shù)據(jù) }, confidence: 0.95, warnings: [] } }status 字段只有兩個(gè)合法值success 或 failed不允許有模糊地帶。result_summary 是給主 Agent 消費(fèi)的結(jié)論摘要必須用自然語(yǔ)言簡(jiǎn)要描述執(zhí)行結(jié)果。raw_data 是原始數(shù)據(jù)按需攜帶。confidence 是子 Agent 對(duì)自己結(jié)果的置信度主 Agent 可以據(jù)此決定是否要二次核驗(yàn)。warnings 是非致命問(wèn)題的列表比如“數(shù)據(jù)只覆蓋了 90% 的 SKU其余 10% 因接口超時(shí)未能拉取”。最關(guān)鍵的設(shè)計(jì)是 result_summary 和 raw_data 的分離。主 Agent 日常推理時(shí)只需要讀取 result_summary避免被大量原始數(shù)據(jù)淹沒(méi)上下文當(dāng)它需要核對(duì)細(xì)節(jié)時(shí)再去翻 raw_data。這個(gè)設(shè)計(jì)把 Token 消耗控制在了低水平又保留了信息的完整性。3.3 主子 Agent 的通信機(jī)制請(qǐng)求-響應(yīng)還是消息隊(duì)列早期我們用的是同步 HTTP 請(qǐng)求主 Agent 調(diào)用子 Agent 的接口等子 Agent 返回結(jié)果后再繼續(xù)下一步。這種方式實(shí)現(xiàn)簡(jiǎn)單但有一個(gè)致命問(wèn)題子 Agent 執(zhí)行一個(gè)任務(wù)往往需要幾十秒甚至幾分鐘同步等待時(shí)主 Agent 線程被阻塞整個(gè)調(diào)度效率極低而且網(wǎng)絡(luò)抖動(dòng)一次鏈路就斷。后來(lái)我們改成了基于任務(wù)隊(duì)列的異步通信模式。主 Agent 把任務(wù)放進(jìn)隊(duì)列后立刻返回子 Agent 消費(fèi)任務(wù)并執(zhí)行執(zhí)行完成后把結(jié)果寫(xiě)入結(jié)果存儲(chǔ)同時(shí)觸發(fā)一個(gè)回調(diào)通知主 Agent 來(lái)取。整個(gè)過(guò)程主 Agent 完全不阻塞同一時(shí)刻可以并行調(diào)度多個(gè)子任務(wù)。具體實(shí)現(xiàn)上我們用 Redis Stream 作為任務(wù)隊(duì)列執(zhí)行結(jié)果也先寫(xiě)入 Redis隨后異步落庫(kù)。主 Agent 側(cè)通過(guò)事件監(jiān)聽(tīng)機(jī)制感知任務(wù)完成。這套機(jī)制改造完成之后同樣一批任務(wù)的整體執(zhí)行耗時(shí)下降了大約 60%。4. 穩(wěn)定性與成本治理企業(yè)級(jí) MultiAgent 的生死線如果說(shuō) Plan 模式解決的是怎么把事干成那這一章解決的是怎么不出事、怎么壓成本。企業(yè)級(jí)系統(tǒng)穩(wěn)定性永遠(yuǎn)排第一Agent 也一樣。4.1 任務(wù)狀態(tài)機(jī)與死循環(huán)防護(hù)Agent 系統(tǒng)最常見(jiàn)的事故就是死循環(huán)任務(wù)反復(fù)執(zhí)行、無(wú)限重試、某一步邏輯走岔了繞圈繞不出來(lái)。我們的做法是在 Plan 級(jí)別做兩層防護(hù)。第一層是任務(wù)最大執(zhí)行次數(shù)限制。每個(gè) Plan 在創(chuàng)建時(shí)綁定一個(gè) max_execution_count所有子任務(wù)的執(zhí)行次數(shù)總和超過(guò)這個(gè)值整個(gè) Plan 直接進(jìn)入 CANCELLED 狀態(tài)不再派發(fā)任何新任務(wù)。這個(gè)限制是最兜底的防線。第二層是單個(gè)任務(wù)的失敗重試策略。并不是所有失敗都值得重試我們只對(duì)某些錯(cuò)誤類(lèi)型做重試比如下游接口返回 5xx、超時(shí)這類(lèi)暫時(shí)性錯(cuò)誤參數(shù)錯(cuò)誤、數(shù)據(jù)格式錯(cuò)誤這類(lèi)確定性錯(cuò)誤直接返回 failed不浪費(fèi) Token 去重試。重試策略遵循指數(shù)退避原則第一次重試等 1 秒第二次等 2 秒第三次等 4 秒防止重試風(fēng)暴打垮下游接口。4.2 Token 預(yù)算控制把成本變成可度量指標(biāo)Token 預(yù)算是多 Agent 系統(tǒng)里一個(gè)必須要做的設(shè)計(jì)沒(méi)有預(yù)算控制的 Agent 系統(tǒng)就是一臺(tái)“零元計(jì)費(fèi)”的燒錢(qián)機(jī)器。我們給每個(gè) Plan 綁定一個(gè) token_budget預(yù)算的可配置粒度可以精細(xì)到任務(wù)級(jí)。分配方式是總預(yù)算先用一個(gè)比例分配給 Plan 規(guī)劃階段比如 10%剩余 90% 留給子任務(wù)執(zhí)行鏈路。子任務(wù)執(zhí)行鏈路內(nèi)部再按任務(wù)重要性動(dòng)態(tài)分配核心任務(wù)拿大頭邊緣任務(wù)拿小頭。每完成一個(gè)子任務(wù)引擎就把實(shí)際消耗從預(yù)算里扣除當(dāng)預(yù)算低于某個(gè)閾值時(shí)不再派發(fā)高消耗任務(wù)優(yōu)先保證核心任務(wù)完成。我們?cè)趯?shí)踐過(guò)程中發(fā)現(xiàn)一個(gè)很重要的事Token 預(yù)算控制不能光靠“扣數(shù)字”還得有預(yù)警機(jī)制。我們?cè)O(shè)置了兩個(gè)預(yù)警線預(yù)算消耗達(dá)到 60% 時(shí)發(fā)送 warning 日志達(dá)到 85% 時(shí)通知到值班群這樣團(tuán)隊(duì)能在事故惡化之前介入調(diào)整。4.3 可觀測(cè)性建設(shè)把 Agent 當(dāng)分布式系統(tǒng)管MultiAgent 系統(tǒng)本質(zhì)上是個(gè)分布式系統(tǒng)多個(gè) Agent 并行執(zhí)行、異步通信、狀態(tài)流轉(zhuǎn)如果沒(méi)有一套完整可觀測(cè)性方案出問(wèn)題的時(shí)候根本不知道是哪個(gè)環(huán)節(jié)出的問(wèn)題。我們采用了 trace metric log 三件套。Trace 層面我們把一次完整的用戶請(qǐng)求作為一條 trace里面的每個(gè)子任務(wù)都是一個(gè) span記錄了子任務(wù)耗時(shí)、調(diào)用的 Agent 類(lèi)型、返回結(jié)果狀態(tài)、Token 消耗量。定位問(wèn)題時(shí)只需要拉起 trace 就能看到整條鏈路的瓶頸在哪。Metric 層面我們重點(diǎn)監(jiān)控任務(wù)成功率、平均執(zhí)行時(shí)長(zhǎng)、Token 消耗速率、隊(duì)列積壓量四個(gè)核心指標(biāo)全部接入可視化監(jiān)控大盤(pán)。Log 層面每個(gè) Agent 的執(zhí)行日志全部結(jié)構(gòu)化輸出包含 task_id、plan_id、agent_type、status 等關(guān)鍵字段支持按任務(wù)維度檢索日志。我這里想強(qiáng)調(diào)的是Agent 系統(tǒng)的可觀測(cè)性建設(shè)必須在系統(tǒng)設(shè)計(jì)初期就搭好架子而不是上線以后補(bǔ)。上線前我們花了一周時(shí)間搭觀測(cè)體系上線后的排查效率提升了不止一個(gè)量級(jí)這筆投入回報(bào)率很高。4.4 灰度發(fā)布與配置開(kāi)關(guān)設(shè)計(jì)Agent 系統(tǒng)的模型輸出具有不確定性即使同一個(gè)任務(wù)今天跑和昨天跑的結(jié)果也可能有差異。這種不確定性意味著我們不能像發(fā)布普通服務(wù)一樣“全量上線”。我們做了一系列配置開(kāi)關(guān)來(lái)控制發(fā)布風(fēng)險(xiǎn)。最核心的開(kāi)關(guān)是 Plan 模式開(kāi)關(guān)用于區(qū)分新舊執(zhí)行鏈路。上線初期我們只把開(kāi)關(guān)打開(kāi)給內(nèi)部測(cè)試賬號(hào)觀察幾天確認(rèn)穩(wěn)定后再按流量比例灰度5% 到 20% 再到 100%。第二個(gè)是子 Agent 資源開(kāi)關(guān)每個(gè)子 Agent 都可以獨(dú)立啟停如果發(fā)現(xiàn)某個(gè)子 Agent 服務(wù)異??梢詥为?dú)把它下線其他任務(wù)不受影響。第三個(gè)是模型參數(shù)開(kāi)關(guān)不同子任務(wù)使用不同 temperature、max_tokens 配置全部做成動(dòng)態(tài)可調(diào)。這套開(kāi)關(guān)體系幫我們躲過(guò)好幾次事故。印象最深的一次是某個(gè)子 Agent 在深夜出現(xiàn)輸出質(zhì)量退化值班同事直接在配置中心把該子 Agent 的調(diào)用流量降為零其他任務(wù)鏈路完全無(wú)感整個(gè)過(guò)程不到三分鐘。5. 實(shí)操中遇到的典型問(wèn)題與排查實(shí)錄寫(xiě)到這里我想把我們?cè)趯?shí)際落地過(guò)程中遇到的幾個(gè)比較有代表性的問(wèn)題做一個(gè)梳理。這些問(wèn)題不是從文檔里抄來(lái)的是真實(shí)線上環(huán)境踩過(guò)的坑。5.1 子 Agent 連接失敗connection failed 排查思路我們用的子 Agent 服務(wù)部署在獨(dú)立容器中通過(guò)內(nèi)部網(wǎng)關(guān)通信曾經(jīng)出現(xiàn)過(guò)間歇性的 connection failed 報(bào)錯(cuò)錯(cuò)誤信息是 connection failed: error sending request for url。第一次遇到時(shí)第一反應(yīng)是網(wǎng)絡(luò)不通但實(shí)際排查后發(fā)現(xiàn)根本不是基礎(chǔ)網(wǎng)絡(luò)問(wèn)題。我們的排查順序是這樣的第一步檢查網(wǎng)絡(luò)連通性確認(rèn)服務(wù)間網(wǎng)絡(luò)白名單是否正確配置DNS 解析是否正常第二步檢查超時(shí)配置發(fā)現(xiàn)子 Agent 處理耗時(shí)較長(zhǎng)而網(wǎng)關(guān)默認(rèn)超時(shí)時(shí)間只有 10 秒導(dǎo)致請(qǐng)求被網(wǎng)關(guān)主動(dòng)斷開(kāi)子 Agent 還在繼續(xù)執(zhí)行但主 Agent 已經(jīng)收到超時(shí)報(bào)錯(cuò)第三步調(diào)整超時(shí)配置和 TCP 連接心跳?;顓?shù)。這個(gè)問(wèn)題的根源其實(shí)是參數(shù)配置不合理不是真正的網(wǎng)絡(luò)故障。我的建議是遇到這類(lèi)連接報(bào)錯(cuò)先把鏈路梳理一遍確認(rèn)是哪個(gè)環(huán)節(jié)斷的再針對(duì)性地調(diào)整配置。5.2 子 Agent 返回結(jié)果被截?cái)嘀?Agent 推理出錯(cuò)這是上線初期非常頭疼的問(wèn)題。某個(gè)分析類(lèi)子 Agent 輸出的 result_summary 特別長(zhǎng)直接超過(guò)了主 Agent 模型的輸出長(zhǎng)度限制結(jié)果被截?cái)鄬?dǎo)致主 Agent 拿到的是一段不完整的結(jié)論推理結(jié)果自然出錯(cuò)。解決方案在協(xié)議側(cè)做了兩條約束一是限制 result_summary 必須控制在 200 字以內(nèi)讓子 Agent 自己提煉摘要二是主 Agent 側(cè)加了截?cái)鄼z測(cè)邏輯當(dāng)檢測(cè)到返回內(nèi)容疑似被截?cái)鄷r(shí)立即標(biāo)記該任務(wù)為 failed要求子 Agent 重新執(zhí)行而不是硬著頭皮往下推理。這個(gè)教訓(xùn)讓我理解了一件事多 Agent 系統(tǒng)的信息流設(shè)計(jì)一定要做長(zhǎng)度預(yù)算不能指望模型自己“合理控制輸出長(zhǎng)度”必須從協(xié)議層面把長(zhǎng)度約束寫(xiě)死。5.3 任務(wù)風(fēng)暴一個(gè)異常觸發(fā)了 32 個(gè)子任務(wù)我們遇到過(guò)一次比較驚險(xiǎn)的事故某個(gè)看板任務(wù)因?yàn)樯嫌螖?shù)據(jù)異常子 Agent 返回了一條 warning主 Agent 沒(méi)有正確識(shí)別 warning 的含義把它當(dāng)成“數(shù)據(jù)不足”再次派發(fā)了一個(gè)補(bǔ)償任務(wù)補(bǔ)償任務(wù)結(jié)果同樣異常又觸發(fā)了下一個(gè)補(bǔ)償任務(wù)……最終一個(gè)請(qǐng)求衍生出 32 個(gè)子任務(wù)差點(diǎn)把下游系統(tǒng)拖垮。事后復(fù)盤(pán)根因是主 Agent 對(duì)子 Agent 返回的 warning 字段理解不到位。補(bǔ)償機(jī)制改成了由執(zhí)行引擎統(tǒng)一管理而不是由主 Agent 自主觸發(fā)因?yàn)?Agent 的自由度越高越容易出現(xiàn)類(lèi)似的連鎖反應(yīng)。5.4 狀態(tài)不一致任務(wù)完成了但系統(tǒng)狀態(tài)還是執(zhí)行中子 Agent 執(zhí)行結(jié)果通過(guò)回調(diào)異步上報(bào)某次回調(diào)服務(wù)重啟上報(bào)消息丟失導(dǎo)致任務(wù)實(shí)際已經(jīng)完成但數(shù)據(jù)庫(kù)里一直是 RUNNING 狀態(tài)。后來(lái)加了兜底任務(wù)掃描每 5 分鐘掃描一次所有執(zhí)行中但超過(guò)預(yù)期時(shí)限的任務(wù)主動(dòng)向子 Agent 查詢真實(shí)狀態(tài)把狀態(tài)糾正回來(lái)。這個(gè)案例說(shuō)明分布式系統(tǒng)里不能依賴單次通知機(jī)制一定要有對(duì)賬邏輯兜底。Agent 系統(tǒng)本質(zhì)上也是分布式系統(tǒng)所有分布式系統(tǒng)的經(jīng)典問(wèn)題它都存在。6. 這套架構(gòu)的門(mén)檻團(tuán)隊(duì)需要具備什么能力才能玩轉(zhuǎn)MultiAgent 不是買(mǎi)了模型 API 就能立刻跑通的對(duì)團(tuán)隊(duì)的工程能力和算法理解都有一定門(mén)檻。這里聊聊我們的實(shí)際情況給想入場(chǎng)的團(tuán)隊(duì)一個(gè)參考。團(tuán)隊(duì)必須有一個(gè)能寫(xiě)生產(chǎn)級(jí)代碼的后端工程師因?yàn)?MultiAgent 系統(tǒng)不是寫(xiě)幾個(gè) Prompt 就行而是需要設(shè)計(jì)狀態(tài)機(jī)、任務(wù)隊(duì)列、配置中心、可觀測(cè)性體系這些全是標(biāo)準(zhǔn)的后端工程問(wèn)題。還得有一個(gè)對(duì)模型能力邊界非常熟悉的人需要清楚什么任務(wù)適合交給什么模型什么樣的 Prompt 設(shè)計(jì)更穩(wěn)定什么樣的任務(wù)鏈路容易觸發(fā)幻覺(jué)。如果這兩個(gè)角色是同一個(gè)人那這個(gè)團(tuán)隊(duì)的配置就相當(dāng)豪華了。另外還要有足夠的耐心和預(yù)算意識(shí)。MultiAgent 系統(tǒng)的調(diào)試周期比單 Agent 長(zhǎng)很多因?yàn)閱?wèn)題可能出在任意一個(gè)子 Agent、任意一條鏈路上定位問(wèn)題需要抽絲剝繭。我們連續(xù)調(diào)了一周多才把第一個(gè)復(fù)雜鏈路調(diào)到可接受的狀態(tài)如果組織沒(méi)有這個(gè)耐心很容易半途而廢。我個(gè)人覺(jué)得如果團(tuán)隊(duì)現(xiàn)在連單 Agent 的基礎(chǔ)能力都還沒(méi)建起來(lái)不要急著上 MultiAgent先把單 Agent 的穩(wěn)定性、可觀測(cè)性、成本控制這些基本功打好再談“多”的事。地基不穩(wěn)再多 Agent 也只是把錯(cuò)誤放大幾倍。7. 對(duì)這套架構(gòu)的一點(diǎn)復(fù)盤(pán)和心得最后分享一些個(gè)人體會(huì)。我們做這套企業(yè)級(jí) MultiAgent 架構(gòu)最大的感悟是工程的復(fù)雜度并沒(méi)有被 MultiAgent 消滅而是被轉(zhuǎn)移和重新分配了。單 Agent 時(shí)代要跟上下文打架多 Agent 時(shí)代要跟協(xié)作協(xié)議打架你要在系統(tǒng)里引入更高的自由度就必須用更強(qiáng)的工程約束去對(duì)沖。做個(gè)簡(jiǎn)單總結(jié)。Plan 模式解決的是“先把事情想清楚再動(dòng)手”的問(wèn)題主子 Agent 協(xié)作解決的是“多個(gè)角色如何分工配合”的問(wèn)題狀態(tài)機(jī)、冪等、限流、重試解決的是“系統(tǒng)如何保證穩(wěn)”的問(wèn)題Token 預(yù)算、上下文字?jǐn)?shù)約束解決的是“成本如何控制住”的問(wèn)題。這四層缺一不可單靠任何一個(gè)環(huán)節(jié)的優(yōu)化都沒(méi)辦法讓整個(gè)系統(tǒng)穩(wěn)定地跑起來(lái)。如果讓我給一個(gè)最直接的建議那就是在設(shè)計(jì)階段就把子任務(wù)的輸入輸出協(xié)議定死把狀態(tài)流轉(zhuǎn)圖畫(huà)清楚把每個(gè) Agent 的職責(zé)邊界寫(xiě)明白。這些臟活累活看著不起眼卻是整個(gè)系統(tǒng)能不能穩(wěn)定運(yùn)行的最大變量。Agent 的模型能力現(xiàn)在是夠用的真正的差距往往出現(xiàn)在工程治理上。