用:并行與順序執(zhí)行策略的工程實(shí)踐)
1. 從一次線上故障說起當(dāng)Agent“貪心”地調(diào)用多個(gè)工具時(shí)那天下午監(jiān)控告警突然響了。一個(gè)處理用戶訂單的AI Agent服務(wù)響應(yīng)時(shí)間從平時(shí)的200毫秒飆到了5秒以上直接觸發(fā)了P95延遲紅線。我趕緊登錄服務(wù)器查看日志發(fā)現(xiàn)了一個(gè)有趣又棘手的問題。這個(gè)Agent的核心邏輯是分析用戶的自然語言指令比如“幫我查一下訂單12345的狀態(tài)如果還沒發(fā)貨就取消它并申請(qǐng)退款”。在復(fù)雜的場(chǎng)景下Agent經(jīng)過推理可能會(huì)決定需要調(diào)用多個(gè)工具Tool才能完成任務(wù)。日志清晰地顯示在一次請(qǐng)求中Agent一次性返回了三個(gè)Tool Callget_order_status、cancel_order、apply_for_refund。問題就出在執(zhí)行這三個(gè)調(diào)用的方式上。當(dāng)時(shí)的代碼簡(jiǎn)單粗暴地使用了Promise.all讓這三個(gè)工具調(diào)用并行發(fā)起。結(jié)果get_order_status這個(gè)查詢接口很快返回了“已發(fā)貨”的狀態(tài)但后續(xù)的cancel_order和apply_for_refund調(diào)用已經(jīng)像脫韁的野馬一樣同時(shí)發(fā)出去了。這不僅導(dǎo)致了業(yè)務(wù)邏輯錯(cuò)誤對(duì)已發(fā)貨訂單執(zhí)行了非法操作還因?yàn)楹髢蓚€(gè)調(diào)用涉及數(shù)據(jù)庫(kù)寫事務(wù)和外部支付網(wǎng)關(guān)通信在并發(fā)下引發(fā)了短暫的鎖競(jìng)爭(zhēng)和資源爭(zhēng)用拖慢了整個(gè)鏈路的響應(yīng)。這次故障讓我深刻反思當(dāng)我們的AI Agent雄心勃勃地規(guī)劃好了一系列行動(dòng)多個(gè)Tool Call我們作為實(shí)現(xiàn)者是應(yīng)該讓它們“齊頭并進(jìn)”并行執(zhí)行以追求極致的速度還是讓它們“排好隊(duì)”順序執(zhí)行來保證嚴(yán)謹(jǐn)?shù)倪壿嬤@絕不是一個(gè)可以拍腦袋的決定它背后是并發(fā)控制、業(yè)務(wù)一致性、資源管理和錯(cuò)誤處理等多個(gè)維度的復(fù)雜權(quán)衡。今天我們就來徹底拆解這個(gè)問題看看在不同的場(chǎng)景下如何為你的Agent選擇正確的執(zhí)行策略。2. 并行 vs. 順序兩種執(zhí)行模式的本質(zhì)剖析在深入討論選擇之前我們必須先厘清“并行執(zhí)行”和“順序執(zhí)行”在Agent工具調(diào)用上下文中的具體含義、實(shí)現(xiàn)機(jī)制以及它們的根本差異。2.1 并行執(zhí)行追求吞吐量的“火力全開”并行執(zhí)行顧名思義是指同時(shí)發(fā)起多個(gè)工具調(diào)用并等待所有調(diào)用完成。在JavaScript/Node.js環(huán)境中這通常通過Promise.all或Promise.allSettled來實(shí)現(xiàn)在Python中則可能使用asyncio.gather。它的核心運(yùn)作模式是同時(shí)發(fā)起Agent生成N個(gè)Tool Call后執(zhí)行引擎幾乎在同一時(shí)刻在單線程異步模型中是快速連續(xù)地調(diào)度向所有對(duì)應(yīng)的工具接口發(fā)起請(qǐng)求。獨(dú)立運(yùn)行每個(gè)工具調(diào)用在自己的執(zhí)行上下文中運(yùn)行彼此之間沒有直接的阻塞或等待。統(tǒng)一收集執(zhí)行引擎等待所有調(diào)用完成或部分完成如allSettled然后收集所有結(jié)果。這種模式的優(yōu)勢(shì)非常明顯最大化利用I/O等待時(shí)間這是并行最大的收益點(diǎn)。如果工具調(diào)用主要是網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)查詢等I/O密集型操作CPU在發(fā)出請(qǐng)求后就會(huì)空閑下來等待響應(yīng)。并行執(zhí)行可以讓CPU在等待一個(gè)請(qǐng)求響應(yīng)時(shí)去處理另一個(gè)請(qǐng)求的發(fā)送或接收從而將原本串行的多個(gè)等待時(shí)間重疊起來。假設(shè)有三個(gè)工具調(diào)用每個(gè)耗時(shí)100毫秒順序執(zhí)行需要300毫秒而并行執(zhí)行理想情況下可能只需要100毫秒多一點(diǎn)。提升整體吞吐量對(duì)于Agent處理大量獨(dú)立請(qǐng)求的場(chǎng)景并行化能顯著減少單個(gè)請(qǐng)求的總耗時(shí)從而提高系統(tǒng)整體的請(qǐng)求處理能力。然而它的代價(jià)和風(fēng)險(xiǎn)同樣突出喪失邏輯依賴性并行執(zhí)行假設(shè)所有工具調(diào)用是彼此獨(dú)立的。一旦調(diào)用之間存在邏輯上的先后順序或數(shù)據(jù)依賴并行就會(huì)導(dǎo)致錯(cuò)誤。就像開頭的例子查詢狀態(tài)必須在取消訂單之前完成以決定后續(xù)操作是否執(zhí)行。資源沖擊與限流同時(shí)發(fā)起大量外部調(diào)用可能瞬間打爆下游服務(wù)的限流閾值導(dǎo)致大量請(qǐng)求失敗或被拒絕。例如同時(shí)調(diào)用10個(gè)第三方API很可能觸發(fā)對(duì)方的速率限制。錯(cuò)誤處理復(fù)雜化當(dāng)一個(gè)調(diào)用失敗時(shí)其他調(diào)用可能仍在進(jìn)行中。你需要決定是立即取消所有未完成的調(diào)用這本身需要額外的協(xié)調(diào)機(jī)制還是讓它們繼續(xù)然后處理部分成功、部分失敗的局面。使用Promise.all時(shí)一個(gè)失敗會(huì)導(dǎo)致整個(gè)批次被拒絕你需要從異常中提取其他可能成功的結(jié)果。加劇競(jìng)爭(zhēng)條件如果多個(gè)工具操作共享資源如寫入同一數(shù)據(jù)庫(kù)記錄并行執(zhí)行極易導(dǎo)致臟寫、更新丟失等并發(fā)問題。2.2 順序執(zhí)行恪守邏輯的“步步為營(yíng)”順序執(zhí)行是指嚴(yán)格按照Agent返回的Tool Call列表順序逐個(gè)執(zhí)行只有前一個(gè)調(diào)用成功完成后才會(huì)發(fā)起下一個(gè)。它的核心運(yùn)作模式是順序迭代執(zhí)行引擎循環(huán)遍歷Tool Call列表。等待-執(zhí)行對(duì)于每個(gè)Tool Call等待其完全執(zhí)行完畢成功或失敗并獲取結(jié)果。結(jié)果傳遞與決策將上一個(gè)調(diào)用的結(jié)果作為上下文或決策依據(jù)傳遞給下一個(gè)Tool Call如果需要然后決定是否繼續(xù)執(zhí)行下一個(gè)。這種模式的優(yōu)勢(shì)在于其確定性和可控性天然保證邏輯順序這是順序執(zhí)行最根本的價(jià)值。它完美契合了那些具有嚴(yán)格前后依賴關(guān)系的操作流程例如“先登錄再查詢后下單”。簡(jiǎn)化錯(cuò)誤處理一旦某個(gè)步驟失敗你可以立即中止整個(gè)流程前面的步驟已經(jīng)完成后面的步驟尚未開始狀態(tài)清晰。重試或補(bǔ)償策略也更容易實(shí)施。避免資源沖突由于同一時(shí)間只有一個(gè)寫操作在進(jìn)行從根本上避免了并發(fā)寫帶來的競(jìng)爭(zhēng)條件。符合直觀的業(yè)務(wù)流很多業(yè)務(wù)流程本身就是線性的順序執(zhí)行代碼更易于閱讀、理解和調(diào)試。它的缺點(diǎn)也同樣直接總耗時(shí)累加這是最顯著的性能代價(jià)??傢憫?yīng)時(shí)間等于所有工具調(diào)用耗時(shí)的總和無法利用I/O等待時(shí)間。在調(diào)用鏈較長(zhǎng)或單個(gè)調(diào)用較慢時(shí)用戶體驗(yàn)會(huì)受影響。潛在的資源閑置在等待一個(gè)慢速I/O響應(yīng)時(shí)CPU和其他資源可能處于空閑狀態(tài)無法充分利用。2.3 核心矛盾效率與正確性的博弈通過上面的對(duì)比我們可以清晰地看到并行與順序的選擇本質(zhì)上是系統(tǒng)效率吞吐量、延遲與業(yè)務(wù)邏輯正確性一致性、依賴性之間的博弈。追求極致性能時(shí)如果工具調(diào)用彼此完全獨(dú)立例如Agent同時(shí)查詢北京的天氣、上海的股價(jià)和紐約的新聞并行是不二之選。保障業(yè)務(wù)正確時(shí)如果工具調(diào)用存在哪怕一絲的依賴關(guān)系數(shù)據(jù)依賴、狀態(tài)依賴、因果依賴順序執(zhí)行就是必須堅(jiān)守的底線。在實(shí)際的Agent應(yīng)用中純獨(dú)立或純依賴的場(chǎng)景都是少數(shù)大量的是混合場(chǎng)景。這就需要我們引入更精細(xì)的執(zhí)行策略。3. 超越二選一混合與動(dòng)態(tài)執(zhí)行策略聰明的架構(gòu)不會(huì)把自己困在非此即彼的選擇里。面對(duì)復(fù)雜的現(xiàn)實(shí)需求我們可以設(shè)計(jì)出混合執(zhí)行策略甚至讓Agent自己參與決策。3.1 依賴關(guān)系分析與有向無環(huán)圖DAG執(zhí)行這是處理混合依賴場(chǎng)景的經(jīng)典方法。思路是不簡(jiǎn)單地看Tool Call的列表順序而是分析它們之間的內(nèi)在依賴關(guān)系構(gòu)建一個(gè)執(zhí)行流程圖。如何實(shí)施依賴聲明在每個(gè)工具的定義或Agent的提示詞中聲明其輸入和輸出。例如工具A輸出order_id工具B需要輸入order_id那么就存在一條從A到B的依賴邊。構(gòu)建DAG根據(jù)Tool Call列表和依賴聲明構(gòu)建一個(gè)有向無環(huán)圖。節(jié)點(diǎn)是Tool Call邊表示依賴關(guān)系A(chǔ) - B 表示B依賴A的結(jié)果。拓?fù)渑判蚺c執(zhí)行對(duì)DAG進(jìn)行拓?fù)渑判虻玫揭唤M可執(zhí)行批次。同一批次內(nèi)的節(jié)點(diǎn)即那些彼此間沒有依賴關(guān)系的Tool Call可以并行執(zhí)行而不同批次之間必須順序執(zhí)行。舉例Agent返回了四個(gè)調(diào)用A獲取用戶信息B基于用戶信息查詢訂單C發(fā)送通知郵件D更新日志。依賴關(guān)系B 依賴 AC 依賴 BD 獨(dú)立。構(gòu)建的DAG可能是A - B - C D 獨(dú)立。執(zhí)行計(jì)劃第一波并行執(zhí)行 A 和 D因?yàn)樗鼈兓ゲ灰蕾?。等A完成后執(zhí)行B。等B完成后執(zhí)行C。這種方法在CI/CD流水線如Jenkins、Harness中非常常見。它兼顧了效率與正確性但實(shí)現(xiàn)復(fù)雜度較高需要額外的依賴分析和調(diào)度引擎。3.2 基于語義的自動(dòng)分組并行對(duì)于依賴關(guān)系不那么顯式、但可以通過簡(jiǎn)單規(guī)則分組的場(chǎng)景可以采用一種更輕量級(jí)的策略。核心思想是讓Agent或執(zhí)行引擎根據(jù)Tool Call的“類型”或“目標(biāo)資源”進(jìn)行分組組內(nèi)并行組間順序。分組策略示例讀寫分組將所有“只讀”查詢類工具調(diào)用分為一組并行執(zhí)行所有“寫入”類操作分為另一組且在讀組之后順序執(zhí)行。這符合“先讀后寫”的常見模式既能并行加速查詢又能避免寫操作沖突。資源分區(qū)如果工具操作不同的資源例如修改用戶個(gè)人資料和查詢產(chǎn)品庫(kù)存它們之間沒有沖突可以并行。如果操作同一資源例如同一個(gè)銀行賬戶的扣款和轉(zhuǎn)賬則必須順序化。階段分組將任務(wù)劃分為“信息收集”、“決策分析”、“行動(dòng)執(zhí)行”等階段。同一階段內(nèi)的工具調(diào)用可以并行例如并行調(diào)用多個(gè)數(shù)據(jù)源API階段之間順序執(zhí)行。3.3 將執(zhí)行策略的決定權(quán)交給AgentMeta-Tool Calling這是一個(gè)更前沿的思路為什么不讓更聰明的Agent來自己決定怎么執(zhí)行呢我們可以將“執(zhí)行策略”本身也設(shè)計(jì)成一個(gè)元工具M(jìn)eta-Tool或者讓Agent在返回Tool Call的同時(shí)也返回執(zhí)行這些調(diào)用的“計(jì)劃”。實(shí)現(xiàn)方式在Agent的提示詞Prompt中明確要求它在輸出多個(gè)Tool Call時(shí)附帶說明這些調(diào)用之間的依賴關(guān)系例如用depends_on字段或者直接建議執(zhí)行模式“parallel”,“sequential”,“grouped”。執(zhí)行引擎解析Agent的返回不僅看到要調(diào)用的工具列表還能看到一個(gè)初步的執(zhí)行計(jì)劃圖。引擎根據(jù)這個(gè)計(jì)劃圖采用對(duì)應(yīng)的策略DAG執(zhí)行或簡(jiǎn)單并行/順序來調(diào)度工具調(diào)用。這要求Agent具備更強(qiáng)的規(guī)劃和推理能力但它是實(shí)現(xiàn)智能、自適應(yīng)工作流的關(guān)鍵一步。目前一些先進(jìn)的Agent框架已經(jīng)開始探索這類能力。4. 工程實(shí)踐中的關(guān)鍵考量與踩坑點(diǎn)無論選擇哪種策略在工程落地時(shí)以下幾個(gè)關(guān)鍵點(diǎn)是決定成敗的細(xì)節(jié)。4.1 錯(cuò)誤處理與事務(wù)補(bǔ)償這是并行執(zhí)行中最棘手的問題。并行下的“全有或全無”使用Promise.all時(shí)一旦某個(gè)調(diào)用失敗整個(gè)Promise會(huì)立即reject其他正在進(jìn)行中的調(diào)用結(jié)果會(huì)丟失。你需要使用Promise.allSettled來獲取所有調(diào)用的完成狀態(tài)成功或失敗然后自行處理部分成功的場(chǎng)景。順序下的“快速失敗”順序執(zhí)行中失敗處理相對(duì)簡(jiǎn)單可以在失敗點(diǎn)中斷。但你需要考慮“部分成功”后的補(bǔ)償Compensation問題。例如成功扣款后發(fā)貨調(diào)用失敗你必須調(diào)用“退款”工具來補(bǔ)償之前的扣款操作這本質(zhì)上又引入了新的工具調(diào)用和業(yè)務(wù)邏輯。設(shè)立超時(shí)與斷路器對(duì)于每一個(gè)工具調(diào)用都必須設(shè)置合理的超時(shí)時(shí)間。在并行執(zhí)行中一個(gè)慢速或掛起的調(diào)用不應(yīng)該拖死整個(gè)批次??梢钥紤]為每個(gè)工具或目標(biāo)服務(wù)配置斷路器Circuit Breaker防止持續(xù)調(diào)用已故障的下游。4.2 上下文傳遞與結(jié)果共享在順序執(zhí)行或DAG執(zhí)行中后一個(gè)工具往往需要前一個(gè)工具的輸出。設(shè)計(jì)清晰的結(jié)果格式每個(gè)工具調(diào)用的返回結(jié)果應(yīng)該是結(jié)構(gòu)化的如JSON包含明確、命名的字段便于后續(xù)工具提取。避免返回純文本或不透明的數(shù)據(jù)。維護(hù)執(zhí)行上下文執(zhí)行引擎需要維護(hù)一個(gè)全局的“上下文”對(duì)象用來存儲(chǔ)所有已完成的工具調(diào)用結(jié)果。當(dāng)執(zhí)行新的Tool Call時(shí)引擎需要將之前相關(guān)的結(jié)果作為參數(shù)注入進(jìn)去。這要求工具接口的定義是兼容的。處理結(jié)果映射Agent在規(guī)劃時(shí)可能會(huì)預(yù)期工具A的輸出字段X被工具B作為輸入字段Y使用。執(zhí)行引擎需要負(fù)責(zé)這個(gè)映射關(guān)系這可能需要在Agent的返回中顯式聲明如“use_output_from: ‘ToolA.fieldX’ as input ‘fieldY’”。4.3 并發(fā)控制與資源保護(hù)無限制的并行是危險(xiǎn)的。限制并發(fā)數(shù)即使采用并行策略也絕不能無限制地并發(fā)。應(yīng)該配置一個(gè)全局或基于工具類型的并發(fā)池例如使用p-limit這樣的庫(kù)。比如限制最多同時(shí)有5個(gè)外部API調(diào)用或者最多2個(gè)數(shù)據(jù)庫(kù)寫操作。區(qū)分優(yōu)先級(jí)并非所有并行任務(wù)都平等。可以考慮為工具調(diào)用設(shè)置優(yōu)先級(jí)高優(yōu)先級(jí)的調(diào)用可以更快地獲得執(zhí)行資源。監(jiān)控與告警密切監(jiān)控工具調(diào)用的成功率、延遲和并發(fā)數(shù)。當(dāng)并行調(diào)用導(dǎo)致錯(cuò)誤率上升或下游服務(wù)告警時(shí)應(yīng)能動(dòng)態(tài)降級(jí)為更保守的順序執(zhí)行策略。4.4 測(cè)試策略的差異不同的執(zhí)行策略需要不同的測(cè)試重點(diǎn)。并行執(zhí)行測(cè)試競(jìng)態(tài)條件測(cè)試重點(diǎn)測(cè)試對(duì)共享資源的并發(fā)訪問。可以使用壓力測(cè)試工具模擬高并發(fā)下Agent調(diào)用多個(gè)寫工具的場(chǎng)景。錯(cuò)誤恢復(fù)測(cè)試模擬在并行批次中一個(gè)工具調(diào)用中途失敗驗(yàn)證其他調(diào)用的行為是否符合預(yù)期是繼續(xù)完成還是被取消以及最終狀態(tài)是否一致。下游承載能力測(cè)試驗(yàn)證并行爆發(fā)是否會(huì)導(dǎo)致下游服務(wù)過載。順序執(zhí)行測(cè)試流程完整性測(cè)試確保在各種輸入條件下整個(gè)調(diào)用鏈能按預(yù)期走通。中間狀態(tài)測(cè)試驗(yàn)證在調(diào)用鏈的每一個(gè)環(huán)節(jié)之后系統(tǒng)和數(shù)據(jù)的狀態(tài)是否正確。補(bǔ)償邏輯測(cè)試針對(duì)可能失敗的環(huán)節(jié)專門測(cè)試其補(bǔ)償工具如退款、回滾是否能被正確觸發(fā)和執(zhí)行。5. 實(shí)戰(zhàn)框架示例與模式選擇指南理論說了這么多我們來看看在具體框架或代碼中如何體現(xiàn)。5.1 偽代碼示例從簡(jiǎn)單到復(fù)雜1. 簡(jiǎn)單的順序執(zhí)行Node.js/Async:async function executeSequentially(toolCalls, context) { const results []; for (const call of toolCalls) { try { const result await invokeTool(call, context); results.push(result); // 將本次結(jié)果更新到上下文供后續(xù)調(diào)用使用 context updateContext(context, call.name, result); } catch (error) { // 順序執(zhí)行中一個(gè)失敗即可終止整個(gè)流程或進(jìn)入補(bǔ)償邏輯 console.error(Tool ${call.name} failed:, error); await runCompensationLogic(results); // 執(zhí)行補(bǔ)償 throw new Error(Pipeline failed at ${call.name}); } } return results; }2. 簡(jiǎn)單的并行執(zhí)行Node.js:async function executeInParallel(toolCalls, context) { // 假設(shè)所有調(diào)用獨(dú)立使用相同的上下文 const promises toolCalls.map(call invokeTool(call, context)); // 使用 allSettled 確保獲取所有結(jié)果即使有失敗 const settledResults await Promise.allSettled(promises); const results []; const errors []; settledResults.forEach((outcome, index) { if (outcome.status fulfilled) { results.push({ tool: toolCalls[index].name, result: outcome.value }); } else { errors.push({ tool: toolCalls[index].name, error: outcome.reason }); } }); if (errors.length 0) { console.error(Some tools failed:, errors); // 處理部分失敗的情況可能需要清理或告警 } return { results, errors }; }3. 帶并發(fā)限制的并行執(zhí)行:const pLimit require(p-limit); const limit pLimit(3); // 全局并發(fā)數(shù)限制為3 async function executeWithConcurrencyLimit(toolCalls, context) { const promises toolCalls.map(call limit(() invokeTool(call, context)) // 將調(diào)用包裹在限制器中 ); return await Promise.allSettled(promises); // ... 后續(xù)結(jié)果處理同上 }5.2 模式選擇決策樹面對(duì)一個(gè)具體的Agent功能你可以遵循以下決策流程來選擇執(zhí)行策略檢查依賴關(guān)系A(chǔ)gent返回的多個(gè)Tool Call之間是否存在明確的數(shù)據(jù)流依賴B需要A的輸出或狀態(tài)依賴B必須在A成功改變某個(gè)狀態(tài)后才能執(zhí)行是- 進(jìn)入步驟2。否- 進(jìn)入步驟3。處理存在依賴的情況依賴關(guān)系簡(jiǎn)單線性A-B-C采用順序執(zhí)行。這是最安全、最簡(jiǎn)單的選擇。依賴關(guān)系復(fù)雜網(wǎng)狀A(yù)-B, A-C, B-D, C-D考慮采用DAG執(zhí)行引擎。評(píng)估實(shí)現(xiàn)的復(fù)雜度與收益是否匹配。如果調(diào)用數(shù)量不多5有時(shí)用順序執(zhí)行手動(dòng)管理依賴也是可接受的。處理獨(dú)立的情況調(diào)用數(shù)量少3且耗時(shí)短并行執(zhí)行收益不大順序執(zhí)行代碼更簡(jiǎn)潔。調(diào)用數(shù)量多或存在慢速I/O調(diào)用優(yōu)先考慮并行執(zhí)行。并行執(zhí)行前必須評(píng)估下游服務(wù)是否有限流 - 如有需實(shí)施帶并發(fā)限制的并行。是否涉及對(duì)同一資源的寫操作 - 如有必須順序執(zhí)行或引入分布式鎖等同步機(jī)制。錯(cuò)誤處理是否復(fù)雜 - 評(píng)估團(tuán)隊(duì)對(duì)部分失敗場(chǎng)景的處理能力?;旌锨闆r大多數(shù)現(xiàn)實(shí)場(chǎng)景是混合的。采用分組策略將獨(dú)立的調(diào)用并行化將有依賴的調(diào)用序列化?;蛘呷绻軜?gòu)允許追求基于DAG的動(dòng)態(tài)調(diào)度。5.3 一個(gè)綜合案例智能旅行規(guī)劃Agent假設(shè)一個(gè)Agent能理解“為我規(guī)劃一個(gè)周末杭州之旅預(yù)訂機(jī)票和酒店并查詢周末的天氣”。Agent規(guī)劃可能生成三個(gè)Tool Callsearch_flights查詢航班search_hotels查詢酒店get_weather查詢天氣。依賴分析查詢航班、酒店、天氣三者之間沒有數(shù)據(jù)依賴它們可以并行執(zhí)行以快速獲取所有信息。執(zhí)行策略采用并行執(zhí)行。使用Promise.allSettled同時(shí)發(fā)起三個(gè)查詢。結(jié)果聚合Agent收到所有并行查詢的結(jié)果后進(jìn)行綜合分析和推薦。后續(xù)操作當(dāng)用戶確認(rèn)預(yù)訂后Agent可能生成新的Tool Callbook_flight和book_hotel。新的依賴分析預(yù)訂航班和酒店雖然業(yè)務(wù)上獨(dú)立但可能共享用戶支付信息且涉及真實(shí)的資源扣減。為了防止支付重復(fù)或資源沖突更安全的做法是順序執(zhí)行這兩個(gè)預(yù)訂操作甚至將它們包裝在一個(gè)分布式事務(wù)中。這個(gè)案例展示了在一個(gè)完整的Agent交互會(huì)話中執(zhí)行策略可能是動(dòng)態(tài)變化的取決于當(dāng)前階段工具調(diào)用的具體性質(zhì)?;氐轿恼麻_頭的那次故障我們最終的解決方案是引入了輕量級(jí)的依賴分析。我們?cè)诿總€(gè)工具的定義中加了一個(gè)category標(biāo)簽如read,write,side_effect。執(zhí)行引擎在收到多個(gè)Tool Call后會(huì)先快速掃描如果全是read則并行執(zhí)行如果出現(xiàn)write則按順序執(zhí)行并將write之前的read并行化。同時(shí)為所有并行執(zhí)行加上了嚴(yán)格的并發(fā)數(shù)限制。這套簡(jiǎn)單的規(guī)則成功避免了類似的邏輯錯(cuò)誤也在大多數(shù)情況下保住了性能收益。所以Agent一次返回多個(gè)Tool Call應(yīng)該并行還是順序執(zhí)行答案是看情況。沒有銀彈。作為開發(fā)者我們的責(zé)任是深入理解業(yè)務(wù)邏輯、工具特性和系統(tǒng)約束為Agent的“思考成果”選擇最合適的“執(zhí)行路徑”。從簡(jiǎn)單的if-else判斷到復(fù)雜的DAG調(diào)度這其中的選擇正是AI應(yīng)用工程化中那種既需要技術(shù)深度又需要業(yè)務(wù)洞察力的迷人之處。