【文章翻譯】Architects, testers, and coders: Building multi-agent development teams
【文章內容使用 Gemini 2.5 Flash 自動翻譯產生】
原文:https://flutter.dev/blog/building-multi-agent-dev-teams
架構師、測試人員和程式設計師:建立多代理開發團隊
如何讓在 Antigravity 中運行的多代理開發團隊使用測試驅動開發將 Python 函式庫移植到慣用的 Dart 套件。

當我第一次開始嘗試 AI 編碼助手時,我只使用一個代理來處理所有事情:架構程式碼、編寫單元測試和偵錯堆疊追蹤。雖然這種方法對於小任務運作良好,但對於複雜的軟體工程問題,它很快就會退化。隨著我的對話歷史記錄增長,代理的上下文視窗會被日誌和搜尋結果飽和,導致幻覺、遺漏連結、馬虎的程式碼和錯誤。
幾週前,我偶然發現了一篇關於多代理、TDD 編碼工作流程的部落格文章。我以前聽說過這種方法,但從未嘗試過。由於 Antigravity 的 Agent Hub 包含了多代理設定的工具,我決定對這種技術進行測試。
為了在真正的挑戰中測試它,我著手將流行的 python-statemachine 函式庫移植到靜態類型、無反射的 Dart 套件。儘管 pub.dev 已經有穩定的狀態機選項,但 python-statemachine 是一個絕佳的基準。它嚴重依賴於動態 Python 功能(例如元類和執行時回呼),這些功能必須針對 Dart 強大的靜態類型和 Flutter 對不使用 dart:mirrors 的要求進行徹底重新架構。

