作框架agency-agents:架構(gòu)設(shè)計(jì)與工程落地實(shí)踐)
1. 從agency-agents這個(gè)名字說起一個(gè)多智能體協(xié)作框架的定位第一次看到agency-agents這個(gè)項(xiàng)目名我的直覺是這大概率是一個(gè)圍繞代理agent和代理機(jī)構(gòu)agency概念做文章的多智能體協(xié)作框架。拆開來看agency在英文里既有代理機(jī)構(gòu)的意思也有能動(dòng)性、自主行動(dòng)能力的含義而agents則是復(fù)數(shù)形式的代理/智能體。把這兩個(gè)詞拼在一起指向的應(yīng)該是一套讓多個(gè)智能體像一家機(jī)構(gòu)里的不同角色那樣協(xié)同工作的系統(tǒng)。這個(gè)判斷不是憑空來的。近兩年圍繞大模型的應(yīng)用開發(fā)已經(jīng)從單次問答快速演進(jìn)到讓模型自己規(guī)劃、調(diào)用工具、分步執(zhí)行任務(wù)的階段。單個(gè)智能體再?gòu)?qiáng)遇到復(fù)雜任務(wù)也會(huì)力不從心——上下文窗口有限、單點(diǎn)能力有短板、無法并行處理子任務(wù)。于是多智能體協(xié)作成了很自然的方向把一個(gè)大任務(wù)拆給多個(gè)各有分工的智能體讓它們像團(tuán)隊(duì)一樣配合。agency-agents 這個(gè)名字恰好踩在這個(gè)方向上。需要先說明的是我拿到的項(xiàng)目正文、關(guān)鍵詞和摘要描述都是空的所以這篇內(nèi)容不是對(duì)某個(gè)具體代碼倉(cāng)庫(kù)的逐行解讀而是基于標(biāo)題本身、結(jié)合多智能體協(xié)作這個(gè)領(lǐng)域的通用實(shí)踐做一次完整的拆解和落地推演。我會(huì)把如果我要從零搭一個(gè)叫 agency-agents 的多智能體協(xié)作框架我會(huì)怎么設(shè)計(jì)、怎么踩坑、怎么調(diào)優(yōu)這件事講透。對(duì)于正在做類似事情的人這篇可以直接當(dāng)設(shè)計(jì)參考對(duì)于剛接觸多智能體的讀者也能借此建立一套完整的認(rèn)知框架。適合讀這篇的人大概有三類一是想給自己的產(chǎn)品加上多角色協(xié)作能力的開發(fā)者二是被單個(gè)智能體越做越亂困擾、想找結(jié)構(gòu)化方案的人三是對(duì) agent 編排orchestration感興趣、想了解工程落地細(xì)節(jié)的技術(shù)負(fù)責(zé)人。下面我會(huì)從核心概念、架構(gòu)設(shè)計(jì)、角色分工、通信機(jī)制、實(shí)操步驟、避坑經(jīng)驗(yàn)幾個(gè)層面展開盡量把每個(gè)為什么都講清楚。2. 多智能體協(xié)作到底解決了單智能體的哪些死結(jié)2.1 單智能體的三個(gè)典型瓶頸在動(dòng)手設(shè)計(jì) agency-agents 之前得先想明白一件事為什么非要多個(gè)智能體單個(gè)大模型加幾個(gè)工具調(diào)用很多時(shí)候也能跑通任務(wù)。我實(shí)際做過不少單智能體的項(xiàng)目總結(jié)下來它有三個(gè)繞不過去的瓶頸。第一個(gè)是上下文污染。當(dāng)一個(gè)智能體既要理解用戶意圖、又要規(guī)劃步驟、還要執(zhí)行具體操作、最后還要檢查結(jié)果時(shí)所有這些信息都堆在同一個(gè)上下文里。任務(wù)一復(fù)雜上下文里就混進(jìn)了大量中間過程的噪音模型很容易忘記最初的目標(biāo)或者在執(zhí)行細(xì)節(jié)時(shí)被之前的規(guī)劃思路帶偏。這就像讓一個(gè)人同時(shí)當(dāng)項(xiàng)目經(jīng)理、程序員和測(cè)試腦子里的角色切換會(huì)互相干擾。第二個(gè)是能力無法專精。單智能體的系統(tǒng)提示詞system prompt往往要兼顧多種能力結(jié)果就是每種能力都寫得比較泛。你很難讓同一個(gè)提示詞既擅長(zhǎng)嚴(yán)謹(jǐn)?shù)拇a審查又擅長(zhǎng)天馬行空的創(chuàng)意發(fā)散。提示詞越長(zhǎng)越全模型對(duì)每一條的遵循度反而越低這是很常見的現(xiàn)象。第三個(gè)是無法并行與隔離。有些子任務(wù)之間沒有依賴關(guān)系本可以同時(shí)做但單智能體只能串行。更麻煩的是一個(gè)子任務(wù)失敗會(huì)污染整個(gè)上下文導(dǎo)致后續(xù)步驟全部受影響缺乏故障隔離。2.2 多智能體帶來的四個(gè)結(jié)構(gòu)性收益agency-agents 這類框架的價(jià)值正是針對(duì)上面三個(gè)瓶頸給出的結(jié)構(gòu)性解法。我把它歸納成四點(diǎn)收益。職責(zé)分離帶來的上下文純凈。每個(gè)智能體只關(guān)心自己那一段規(guī)劃者只管拆解任務(wù)執(zhí)行者只管干活審查者只管挑毛病。各自的上下文里只有和自己相關(guān)的信息噪音大幅減少遵循度自然提升。角色專精帶來的提示詞優(yōu)化空間。因?yàn)槊總€(gè)智能體只干一件事它的系統(tǒng)提示詞可以寫得非常聚焦、非常具體甚至可以為每個(gè)角色單獨(dú)調(diào)參、單獨(dú)選模型。便宜的模型干簡(jiǎn)單的活貴的模型干關(guān)鍵的活成本也能優(yōu)化。并行執(zhí)行帶來的效率提升。沒有依賴關(guān)系的子任務(wù)可以分發(fā)給多個(gè)執(zhí)行智能體同時(shí)處理最后匯總。這在批量處理類任務(wù)上收益非常明顯。故障隔離帶來的魯棒性。某個(gè)執(zhí)行智能體跑掛了不會(huì)直接毀掉整個(gè)流程編排層可以重試、可以換一個(gè)智能體、可以把失敗信息交給審查者處理。這種隔離是單智能體很難做到的。理解了這四點(diǎn)后面所有的架構(gòu)設(shè)計(jì)其實(shí)都是在回答一個(gè)問題怎么把職責(zé)分離、角色專精、并行執(zhí)行、故障隔離這四件事在工程上落地。3. agency-agents 的架構(gòu)骨架編排層、角色層與共享狀態(tài)3.1 三層結(jié)構(gòu)的分工如果讓我來設(shè)計(jì) agency-agents我會(huì)把它拆成三層編排層Orchestration Layer、角色層Agent Layer、共享狀態(tài)層Shared State Layer。這三層各司其職邊界清晰是整個(gè)框架能穩(wěn)定運(yùn)行的基礎(chǔ)。編排層是大腦負(fù)責(zé)接收用戶任務(wù)、決定用哪些角色、按什么順序調(diào)度、處理失敗重試、判斷任務(wù)是否完成。它本身通常也是一個(gè)智能體或者是一段確定性的調(diào)度邏輯。我的經(jīng)驗(yàn)是能用確定性代碼寫的調(diào)度邏輯就不要交給模型去決策。比如先規(guī)劃再執(zhí)行再審查這種固定流程用代碼寫死比讓模型自由發(fā)揮穩(wěn)定得多。模型只應(yīng)該用在真正需要判斷力的地方比如任務(wù)拆解、結(jié)果評(píng)估。角色層是干活的團(tuán)隊(duì)每個(gè)角色是一個(gè)獨(dú)立的智能體實(shí)例有自己的系統(tǒng)提示詞、工具集、模型配置。角色之間不直接互相調(diào)用而是通過編排層或共享狀態(tài)來交換信息。這一點(diǎn)很關(guān)鍵——如果讓角色之間隨意互相調(diào)用很快就會(huì)變成一團(tuán)亂麻調(diào)試時(shí)根本追不清調(diào)用鏈。共享狀態(tài)層是公共白板存放任務(wù)描述、中間產(chǎn)物、各角色的輸出、執(zhí)行日志等。所有角色讀寫這塊共享區(qū)域而不是把信息塞在消息里傳來傳去。這樣做的好處是信息有單一可信來源任何角色都能看到全局進(jìn)展也方便做持久化和斷點(diǎn)恢復(fù)。3.2 為什么用共享狀態(tài)而不是純消息傳遞這里我要專門解釋一下為什么傾向共享狀態(tài)而不是純消息傳遞因?yàn)檫@是很多人在設(shè)計(jì)多智能體系統(tǒng)時(shí)容易走偏的地方。純消息傳遞的模式下智能體 A 把結(jié)果發(fā)給 BB 處理完發(fā)給 C。聽起來很清晰但實(shí)際跑起來問題很多消息格式要嚴(yán)格約定一旦某個(gè)環(huán)節(jié)格式不對(duì)整條鏈就斷了中間結(jié)果無法復(fù)用如果 D 也需要 A 的輸出就得讓 A 再發(fā)一遍或者層層轉(zhuǎn)發(fā)調(diào)試時(shí)你只能看到一條條消息很難還原當(dāng)前全局狀態(tài)到底是什么。共享狀態(tài)模式則像一塊大家都能讀寫的白板。A 把結(jié)果寫到白板的某個(gè)區(qū)域B、C、D 誰(shuí)需要誰(shuí)去讀。信息只寫一次多處復(fù)用。調(diào)試時(shí)直接看白板快照全局一目了然。當(dāng)然共享狀態(tài)也有代價(jià)——需要處理并發(fā)寫入的沖突需要設(shè)計(jì)好狀態(tài)的結(jié)構(gòu)。但對(duì)于 agency-agents 這種多角色協(xié)作場(chǎng)景共享狀態(tài)的收益遠(yuǎn)大于成本。我通常會(huì)把共享狀態(tài)設(shè)計(jì)成一個(gè)結(jié)構(gòu)化的對(duì)象大致包含這幾個(gè)字段任務(wù)目標(biāo)、任務(wù)拆解后的子任務(wù)列表、每個(gè)子任務(wù)的狀態(tài)待處理/進(jìn)行中/已完成/失敗、每個(gè)子任務(wù)的產(chǎn)出、全局的執(zhí)行日志、以及一個(gè)當(dāng)前階段標(biāo)記。這個(gè)結(jié)構(gòu)用 JSON 或類似格式序列化方便持久化和恢復(fù)。3.3 編排層的調(diào)度策略選擇編排層的調(diào)度策略直接決定了整個(gè)系統(tǒng)的行為模式。常見的有三種順序流水線、動(dòng)態(tài)路由、混合模式。順序流水線最簡(jiǎn)單規(guī)劃者拆任務(wù)執(zhí)行者逐個(gè)做審查者最后檢查。適合流程固定的場(chǎng)景比如寫一份報(bào)告這種線性任務(wù)。優(yōu)點(diǎn)是穩(wěn)定可預(yù)測(cè)缺點(diǎn)是靈活性差。動(dòng)態(tài)路由更靈活編排層根據(jù)當(dāng)前狀態(tài)動(dòng)態(tài)決定下一步該叫哪個(gè)角色。比如執(zhí)行者報(bào)告某個(gè)子任務(wù)失敗編排層可以決定是重試、是換個(gè)角色做、還是叫審查者介入。這種模式適合任務(wù)結(jié)構(gòu)不確定的場(chǎng)景但調(diào)度邏輯復(fù)雜容易出 bug。混合模式是我最推薦的主干流程用順序流水線保證穩(wěn)定在關(guān)鍵決策點(diǎn)引入動(dòng)態(tài)路由處理異常。比如正常情況按規(guī)劃→執(zhí)行→審查走但執(zhí)行階段如果某個(gè)子任務(wù)連續(xù)失敗兩次就動(dòng)態(tài)插入一個(gè)診斷角色來分析原因。這樣既有穩(wěn)定性又有靈活性。4. 角色設(shè)計(jì)一個(gè) agency 里到底該有哪些 agent4.1 核心角色清單與職責(zé)邊界一個(gè)能跑通復(fù)雜任務(wù)的 agency我建議至少包含這幾類角色。注意角色不是越多越好每多一個(gè)角色就多一份調(diào)度復(fù)雜度和 token 成本夠用就行。角色核心職責(zé)典型工具建議模型檔位規(guī)劃者 Planner把用戶任務(wù)拆成可執(zhí)行的子任務(wù)無或僅任務(wù)管理工具高能力模型執(zhí)行者 Executor完成具體子任務(wù)搜索、代碼執(zhí)行、文件讀寫等中高能力模型審查者 Reviewer檢查產(chǎn)出質(zhì)量、發(fā)現(xiàn)錯(cuò)誤無或校驗(yàn)工具高能力模型匯總者 Synthesizer把多個(gè)子任務(wù)產(chǎn)出整合成最終結(jié)果無中高能力模型診斷者 Diagnoser分析失敗原因、給出修復(fù)建議日志讀取高能力模型規(guī)劃者是整個(gè)流程的起點(diǎn)它的輸出質(zhì)量直接決定后續(xù)所有環(huán)節(jié)。我踩過的坑是規(guī)劃者拆的任務(wù)粒度太粗或太細(xì)都不行。太粗執(zhí)行者拿到一個(gè)模糊的大任務(wù)還是不知道怎么做太細(xì)子任務(wù)數(shù)量爆炸調(diào)度開銷和 token 成本飆升。我的經(jīng)驗(yàn)是每個(gè)子任務(wù)應(yīng)該是一個(gè)執(zhí)行者能在一次交互內(nèi)完成、且有明確驗(yàn)收標(biāo)準(zhǔn)的單元。執(zhí)行者是數(shù)量最多的角色可以按領(lǐng)域再細(xì)分。比如做數(shù)據(jù)分析的 agency執(zhí)行者可以分成數(shù)據(jù)獲取者數(shù)據(jù)清洗者統(tǒng)計(jì)分析者可視化者。細(xì)分的好處是每個(gè)執(zhí)行者的提示詞和工具集都能高度專精。審查者的價(jià)值經(jīng)常被低估。很多人覺得模型自己產(chǎn)出的東西自己檢查就行但實(shí)測(cè)下來讓一個(gè)獨(dú)立的、帶著挑刺心態(tài)的審查者來檢查發(fā)現(xiàn)問題的概率明顯高于讓執(zhí)行者自查。因?yàn)閳?zhí)行者有自己的思維慣性容易對(duì)自己的產(chǎn)出過度自信。審查者的提示詞要明確要求它假設(shè)產(chǎn)出有問題主動(dòng)找證據(jù)而不是看看有沒有問題。4.2 角色提示詞的寫法三個(gè)必須寫清楚的要素每個(gè)角色的系統(tǒng)提示詞我建議必須寫清楚三件事身份與目標(biāo)、能力邊界、輸出格式。身份與目標(biāo)要具體。不要寫你是一個(gè)助手而要寫你是一個(gè)負(fù)責(zé)把復(fù)雜任務(wù)拆解成可執(zhí)行步驟的規(guī)劃專家你的目標(biāo)是產(chǎn)出粒度適中、依賴關(guān)系清晰的子任務(wù)列表。越具體模型越能進(jìn)入狀態(tài)。能力邊界要明確說不做什么。比如執(zhí)行者的提示詞里要寫你只負(fù)責(zé)完成分配給你的子任務(wù)不要嘗試規(guī)劃整體流程不要修改其他子任務(wù)的內(nèi)容。這條極其重要因?yàn)槟P吞烊挥性浇绲膬A向不明確禁止它就會(huì)去干不屬于自己的活導(dǎo)致職責(zé)混亂。輸出格式要嚴(yán)格約定。多智能體系統(tǒng)里角色之間的輸出是要被程序解析的格式不對(duì)整個(gè)流程就斷了。我通常要求角色輸出結(jié)構(gòu)化的 JSON并在提示詞里給出完整的 schema 示例。如果模型經(jīng)常不遵守格式可以在提示詞末尾加一句只輸出 JSON不要有任何其他文字效果通常不錯(cuò)。4.3 角色數(shù)量與成本的權(quán)衡這里分享一個(gè)很實(shí)際的經(jīng)驗(yàn)角色數(shù)量要跟著任務(wù)復(fù)雜度走不要一上來就搭一個(gè)十幾個(gè)角色的龐大體系。我見過有人一上來就設(shè)計(jì)了規(guī)劃、執(zhí)行、審查、匯總、診斷、記憶管理、工具路由等七八個(gè)角色結(jié)果調(diào)試了兩周還沒跑通一個(gè)完整任務(wù)。原因是角色越多交互路徑越多出問題的地方越多而且 token 成本是線性甚至指數(shù)級(jí)增長(zhǎng)的。我的建議是從最小可用集開始規(guī)劃者 執(zhí)行者 審查者三個(gè)角色先跑通一個(gè)簡(jiǎn)單任務(wù)。跑通之后再根據(jù)實(shí)際遇到的瓶頸逐步增加角色。比如發(fā)現(xiàn)執(zhí)行者經(jīng)常失敗但不知道為什么再加診斷者發(fā)現(xiàn)多個(gè)執(zhí)行者產(chǎn)出需要整合再加匯總者。這種漸進(jìn)式的做法比一次性設(shè)計(jì)一個(gè)大而全的體系要靠譜得多。5. 智能體之間的通信消息格式、狀態(tài)同步與沖突處理5.1 結(jié)構(gòu)化消息格式的設(shè)計(jì)角色之間傳遞的信息必須是結(jié)構(gòu)化的不能是自由文本。我通常設(shè)計(jì)一個(gè)統(tǒng)一的消息信封envelope包含這幾個(gè)字段發(fā)送者、接收者、消息類型、負(fù)載payload、時(shí)間戳、關(guān)聯(lián)的子任務(wù) ID。消息類型我一般定義幾種任務(wù)分配、任務(wù)結(jié)果、任務(wù)失敗、狀態(tài)查詢、審查意見。每種類型對(duì)應(yīng)不同的 payload 結(jié)構(gòu)。比如任務(wù)結(jié)果的 payload 里要有子任務(wù) ID、產(chǎn)出內(nèi)容、執(zhí)行耗時(shí)、使用的工具列表任務(wù)失敗的 payload 里要有失敗原因、錯(cuò)誤堆棧、已嘗試的方案。為什么要這么細(xì)因?yàn)榫幣艑有枰鶕?jù)這些結(jié)構(gòu)化字段做決策。比如看到某個(gè)子任務(wù)失敗且錯(cuò)誤類型是工具調(diào)用超時(shí)編排層就知道可以重試如果錯(cuò)誤類型是輸入格式錯(cuò)誤那重試也沒用得讓規(guī)劃者重新拆任務(wù)。這些判斷都依賴結(jié)構(gòu)化的錯(cuò)誤信息自由文本是做不到的。5.2 共享狀態(tài)的并發(fā)寫入問題前面說了用共享狀態(tài)但共享狀態(tài)有個(gè)繞不開的問題多個(gè)執(zhí)行者并行寫入時(shí)怎么避免沖突我的做法是按子任務(wù)分區(qū)。共享狀態(tài)里每個(gè)子任務(wù)有自己獨(dú)立的區(qū)域執(zhí)行者只寫自己負(fù)責(zé)的子任務(wù)區(qū)域不碰別人的。這樣并行寫入時(shí)天然不沖突。全局性的字段比如當(dāng)前階段整體進(jìn)度只由編排層寫入執(zhí)行者只讀不寫。如果確實(shí)需要多個(gè)角色寫同一塊區(qū)域比如多個(gè)審查者都要往審查意見列表里追加那就用追加append而不是覆蓋overwrite的語(yǔ)義并且給每條記錄帶上寫入者標(biāo)識(shí)和時(shí)間戳。這樣即使并發(fā)寫入也只是順序問題不會(huì)丟數(shù)據(jù)。5.3 狀態(tài)同步的時(shí)機(jī)與粒度狀態(tài)同步的時(shí)機(jī)也很講究。同步太頻繁開銷大同步太少各角色看到的狀態(tài)不一致容易做出錯(cuò)誤決策。我的經(jīng)驗(yàn)是在角色切換的邊界做同步。也就是說一個(gè)角色完成工作、把結(jié)果寫入共享狀態(tài)后編排層做一次狀態(tài)快照然后再啟動(dòng)下一個(gè)角色。這樣每個(gè)角色啟動(dòng)時(shí)看到的都是最新的、一致的狀態(tài)。角色執(zhí)行過程中不需要實(shí)時(shí)同步因?yàn)樗徊僮髯约耗菈K區(qū)域。對(duì)于并行執(zhí)行的多個(gè)執(zhí)行者它們各自完成后分別寫入自己的區(qū)域編排層等所有并行任務(wù)都結(jié)束后再做一次匯總同步。這種邊界同步的策略在保證一致性的同時(shí)把同步開銷降到了最低。6. 從零搭一個(gè) agency-agents 的實(shí)操步驟6.1 環(huán)境準(zhǔn)備與依賴選型假設(shè)現(xiàn)在要?jiǎng)邮謱?shí)現(xiàn)我會(huì)這樣準(zhǔn)備環(huán)境。首先是語(yǔ)言和框架的選擇Python 是這類項(xiàng)目的主流選擇生態(tài)成熟各種大模型 SDK 都有官方支持。編排邏輯可以用純 Python 寫也可以用現(xiàn)成的編排框架但我建議核心調(diào)度邏輯自己寫因?yàn)楝F(xiàn)成框架的抽象往往和你的具體需求不完全匹配改起來反而更費(fèi)勁。依賴方面至少需要一個(gè)大模型的調(diào)用 SDK、一個(gè)用于結(jié)構(gòu)化輸出的校驗(yàn)庫(kù)比如 Pydantic 這類做數(shù)據(jù)校驗(yàn)的、一個(gè)持久化方案初期用本地文件或輕量數(shù)據(jù)庫(kù)就夠。如果涉及工具調(diào)用還需要準(zhǔn)備各個(gè)工具對(duì)應(yīng)的客戶端庫(kù)。配置管理要提前做好。模型 API 的密鑰、各角色的模型選擇、超時(shí)時(shí)間、重試次數(shù)這些都應(yīng)該放在配置文件里不要硬編碼。我見過太多項(xiàng)目把這些寫死在代碼里換個(gè)環(huán)境就要改代碼非常痛苦。6.2 定義共享狀態(tài)的數(shù)據(jù)結(jié)構(gòu)第一步是定義共享狀態(tài)。用 Pydantic 或類似工具定義一個(gè)狀態(tài)類包含任務(wù)目標(biāo)、子任務(wù)列表、每個(gè)子任務(wù)的狀態(tài)和產(chǎn)出、執(zhí)行日志、當(dāng)前階段。每個(gè)子任務(wù)本身也是一個(gè)結(jié)構(gòu)包含 ID、描述、依賴的子任務(wù) ID、狀態(tài)、產(chǎn)出、錯(cuò)誤信息。定義好之后寫兩個(gè)基礎(chǔ)方法一個(gè)是把狀態(tài)序列化成 JSON 存盤一個(gè)是從 JSON 反序列化恢復(fù)。這兩個(gè)方法是斷點(diǎn)恢復(fù)的基礎(chǔ)一定要在項(xiàng)目早期就做好。我吃過虧——項(xiàng)目做到一半才想起來要支持?jǐn)帱c(diǎn)恢復(fù)結(jié)果發(fā)現(xiàn)狀態(tài)結(jié)構(gòu)設(shè)計(jì)得不合理序列化出來一堆問題返工成本很高。6.3 實(shí)現(xiàn)規(guī)劃者任務(wù)拆解的關(guān)鍵技巧規(guī)劃者的實(shí)現(xiàn)核心是提示詞設(shè)計(jì)和輸出解析。提示詞里要明確要求它輸出一個(gè)子任務(wù)列表每個(gè)子任務(wù)包含描述、依賴關(guān)系、驗(yàn)收標(biāo)準(zhǔn)。輸出用 JSON 格式方便解析。這里有個(gè)關(guān)鍵技巧在提示詞里給規(guī)劃者一個(gè)拆解原則。比如每個(gè)子任務(wù)應(yīng)該能在一次交互內(nèi)完成子任務(wù)之間的依賴關(guān)系要顯式聲明每個(gè)子任務(wù)要有可驗(yàn)證的完成標(biāo)準(zhǔn)。不給這些原則規(guī)劃者拆出來的任務(wù)質(zhì)量參差不齊。解析規(guī)劃者輸出時(shí)一定要做校驗(yàn)。檢查子任務(wù)數(shù)量是否合理比如超過 20 個(gè)就要警惕、依賴關(guān)系是否有環(huán)、每個(gè)子任務(wù)是否有描述和驗(yàn)收標(biāo)準(zhǔn)。校驗(yàn)不通過就帶著錯(cuò)誤信息讓規(guī)劃者重新拆通常重試一兩次就能得到合格的結(jié)果。6.4 實(shí)現(xiàn)執(zhí)行者工具調(diào)用與結(jié)果回寫執(zhí)行者的實(shí)現(xiàn)相對(duì)直接但有幾個(gè)細(xì)節(jié)要注意。執(zhí)行者拿到子任務(wù)后要根據(jù)任務(wù)描述決定調(diào)用哪些工具、按什么順序調(diào)用。這里我建議給執(zhí)行者一個(gè)明確的工具使用規(guī)范比如優(yōu)先使用搜索工具獲取事實(shí)信息代碼執(zhí)行前先檢查輸入格式。執(zhí)行完成后執(zhí)行者要把結(jié)果寫回共享狀態(tài)對(duì)應(yīng)的子任務(wù)區(qū)域并更新子任務(wù)狀態(tài)。如果執(zhí)行失敗要寫入結(jié)構(gòu)化的錯(cuò)誤信息而不是簡(jiǎn)單拋個(gè)異常。錯(cuò)誤信息里至少要有失敗原因分類、詳細(xì)描述、已嘗試的方案。這些信息是后續(xù)診斷和重試的依據(jù)。6.5 實(shí)現(xiàn)審查者與匯總者審查者拿到執(zhí)行者的產(chǎn)出后對(duì)照子任務(wù)的驗(yàn)收標(biāo)準(zhǔn)做檢查。它的輸出應(yīng)該是一個(gè)結(jié)構(gòu)化的審查結(jié)果通過/不通過、不通過的具體問題、修改建議。如果審查不通過編排層要把問題反饋給執(zhí)行者重新做或者交給診斷者分析。匯總者在所有子任務(wù)完成后啟動(dòng)把所有子任務(wù)的產(chǎn)出整合成最終結(jié)果。它的提示詞要強(qiáng)調(diào)保持各部分的一致性消除重復(fù)內(nèi)容確保整體邏輯連貫。匯總不是簡(jiǎn)單拼接而是真正的整合這一步做不好前面所有工作都會(huì)打折扣。6.6 編排主循環(huán)的編寫編排主循環(huán)是整個(gè)系統(tǒng)的中樞。它的邏輯大致是初始化狀態(tài) → 調(diào)用規(guī)劃者 → 循環(huán)處理子任務(wù)按依賴順序無依賴的并行→ 每個(gè)子任務(wù)執(zhí)行后調(diào)用審查者 → 全部完成后調(diào)用匯總者 → 輸出最終結(jié)果。循環(huán)里要處理各種異常執(zhí)行失敗的重試、審查不通過的返工、超時(shí)的處理。每個(gè)異常處理分支都要有明確的策略和上限比如同一子任務(wù)最多重試 3 次整個(gè)任務(wù)最多運(yùn)行 30 分鐘。沒有上限的循環(huán)是災(zāi)難我見過因?yàn)橐粋€(gè)子任務(wù)反復(fù)失敗導(dǎo)致整個(gè)流程跑了幾個(gè)小時(shí)、燒掉大量 token 的情況。7. 實(shí)測(cè)中踩過的坑與調(diào)優(yōu)經(jīng)驗(yàn)7.1 規(guī)劃者拆任務(wù)粒度失控最常見的坑是規(guī)劃者拆出來的任務(wù)粒度不合適。要么太粗執(zhí)行者拿到分析這份數(shù)據(jù)這種模糊任務(wù)無從下手要么太細(xì)把讀取文件和解析文件都拆成獨(dú)立子任務(wù)導(dǎo)致子任務(wù)數(shù)量爆炸。我的解法是在提示詞里給出正反例。比如正面例子是計(jì)算過去 12 個(gè)月的月度銷售增長(zhǎng)率并生成趨勢(shì)圖反面例子是分析數(shù)據(jù)太粗和打開文件太細(xì)。給了具體例子之后規(guī)劃者的輸出質(zhì)量明顯提升。另外可以在解析階段做自動(dòng)檢查子任務(wù)描述少于一定字?jǐn)?shù)就判定為太粗打回重拆。7.2 執(zhí)行者越界修改全局狀態(tài)執(zhí)行者越界是個(gè)隱蔽但危害很大的問題。表現(xiàn)是執(zhí)行者在完成自己任務(wù)的同時(shí)順手改了共享狀態(tài)里不屬于它的區(qū)域或者擅自修改了子任務(wù)列表。這會(huì)導(dǎo)致狀態(tài)混亂后續(xù)角色基于錯(cuò)誤狀態(tài)做決策。解法是在執(zhí)行者的提示詞里明確禁止同時(shí)在代碼層面做權(quán)限控制——執(zhí)行者只能寫自己子任務(wù)對(duì)應(yīng)的區(qū)域?qū)懫渌麉^(qū)域直接拒絕并記錄警告。提示詞約束加代碼約束雙保險(xiǎn)基本能杜絕這個(gè)問題。7.3 審查者過于寬松或過于苛刻審查者的尺度很難把握。太寬松問題漏過去最終結(jié)果質(zhì)量差太苛刻什么都通不過執(zhí)行者反復(fù)返工流程卡死。我的調(diào)法是給審查者明確的判定標(biāo)準(zhǔn)并且要求它區(qū)分必須修改和建議優(yōu)化兩類問題。必須修改的才觸發(fā)返工建議優(yōu)化的記錄在案但不阻塞流程。這樣既保證了質(zhì)量底線又避免了無限返工。另外可以給審查者設(shè)一個(gè)通過率的軟約束如果它連續(xù)判定多個(gè)子任務(wù)不通過就提示它重新審視標(biāo)準(zhǔn)是否過嚴(yán)。7.4 token 成本失控的排查多智能體系統(tǒng)的 token 成本很容易失控因?yàn)槊總€(gè)角色都要消耗 token而且共享狀態(tài)越大每個(gè)角色讀取時(shí)消耗的 token 越多。排查成本問題我一般先看共享狀態(tài)的大小。如果狀態(tài)里堆積了大量中間過程的詳細(xì)日志每個(gè)角色讀取時(shí)都要把這些日志讀進(jìn)去成本自然高。解法是給共享狀態(tài)做分層角色默認(rèn)只讀和自己相關(guān)的部分全局摘要信息單獨(dú)維護(hù)一份精簡(jiǎn)版。這樣每個(gè)角色讀取的上下文就小很多。另一個(gè)成本大頭是重試。如果某個(gè)子任務(wù)反復(fù)失敗重試token 消耗會(huì)成倍增長(zhǎng)。所以要給重試設(shè)上限并且每次重試時(shí)把之前的失敗信息精簡(jiǎn)后再傳給執(zhí)行者避免上下文越滾越大。7.5 并行執(zhí)行時(shí)的資源競(jìng)爭(zhēng)并行執(zhí)行多個(gè)子任務(wù)時(shí)如果它們都要調(diào)用同一個(gè)外部工具比如同一個(gè)搜索接口可能會(huì)觸發(fā)限流。這個(gè)坑我在實(shí)際項(xiàng)目里踩過多個(gè)執(zhí)行者同時(shí)發(fā)請(qǐng)求結(jié)果被接口方限流全部失敗。解法是給外部工具調(diào)用加一個(gè)統(tǒng)一的限流器控制并發(fā)數(shù)。另外并行度不要設(shè)太高一般 3 到 5 個(gè)并行就夠了再高收益遞減而風(fēng)險(xiǎn)上升。并行度這個(gè)參數(shù)最好做成可配置的方便根據(jù)實(shí)際情況調(diào)整。8. 這套框架適合什么場(chǎng)景以及后續(xù)可以怎么擴(kuò)展agency-agents 這類多智能體協(xié)作框架最適合的是任務(wù)結(jié)構(gòu)相對(duì)復(fù)雜、可以拆解、且對(duì)結(jié)果質(zhì)量有要求的場(chǎng)景。比如長(zhǎng)文檔的撰寫與審校、多步驟的數(shù)據(jù)分析流程、需要多輪驗(yàn)證的代碼生成、復(fù)雜的信息調(diào)研與整合。這些場(chǎng)景的共同點(diǎn)是單次交互搞不定但拆開之后每個(gè)子任務(wù)都不算太難。反過來如果任務(wù)本身很簡(jiǎn)單比如單輪問答、簡(jiǎn)單的格式轉(zhuǎn)換那用多智能體就是殺雞用牛刀徒增成本和復(fù)雜度。判斷標(biāo)準(zhǔn)很簡(jiǎn)單如果你用單智能體加幾個(gè)工具調(diào)用就能穩(wěn)定搞定就不要上多智能體。后續(xù)擴(kuò)展方向我覺得有幾個(gè)值得嘗試。一是引入長(zhǎng)期記憶讓 agency 能記住之前處理過的類似任務(wù)復(fù)用經(jīng)驗(yàn)。二是動(dòng)態(tài)角色生成根據(jù)任務(wù)類型自動(dòng)決定需要哪些角色而不是預(yù)先寫死。三是多 agency 協(xié)作讓多個(gè) agency 各自負(fù)責(zé)一塊再有一個(gè)更高層的編排者協(xié)調(diào)它們。這些方向都很有意思但每加一層復(fù)雜度調(diào)試難度都會(huì)上一個(gè)臺(tái)階建議在單 agency 跑穩(wěn)之后再考慮。最后分享一個(gè)我自己的體會(huì)多智能體系統(tǒng)的調(diào)試比單智能體難得多因?yàn)閱栴}可能出在任何一個(gè)角色、任何一次交互上。所以日志和可觀測(cè)性一定要在項(xiàng)目早期就做好。每個(gè)角色的輸入輸出、每次狀態(tài)變更、每個(gè)決策點(diǎn)都要有清晰的日志。我現(xiàn)在的習(xí)慣是在編排層加一個(gè)回放功能能把一次完整執(zhí)行的所有交互按時(shí)間順序打印出來。有了這個(gè)排查問題的時(shí)間能縮短一大半。這個(gè)投入絕對(duì)值得。