在之前的 《Flutter 官方 LLM 動態 UI 庫 flutter_genui 發布,讓 App UI 自己生成 UI》 我們就聊過,Flutter 已經支援讓 Agent 在 App 執行中動態生成元件,而現在 GenUI 和對應的 A2UI 這次也都更新了全新協議,所以這波我們也整體回顧一下這整套全新的 AI 動態 UI 方案。

目前在 Flutter 上整個 AI 生成 UI 可以分為兩層:
也就是說,A2UI 模型輸出的也不是 Dart、JS、HTML 這種具體程式碼,實際上輸出的是一種結構化的 UI 描述,因為協議是通用的,然後這裡再由 GenUI 對接後渲染成 Flutter 的元件。
所以我們還是需要聊一聊這個協議,因為它不只是 Flutter 專用。
正常流程上,Flutter 需要透過 A2UI 取得描述,Flutter 端會透過 GenUI runtime 解析這些描述,再結合 Catalog、DataModel、SurfaceController 等機制,把它變成一套可以「互動、更新、回流」給 Agent 的 Flutter Widget:

所以其實這裡 A2UI 就是 Agent-to-UI 的協議層,它可以用在 Flutter,也可以用在 CMP、RN、Vue 等各種場景。
我一直覺得它最大的用處就是做 Agent 應用,比如在 AI 對話或者客服場景,A2UI 可以直接給出結果而不是文字,當使用者說:
那你說這和讓 AI 生成程式碼有什麼區別?其實還真沒太大本質區別,只是如果你輸出的是程式碼,那麼可用性就低了,而且還需要額外的編譯渲染。
而 A2UI 是模型生成受 schema 約束的 UI 指令,用戶端再用「已經註冊的元件」完成渲染,整體效能和速度會好不少,當然靈活性也會差一些:

那這次 A2UI v0.9 有什麼特別?主要是這個版本做了很多核心調整:
在這次的 A2UI v0.9 把原來的「Standard components」改為「Basic components」,也就是 A2UI 現在不會內建什麼標準設計,因為「前端、行動端、企業應用」一般都有自己的設計風格,比如 Flutter App 裡會有自己的 ProductCard、OrderStatusView、MetricChart、PermissionNotice、DeviceControlPanel 等設計場景。
所以 A2UI 這次調整成「Basic components」,核心是想提供一套參考元件、基礎元件和範例元件,所以這次協議變更也明確了一個標準:
A2UI v0.9 版本還引入 shared web-core,同時更新了 React、Flutter、Angular 等 renderer,所以 A2UI 在 0.9 版本開始生態不再是 Flutter-only 或者 React-only 方案,而是同一份 A2UI 輸出,可以被不同 renderer 解析並渲染:

這其實很重要,因為這代表 A2UI 邏輯可以在不同語言和框架下多端適配,這對現階段的 AI Coding 場景來說很實用。
當然,最重要的是 A2UI v0.9 提供了 Agent SDK,而 Agent 支援生成「合法、可解析且可驗證」的 A2UI 輸出,Agent 的整體核心圍繞 schema、prompt、解析、修復、驗證 來完成工程化閉環:

這裡的關鍵點在於,A2UI 解決了「模型輸出不穩定」問題,輸出的結果在工程裡可以透過 Agent SDK 自己修復問題,比如生成 system prompt、描述元件 catalog、解析模型輸出、修復部分格式等場景,最終輸出轉換成客戶端可以消費的 A2UI message。
其他部分 A2UI v0.9 還新增和強化了幾類能力:
當然,最重要的是這次修改後 Transport 更開放了,現在 transport interface 可以執行在 MCP、WebSocket、REST、AG-UI、A2A 等不同傳輸方式上,比如:
所以也可以看出來,A2UI 的定位更像是 Agentic UI 的中介協議層,主要用在 Agent 和 UI runtime 之間的語意表達。
那到這裡就很清楚了,Flutter GenUI 就是 A2UI 在 Flutter 的執行時 SDK,它主要負責把 Agent 輸出的結構化 UI 指令解析成 Flutter 可渲染的 UI,當然,除此之外它還支援了 使用者互動、資料綁定、Surface 生命週期、下一輪 Agent 對話 等場景,GenUI 算是 A2UI 上的一套完整實作架構:

如果從使用鏈路上看其實鏈條還是很長的,不過這裡主要需要關注的是三個點:

所以可以看出來,GenUI 不是一套簡單的 UI 生成,甚至你可以認為它是一套 App 端的 SSR 都行,而這次 GenUI 0.9 也做了大更新,開始從耦合演變成分層結構。
因為舊的 GenUI 思路更像是一個集中的 GenUiConversation 加 ContentGenerator 處理,AI 輸出、A2UI 訊息、文字流、錯誤流的處理邏輯會被放在較強耦合的臭象裡,而新方案根據職責對實作進行了拆分:

事實上這個調整還是很重要的,因為它讓 Flutter GenUI 更方便接入到不同模型、Agent 後端和傳輸協議裡,比如現在你可以接:
因為現在 GenUI 沒有把「模型怎麼呼叫」寫死在 SDK,而是把模型接入、協議解析、狀態管理和 Flutter 渲染分開。
而 0.9 的另外一個變化就是 Prompt First,也就是現在不只是單純依賴 structured output,因為並不是所有模型、provider、和執行環境都能穩定支援嚴格 structured output。
所以為了讓更多模型可以支援 GenUI,這次 GenUI 選擇透過 PromptBuilder 把 Catalog、A2UI schema、生成規則注入 system prompt,讓模型按 A2UI 格式輸出,同時 GenUI runtime 也圍繞 Surface 生命週期定義了幾類場景:

實際上 Prompt First 的優勢是相容性更好,能適配更多 LLM provider,當然代價是 system prompt 會變得更長,token 成本會升高。
那實際上整個 GenUI 是怎麼工作的?首先第一個要理解的就是 Catalog。
Catalog 是 Flutter GenUI 裡非常重要的定義,它定義了 AI 可以使用哪些元件,以及每個元件有哪些屬性、事件和渲染方式,簡單來說類似:
bash 体验AI代码助手 代码解读复制代码CatalogItem
元件名稱
元件屬性 schema
Flutter builder function
可選描述 / 範例
因為模型生成的不是 Dart 程式碼,而是類似這樣的 UI 意圖:
css 体验AI代码助手 代码解读复制代码{
"type": "Button",
"properties": {
"label": "確認",
"action": "submit"
}
}
而 Flutter 客戶端看到這個資料後,會去 Catalog 裡找 Button 對應的 builder,再渲染成真實 Flutter Widget。
所以 Catalog 最重要的作用就是:
所以它也不是傳統意義上的熱更新,GenUI 的 A2UI message 只是讓 UI 做
createSurface、updateComponents、updateDataModel、deleteSurface這類動作,本質是執行時狀態和元件樹描述的變化。
你需要引入 GenUI SDK,提前註冊 Catalog,之後 LLM 生成結構化 UI 描述,這些描述進入 SurfaceController 更新內部狀態,然後透過 Flutter rebuild 去渲染,也就是:
執行時讀取 JSON 資料,然後用你 App 裡已經 AOT 編譯好的 Dart 程式碼去建立 Widget 物件,Catalog 本質就是一張「字串 - 已編譯 builder」的註冊表。
簡單來說就是,GenUI 的 Catalog 可以簡化理解成這樣:
javascript 体验AI代码助手 代码解读复制代码final catalog = {
'text': (props) => Text(props['value']),
'button': (props) => ElevatedButton(
onPressed: () {},
child: Text(props['label']),
),
'slider': (props) => Slider(
value: props['value'],
min: props['min'],
max: props['max'],
onChanged: (_) {},
),
'chart': (props) => MyChart(data: props['data']),
};
然後伺服器回傳:
json 体验AI代码助手 代码解读复制代码{
"type": "slider",
"props": {
"value": 50,
"min": 0,
"max": 100
}
}
最後客戶端做:
ini 体验AI代码助手 代码解读复制代码final builder = catalog['slider'];
return builder(props);
大概就是這樣的一個流程,所以也不違反上架要求。
如果說前面的 Catalog 是 UI 核心,那麼 DataModel 層的實作就是互動核心,DataModel 的作用就是提供生成 UI 的互動能力,使用者可以透過按鍵、進度條和表單,把狀態變成下一輪 Agent 推理的一部分:

這也是 GenUI 和傳統 chatbot 場景的差別,傳統 chatbot 只能等使用者輸入,而 GenUI 可以讓使用者透過圖形介面修改狀態,然後把狀態回流給 Agent,所以可以在操作過程裡即時更新和建立新的 UI。
最後 genui_core 就是整個 GenUI 的基礎實作,而這次 0.9 也明確了 genui_core 的長期方向:把協議處理、狀態樹維護、JSON Pointer、表示式求值等能力放到更純粹的 genui_core 中,而 Flutter package 只負責 Flutter 渲染,大概類似:

目的其實也很簡單,就是減少 Flutter 渲染層和 A2UI 協議層的耦合,讓不同端的實作更一致,因為 Web 端已經有 shared web-core,Flutter 如果也能把 core 層抽出來,協議行為就更容易統一。
所以客戶端也許真的不需要開發一個完整的頁面功能,開發者在 App 裡可能更多是在維護元件庫,然後剩下的就是 AI 負責渲染和組合維護,例如:
這些都可以在 A2UI 場景下得到能力提升,如果你要說問題是什麼??問題肯定是 Token,有人說生成速度太慢,那是因為你沒上 AI 滿倍率速度,只要捨得上,你看效果怎麼樣?
所以核心其實還是 Token 消耗會很高,使用者的操作都會變成企業的 Token 支出。
當然,GenUI 也明確,開發者可以在自己的 LLM/Agent 接入層快取 A2UI 輸出或業務狀態,而對於已經得到的 JSON,你也可以自己管理快取,什麼時候需要生成,什麼時候沿用既有的,具體就看業務設計了。
那麼,你覺得 A2UI 對你來說有用嗎?