這比看起來要複雜,我發誓!
我學到的第一件事是,有效代理團隊的基礎是一組明確定義的角色,這些角色對代理可以做的事情有特定的限制。為了實施這些,我建立了一個總體工作流程技能(tdd-dart-workflow)來建立共用的 TDD 規則和權限,以及四個定義每個代理的角色特定技能:
- **架構師 (
tdd-dart-architect)**:分析原始碼,生成前端的architecture_blueprint.md(階段 0),並在specs/下編寫有針對性的模組規範 (階段 1)。架構師不能寫入lib/、test/或example/。 - **測試人員 (
tdd-dart-tester)**:根據架構師的規範 (階段 2a) 在test/下編寫全面的失敗單元測試。測試人員不能查看或寫入lib/或specs/。 - **程式設計師 (
tdd-dart-coder)**:在lib/src/下建立編譯骨架並實作函式庫程式碼以使失敗的測試通過 (階段 2b 和 3)。程式設計師不能編輯test/或specs/。 - **協調者 (
tdd-dart-coordinator)**:協調者父代理。協調者管理 Git 分支提交,執行dart analyze && dart test驗證,並將任務委派給子代理。
透過強制執行嚴格的角色分離,沒有任何單一代理可以同時修改測試斷言和底層程式碼。協調者充當守門員,僅在子代理完成任務時收到簡短的完成報告。這建立了一個「認知防火牆」。除了在工作面試中是一個有趣的詞語之外,這意味著每個子代理的試錯標記歷史記錄會在任務完成後被丟棄。因此,父協調者的上下文視窗保持乾淨、專注,並且沒有標記飽和。
需要澄清的是,我在此處省略了一些潛在問題,例如「如果子代理陷入循環會發生什麼?」和「是否應該設定一個時間截止,在此之後子代理會被終止並重新創建或通知人類?」不過,這是我首次涉足多代理團隊,這些問題我將留到後續的部落格文章中再討論!
為了防止競爭條件和未經證實的程式碼提交,檔案系統寫入權限在工具層級的 tdd-dart-workflow 中受到限制,具體取決於代理的指定角色:
| 代理角色 | 允許讀取路徑 | 允許寫入路徑 | 禁止操作 |
|---|---|---|---|
| 協調者 | 任何地方 | 任何地方 | 直接程式碼修改 (委派給程式設計師/測試人員) |
| 架構師 | 任何地方 | specs/, skills/ |
不能寫入 lib/、test/ 或 example/ |
| 測試人員 | 任何地方 | test/, example/ |
不能寫入 lib/ 或 specs/ |
| 程式設計師 | 任何地方 | lib/, example/ |
不能寫入 test/ 或 specs/ |
在我的版本中,這些限制包含在代理的說明中,因此它們技術上可能會被違反。然而,隨著多代理系統的演進,我預計我們將開始看到以更安全的方式實施限制的方法。
一個挑戰範例
在像 Dart 這樣的編譯語言中操作多代理團隊帶來了一個有趣的挑戰:靜態編譯和為尚不存在的程式碼編寫測試之間的緊張關係。在像 Python 這樣的動態語言中,TDD 以一個拋出運行時錯誤的失敗測試(紅)開始。然而,在靜態語言中,為尚不存在的方法編寫單元測試會導致編譯時失敗。編譯器會中止,阻止測試執行器執行並證明測試本身是有效的。
我的代理團隊在 紅色階段 循環中解決了這個問題。首先,測試人員根據架構師的規範編寫測試。接下來,程式設計師在 lib/src/ 下建立一個編譯骨架,其中包含返回虛擬值或拋出 UnimplementedError 的類和方法存根。一旦骨架滿足編譯器,協調者會運行 dart analyze && dart test 以驗證測試因正確的原因(未實現的邏輯而不是語法或匯入錯誤)而失敗。註釋邊界確保臨時骨架存根與永久測試工具隔離,允許協調者在程式設計師完成綠色階段後自動清除它們:
1 | // TEST UTILITIES - KEEP PERMANENTLY |
出了什麼問題:摩擦點和飛行中的技能更新
使用代理確實加快了移植函式庫的過程,但它也帶來了自己的挑戰。然而,工作流程中斷的時刻提供了最有價值的工程教訓。在移植過程中,我不得不暫停並更新我的技能檔案(SKILL.md)以解決三個問題:
- 意外刪除測試工具:一旦程式設計師在
lib/src/中實作了真實的函式庫類別,協調器就必須清理測試檔案中留下的臨時編譯存根。它總是將存根與真實的東西混淆,因此需要清晰的註釋標頭才能使真實的實作清晰。 - 展開運算子 (
...) 類型不匹配:Python 和 Dart 處理類型的方式不同,Python 中預設可迭代的東西在 Dart 中不一定如此。我不得不針對需要實作Iterable的東西新增一些明確的說明。 - 「帶有外來口音」的動態類型:再次地,不同的類型系統造成了問題。原始的 Python 函式庫在幾個地方使用了
hasattr檢查。我不得不改進tdd-dart-architect/SKILL.md以強制架構師使用慣用的 Dart 和明確的回呼委派,而不是動態屬性查找。
這些技能改進直接塑造了最終的設計。產生的 Dart 套件 (state_machine) 保留了 python-statemachine 的完整功能集,程式設計師代理實作了流暢的建構器以支援 Dart 的原生展開運算子 (...)。以下是原始 Python 類別定義與代理團隊產生的最終 Dart 狀態機之間的比較:
舊方式:
1 | # python-statemachine syntax (declarative via metaclasses) |
新方式:
1 | // state_machine Dart syntax (declarative constructor DSL) |
所有這些的重點更多是為我自己產生一套可重複使用的技能,而不是建立和發布一個新的 Dart 套件。我目前無法監測報告的問題並長期維護這個套件。我無法保證所有建立的程式碼都沒問題(儘管在我測試時它確實有效),而且生態系統中已經有幾個維護良好的套件。然而,希望這能讓您了解在 Antigravity 中運行的多代理系統能為 Dart 和 Flutter 開發人員做些什麼。
如果您想在自己的專案中探索多代理工作流程,請嘗試一下!
- 下載 Antigravity。
- 造訪 AGY 入門文件,了解如何定義自己的代理和自訂開發人員技能。
- 查看我在這個專案中建立的實際技能檔案,根據您的需求修改它們,並讓我們知道進展如何!