【文章內容使用 Gemini 2.5 Flash 自動翻譯產生】
為 ADK 建立 Flutter 前端
當代理程式使用我從未用過的 SDK 和語言構建時,我該如何為它建立 Flutter 前端?
這是我在處理使用 Agent Development Kit (ADK) 編寫的基於 Python 的代理程式時面臨的挑戰。由於 Python 經驗有限,且以前從未接觸過 ADK 框架,因此構建一個與後端伺服器整合的客戶端帶來了巨大的學習曲線。此外,即使我能讓程式碼代理程式產生一些可行的東西,如果我不理解程式碼,完成專案也是一種失敗的形式。
然而,在幾次失敗的嘗試之後,我找到了答案。我與我的 AI 編碼夥伴 Antigravity 採用了結構化、迭代的工作流程,建立了一個可重複使用的開發人員技能,將我在每次循環中學到的知識編碼化。我從零開始,產生了關於程式碼的筆記,建立了多個連接到 deep_search 代理程式(來自官方 ADK 範例儲存庫的多代理研究協調器)的應用程式,並逐步建立了技能和我的理解。有時,我同時使用了多個代理程式,「作者」代理程式與我一起建立技能,「編碼員」代理程式使用該指南來建立前端。
我最終得到的是一個名為 flutter_frontend_for_adk 的代理程式技能。它包含五個參考文件,引導 Antigravity 經歷一系列階段,每個階段都以可交付成果結束。第一階段產生了以下筆記文件,以便我可以結構化「編碼員」代理程式在分析代理程式並準備產生應用程式時對任務的思考:
- AGENT_INTERFACE_NOTES.md — 在分析代理程式原始碼時所做的筆記。它的目的是什麼,它是如何構建的?這個代理程式公開了哪些介面和 API,它們是如何運作的?
- FRONTEND_USAGE_NOTES.md — 第一個規範。前端應該做什麼,使用者應該如何與它互動?
- FRONTEND_ARCHITECTURE_NOTES.md — 架構計畫。應該建立哪些服務、類別、狀態和模型?
- FRONTEND_DESIGN_NOTES.md — 前端的設計文件。它會是什麼樣子?顏色、字體和其他細節是什麼?
之後,Antigravity 可以產生應用程式的程式碼,運行並測試它。雖然技能(和我)仍在開發中,但我現在已經很好地掌握了 ADK,並且有了一種有用的方法來為現有代理程式建立前端。
這就是它的發生方式。
從他人的工作開始
我不是這裡唯一一個編寫技能的人,所以第一步是從 Google Cloud 和 Flutter 團隊安裝一些技能:
1 | npx skills add google/agents-cli --skill google-agents-cli-adk-code |
這讓我對 ADK 及其 CLI 工具和 Flutter 有了一些基本的了解。由於 Antigravity 的 Dart 擴充功能,我也安裝了 Dart MCP 伺服器。
建立循環
我沒有一開始就要求代理程式產生一個應用程式,而是與它建立了一種「學習循環」。首先,我要求編碼代理程式執行我技能中的工作流程,然後我與作者代理程式合作手動評估編碼程式的輸出,找出技能說明中的漏洞,並更新指南以改進未來的運行。每次迭代後,我會刪除產生的筆記和應用程式,重新開始,然後發現我需要學習的下一件事。
該循環由與 Antigravity 對話驅動的五個不同步驟組成:
1) 執行目前的技能:在一次新的對話中,編碼代理程式執行由目前版本的技能檔案定義的工作流程。
我的提示:這個程式碼庫包含一個使用 ADK 構建的代理程式,但沒有前端或客戶端。我希望您閱讀 flutter-frontend-for-adk/SKILL.md 中的說明並遵循工作流程。不要檢查 git 歷史記錄,不要參考我們進行過的任何其他對話的上下文,也不要更改 git 分支。
2) 評估輸出和規範:在第二次對話中,作者代理程式和我檢查產生的可交付成果,例如架構筆記、設計規範和產生的程式碼結構。我更擅長發現結構問題,而 Antigravity 則幫助我捕捉所有小細節。
我的提示:在我審查筆記和程式碼時,請查看生成的工件並告訴我您認為它們與說明和我們的目標的匹配程度。
3) 識別差距和故障模式:我們識別出程式碼代理程式缺乏特定指導、做出不正確假設或遇到整合問題的領域。
我的提示:我在上次運行中發現了兩個問題:首先,根 gitignore 由於全域的「lib/」忽略規則而忽略了新的 frontend/lib/ 資料夾。其次,程式碼代理程式連續執行所有六個階段而不停止。我們需要一種方法來在每個階段之後暫停並驗證可交付成果。
4) 更新核心技能和參考資料:我們更新 SKILL.md 中的說明或 references/ 目錄中的子指南以解決這些差距。
我的提示:讓我們更新 SKILL.md 中的 Phase 6,明確處理 gitignore 問題,方法是如果「lib/」全域忽略,則添加「!frontend/lib」。此外,在 Phase 1 到 4 的末尾添加一個強制性的「審查」步驟,指示代理程式暫停並等待我的批准,然後再繼續。
5) 清除本地文件並重新執行:我刪除臨時規範文件,重置 git 工作樹,然後回到循環的頂部。
儘管與一對代理程式合作確實加快了速度,但它並沒有使過程瞬間完成。我一次只能吸收這麼多資訊!但在每次迭代中,我都會閱讀筆記和原始碼檔案,查看與 Antigravity 的對話,並且(一旦我產生了真實的程式碼)運行應用程式以查看其效能。
一開始,我主要在閱讀和學習。但到最後,我對正在發生的事情了解得足夠多,足以專注於一直失敗的事情,開始自己研究,並調整程式碼以修復問題。修改完筆記和程式碼庫後,我會詢問 Antigravity 如何更新技能,以使未來的程式碼產生看起來更像我組裝的內容。因此,該技能不僅僅是程式碼代理程式的指令,更是我學習的記錄。
循環迴圈
總共經過 13 次迭代,我才得到一些我不羞於分享的東西。以下是前 6 次,主要用於發現和記錄筆記:
- 啟動和工作區映射 — 我意識到一個單一的、整體式的 SKILL.md 文件對於代理程式來說太難導航了。我將技能重構為模組化,建立了一個專用的
references/資料夾並編寫了第一個專業指南:references/agent_discovery.md。這讓 Antigravity 通過分析代理程式的原始碼並建立AGENT_INTERFACE_NOTES.md來記錄它學到的東西。 - 定義行為和使用者體驗 — 接下來是前端的使用規範:它會做什麼?使用者將如何與它互動?我在技能中添加了一個新階段,指示它閱讀
references/frontend_usage.md並採訪我以了解平台偏好和功能要求。這讓我在觸摸程式碼之前就得到了FRONTEND_USAGE_NOTES.md,它定義了應用程式的目的和功能集。 - 設定結構藍圖 — 架構。我們將
references/frontend_architecture.md添加到技能中,該技能側重於前端所需的架構細節,我讓代理程式產生FRONTEND_ARCHITECTURE_NOTES.md。 - 設計視覺美學 — 我們建立
references/frontend_design.md來指導代理程式如何定義視覺美學,並將 scaffolding 指令添加到 SKILL.md 中。此指南指示代理程式採訪我以了解主題、斷點和動畫偏好,Antigravity 開始產生FRONTEND_DESIGN_NOTES.md。 - 產生並運行應用程式 — 至此,我能夠告訴 Antigravity 開始根據我們收集的所有規範產生實際的 Flutter 程式碼。應用程式以驚人的方式失敗了,我意識到需要某種通用的「最佳實踐」文件來解決可能重新出現的問題。我們將
references/frontend_best_practices.md添加到技能檔案中以指導實際的編碼,並開始一次修復一個問題。
從那時起,我繼續與 Antigravity 進行迭代,一次解決一個問題,更新程式碼,更新技能以匹配,然後清除產生的前端以再次嘗試。在此過程中,循環變得更緊密,更改更小。我做了七次額外迭代:
- 應用程式無法進行網路呼叫! — 修正了 macOS 和 iOS 的權限和資訊。
- 所有這些 Markdown 都沒有被格式化! — 利用
flutter_markdown正確顯示來自代理程式的文字,其中通常包含 Markdown。 - 為什麼程式碼看起來不對勁? — 添加了 lint、格式化規則和其他產生後檢查。
- 密封類別! — 不同的訊息類型應共用一個基類型,以便應用程式可以使用窮舉 switch 語句。
- 為什麼聊天不會捲動? — 添加了 ScrollController,以便在新訊息到達時自動推進訊息列表。
- 為什麼應用程式在網路上運行時崩潰了? — 移除了
dart:io,轉而依賴package:http進行網路連線。 - 清單中的部分事件! — ADK 發送事件流,有時是分段的。前端需要將它們連貫地組裝和呈現,而不是向使用者顯示所有部分(帶有損壞的 Markdown 格式)的列表。
- 為什麼工具視窗是空白的? — 在產生時,應用程式沒有正確處理工具命名約定,並且事件處理沒有正確識別何時調用工具。
一個「出錯」的例子
為了讓您了解每次迭代中完成的工作,讓我們來看看其中一個變更:前端如何處理部分事件。
ADK 伺服器會串流事件,這些事件表示一小段內容或部分工具執行階段。但是,如果客戶端應用程式將每個傳入的網路事件都渲染為聊天清單中的獨立訊息氣泡,那麼介面就會變得碎片化。代理程式的一個回應將顯示為數十個孤立的、損壞的文字塊。
舊方法(一個簡單的清單):
1 | // 在清單視圖中渲染每個原始事件區塊 |
此程式碼導致的 UI 如下所示:
一旦你知道該怎麼做,這個問題的解決方法其實並不難。當然,我不知道,所以我開始向 Antigravity 提出問題,例如「ADK 如何使用 SSE 串流事件?」和「事件的傳輸資料結構是什麼樣的,我怎麼知道它是否是部分事件?」如果「氛圍學習」是真實存在的,我正在這麼做。
事實證明,您只需要檢查一個旗標,所以我調整了前端 AgentProvider 類別中的程式碼,要求 Antigravity 審查它以防我忘記了任何顯而易見的東西,然後運行應用程式進行驗證。我再次向 Antigravity 發出請求,以更新最佳實踐,以便每個新的前端都會使用這種方法。
新方法 (AgentProvider 中的聚合):
1 | await for (final event in stream) { |
親自試試看
我非常喜歡「做中學」,而嘗試完全超出我舒適區的東西(例如一種新語言和一個新 SDK)相當令人生畏。然而,擁有這個循環為我提供了一個可以參考的結構,這非常有幫助,現在我擁有了一個 漂亮的新代理程式技能。
如果您還沒有,請自己下載 Antigravity 並試用一下 — 我只花了幾個小時,而且我確實學到了一些新技巧。
要開始:
- 下載 Antigravity 以將代理程式編碼助手整合到您的開發環境中。
- 訪問 AGY 入門 文件,了解如何定義自己的自訂開發人員技能和參考指南。
- 為您想要探索的框架草擬一個簡單的技能,並不斷循環直到您得到喜歡的東西!
使用 Antigravity 更快學習 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。