另一個重點是 .NET MAUI 團隊正在 MAUI Labs 實驗的 Essentials AI。它延續 Xamarin Essentials 將跨平台裝置能力整合為統一 API 的思路,嘗試為 iOS、Android 和 Windows 的裝置端 AI 模型提供一致的使用方式。開發者可依平台註冊對應的 IChatClient 實作,再讓應用程式其他部分透過共同介面呼叫。Gerald 說明,Essentials AI 目前以 MAUI Labs 預覽套件形式提供,方便團隊快速實驗並收集回饋;它受到團隊積極維護,但尚不等同納入正式產品支援承諾。
使用裝置端 AI 前,App 必須檢查裝置是否具備相應能力、模型是否已準備就緒,以及是否需要下載模型。不同平台與裝置支援的功能也不完全相同;以分享當時的情況來說,工具呼叫能力尤其需要逐一確認。這意味著開發者不能只因某台裝置「有 AI 模型」,就假設所有 AI 功能都能執行,仍須做好能力檢測、替代流程和實機測試。
要讓 AI「採取行動」,Gerald 展示了 AI attributes 的做法。開發者可在既有 C# 方法上標註匯出 AI 函式的屬性,替函式及參數寫出清楚描述,使模型能根據使用者語句判斷何時呼叫工具,以及該傳入哪些參數。例如,開啟講者頁面、搜尋議程或調整個人行程,都可以轉為模型可呼叫的工具。相關原始碼產生器會建立呼叫程式碼,避免在執行時依賴反射。工具最終仍透過 App 原本的 ViewModel、模型和服務執行,不必另建一套與既有介面脫節的操作邏輯。
讓 App 能行動,也必須讓使用者保持控制權。示範中,移除已儲存議程屬於可能造成損失的操作,因此 AI 會先列出將移除的項目並要求確認;使用者可以選擇移除或保留。Gerald 建議開發者驗證每項請求與工具參數、留意提示注入風險、清楚說明 AI 能做什麼,並只公開必要且願意讓模型操作的工具。AI 可以協助判斷意圖,但不應繞過安全檢查或替使用者擅自決定重大操作。
分享最後也提出更多延伸方向。語意搜尋可將文字轉成向量,讓使用者不必輸入完全一致的關鍵字,就能找到意思相近的議程。AI 也可能協助新使用者找到設定、推薦入門內容、說明觀看某場演講前應具備的背景知識,或將議程摘要翻譯成偏好的語言。MAUI Labs 中的 AI Wayfinding 實驗則進一步思考:如果使用者能直接表達目的,App 是否可以替他找到操作路徑,甚至呈現更符合個人偏好的介面?
ASP.NET Core 讓團隊運用共通的 C# 技能、程式庫與工具,建立 API 和網頁介面;Razor 工具、Hot Reload 與 AI 輔助則有助於縮短迭代時間。講者舉 Toscano Digital 為例:其五人開發團隊在既有 Blazor 內部 CRM 之外,建立公開房地產入口網站,每年服務約 500 萬次工作階段與 1,100 萬次頁面瀏覽。團隊結合 .NET 與 Blazor 的不同渲染策略,兼顧搜尋可見度、行動裝置效能和豐富互動,並透過 C# 全端開發及平台內建功能提高生產力。
Blazor 生態系也獲得合作夥伴投入。Infragistics 將超過 50 個 Ignite UI for Blazor 元件以免費、開源方式提供,涵蓋資料格、清單、輸入、導覽與版面配置等。Syncfusion 則推出免費開源的 Syncfusion Toolkit for Blazor,包含圖表、輸入、行事曆與對話方塊。這兩項產品均採 MIT 授權,可用於商業用途,且與廠商原有的商用元件套件分開提供。除了元件,Infragistics 也為 .NET 11 貢獻可找出常見錯誤的 Blazor 分析器;Syncfusion 則投入框架與鷹架修正、診斷訊息改善,以及新功能測試。
C# Union、OpenAPI 與非同步驗證
.NET 11 的 ASP.NET Core 支援在 API 和網頁介面中使用 C# Union。以退貨處理為例,同一個結果可以是「退款」或「更換商品」,兩者具有不同欄位。開發者可用 Union 表達這兩種情況,讓 System.Text.Json 依實際值序列化對應內容,並由 ASP.NET Core 產生描述各種可能結果的 OpenAPI 3.2 Schema。示範中的 Minimal API 分別回傳退款與更換商品資料,不需要額外包裝物件或型別辨識欄位;Razor 與 Blazor 介面也可依 Union 的實際情況,呈現對應內容。
商業規則常需要查詢資料庫或呼叫其他服務,因此不一定能同步完成。.NET 11 的 Data Annotations 加入非同步驗證 API:AsyncValidation 屬性可建立可重複使用的自訂規則,IAsyncValidatableObject 則可進行物件層級、涉及多個欄位的檢查。Minimal API 與 Blazor 都支援這兩種方式。
示範中,客服選擇更換商品型號時,系統會非同步查詢庫存。頁面在等待期間顯示載入提示,並依結果告知商品是否有貨。實作上,更換商品的請求模型沿用一般資料註解驗證,另以自訂的 InStockAttribute 執行庫存檢查;Blazor 表單仍使用一般的 EditForm 與 Data Annotations 驗證器,並可透過相關 API 偵測驗證是否仍在進行。相同模型也能用於 Minimal API:無庫存的型號會得到驗證失敗結果,有庫存的型號則回傳 HTTP 200。
兩種執行階段仍有較底層的差異。Mono 提供豐富的嵌入 API,讓原生 C 或 C++ 程式碼載入型別、呼叫方法並檢查 .NET 型別;CoreCLR 沒有完全對等的 API 集合。因此,依賴 Mono 嵌入 API 的特殊專案,例如某些遊戲引擎整合方式,可能需要重新設計。不過,這通常不是一般 .NET MAUI 應用會碰到的層次。
過去使用 Mono AOT 時,建置工具 mono-aot-cross 會處理應用程式的 DLL,並為各 DLL 產生對應的原生函式庫。改用 CoreCLR 後,對應的重要技術是 Ready to Run(R2R):CrossGen2 會在建置時產生原生碼,並將其放入仍含有 IL 的 DLL。這也是啟用 Ready to Run 後,DLL 可能變大的原因。
在 Android 上,.NET MAUI 預設採用部分 Ready to Run,而非將所有程式碼都預先編譯。團隊透過具有代表性的 MAUI 應用記錄啟動時用到的方法,將資料保存為 MIBC 檔案,交給 Ready to Run 編譯器使用。如此可優先加快啟動路徑,同時避免完整預先編譯造成應用程式體積大幅增加。開發者仍可評估自己的應用,決定是否以較大的檔案換取完整 Ready to Run 可能帶來的效能收益。iOS 則因無法以相同方式使用 JIT,沒有採用 Android 的這種部分 Ready to Run 預設方案。
應用程式的封裝方式也會隨之變化。在 Android 上,.NET 組件會被放入名為 libassemblystore 的原生函式庫中,便於依裝置架構封裝與配送。使用 CoreCLR 時,其中除了 IL,也可能包含 Ready to Run 映像;一般開發者通常不需要直接處理這些內部檔案。
Native AOT 是另一條路,不等於這次的 CoreCLR 切換
Native AOT 不只是「把 Ready to Run 開得更完整」,而是另一種執行階段與建置模式。它在建置時完成編譯,不依賴 JIT,並積極移除未使用的程式碼。其成果通常是啟動更快、體積更小的應用;例如 Android 可產生一個包含執行階段與已編譯 .NET 程式碼的 .so 檔案。不過,在這場分享所述的階段,Android 上的 Native AOT 仍屬預覽功能。
John 展示了以 Samsung Galaxy A16 等裝置測試的代表性結果,涵蓋 MAUI 專案範本、加入更多控制項與圖表的範例,以及實際以 .NET MAUI 建置的 Microsoft 365 Admin 應用。在 Android 上,Mono、預設的部分 Ready to Run,以及完整 Ready to Run 的啟動表現大致可比;部分與完整 Ready to Run 哪個較快,會因應用而異。在 iOS 的測試中,展示的應用啟動時間則普遍有所改善。
體積方面,Android 的部分 Ready to Run 與原先 Mono 版本相近,完整 Ready to Run 通常會讓 APK 稍微變大;展示的 iOS 測試則呈現應用程式體積縮小的趨勢。這些結果並不保證每個應用都會相同,因此團隊希望開發者以自己的實際專案測量;若出現明顯異常,也歡迎回報以便調查。
二十年前,Y Combinator(YC)聯合創始人 Paul Graham 曾把「一個人創業」列為可能害死新創公司的頭號錯誤。如今,YC 總裁 Gary Tan 卻在播客《Lightcone》中說:「YC 自己就是獨自創業者的 YC。」這並不代表找搭檔已經過時,而是 AI 正在改變創業初期需要多少人、哪些能力最難取得。
**第二個變化,是資深創業者更能發揮優勢。**Gary Tan 說,他最近見到的一些出色創始人,年齡在三十多、四十多歲,甚至五十多歲。他舉 OpenCLAW 作者 Peter Steinberger 為例:對方四十歲,先前有十年經營公司的經驗。合夥人 Jared 指出,管理 AI 程式設計代理,在某些方面與管理人員相似:都要拆解任務、訂立標準、驗收成果,並預判容易出錯之處。這些能力往往來自長年的實務經驗。當「不會寫程式碼」或「找不到技術搭檔」不再像以前那樣難以克服,熟悉一個行業的人,也更有機會親手驗證自己的想法。
強化學習環境可以理解為 AI 的模擬考場。例如建立一套虛構的公司財務系統,放入帳本、發票和待辦事項,讓 AI 練習對帳、報稅,並依結果自動評分。要讓 AI 學會處理真實工作,除了讀取資料,還需要能反覆操作、檢驗對錯的場景;環境越貼近現實,就越有價值。機器人領域也有類似需求:有公司在各地工廠,以第一人稱視角拍攝工人的操作,再將資料提供給機器人實驗室。YC 認為,部分業者不願公開談論這門生意,正因為不想讓競爭對手注意到機會;YC 於 2016 年投資的 Scale AI,則是這個領域的早期代表。
一段談論 AI 工作方式的影片近期引發討論。原文介紹,一名網名「土豆女神」的工程師 Lauren Tan,展示了由一個 AI 協調多個 AI 代理(Agent)處理工作的做法。原文也提到「指揮 50 多個 AI」、「完成 20 多名工程師的工作量」及「公司九成以上員工都在使用」等說法;這些是原文轉述的宣稱,不能僅憑這段文字確認。
在上一篇關於 Microsoft Agent Framework 系列教學文章 "MFA014 - 多模態輸入(圖片)" 中,我們學會了使用 Microsoft Agent Framework 建立能夠處理圖片輸入的 AI 代理。讓模型接收到多模態的資料,在這裡使用的圖片,這裡的圖片將會是冰箱的照片。透過這個練習,我們了解了如何讓 AI 代理分析圖片內容並給出建議。
在完成這篇文章的練習之後,你將能夠使用 Microsoft Agent Framework 建立一個能夠處理多輪對話的 AI 代理,並了解 Responses API 與 Chat Completions 代理在多輪對話中的差異。所謂的 Chat Completion API 則是每輪都需要將完整對話歷史送給模型,服務端不會保存對話狀態。而對於 Responses API,服務端會保存對話狀態,因此每輪不需要重送完整對話歷史,且能保留上一輪的推論摘要。那麼對於使用者而言,面對問題需求的時候,該如何挑選適合的代理,就可以根據是否需要服務端保存對話歷史以及對訊息數與 Token 使用量的考量來決定。
接下來看看如何做到這樣的效果。
建立 Console 專案
開啟 Visual Studio 2026
選擇「建立新專案」
在 [建立新的專案] 視窗中,在右方清單內,找到並選擇「主控台應用程式」 項目
然後點擊右下方「下一步」按鈕
此時將會看到 [設定新的專案] 對話窗
在該對話窗的 [專案名稱] 欄位中,輸入專案名稱,例如 "csResponsesAgent"
然後點擊右下方「下一步」按鈕
接著會看到 [其他資訊] 對話窗
在這個對話窗內,確認使用底下的選項
架構:.NET 10.0 (或更新版本)
勾選 不要使用最上層陳述式 (這是我的個人習慣)
然後點擊右下方「建立」按鈕
現在,已經完成了這個 Console 主控台 專案的建立
安裝需要用到的 NuGet 套件
要完成這個第一次接觸 Microsoft Agent Framework 練習專案,需要安裝以下幾個 NuGet 套件:
Microsoft.Agents.AI.OpenAI
這個套件是微軟官方為 .NET 整合 AI 服務所提供的擴充套件,專門用於與 OpenAI 進行整合。它實現了 IChatClient 與 IEmbeddingGenerator 核心抽象介面,讓開發人員能以一致的程式碼,輕鬆串接 OpenAI 或相容的 API 端點(例如 Azure OpenAI、GitHub Models 等)。
在上面的範例程式碼中,將會展示如何使用 Responses API 代理與 Chat Completions 代理,並比較它們在處理同一個邏輯題時的行為差異。為什麼會想要這麼來比較呢?因為,這裡提供兩種類型的 API,當我們遇到問題的時候,究竟要如何選擇採用哪種 API 呢?透過這個範例,我們可以觀察到兩者在訊息傳遞、對話管理以及推論摘要上的差異,進而做出更適合的選擇。
**Explaining the puzzle setup**
I’m considering a standard puzzle with three labeled boxes: apple, orange, and mixed, but they’re all incorrectly labeled. Typical strategies involve drawing from the mixed box to find the correct fruit, but here there are four types with three fruit kinds, which complicates things. It seems like one sample isn’t enough to solve this, and I should clarify using counterexamples to support that idea while keeping the explanation concise and clear.
【reasoning effort = High】
[推論摘要]
**Solving the labeling puzzle**
I need to find a solution involving boxes labeled incorrectly with their contents. The mixed-labeled box will help identify what’s inside, which will then allow me to label the others correctly. If I draw an apple from the mixed box, I can eliminate that as a possibility for the remaining boxes, given the constraints of labeling. For instance, if I label one box correctly, I can’t have the others labeled correctly. I’ll explore all possible arrangements next.**Analyzing the box labeling puzzle**
I’m trying to determine if the arrangement A-box B, O-box M, and B-box O is valid. Drawing from the mixed box could help identify one pure box, but it might not uniquely solve the problem with three remaining boxes. To answer the user’s question about guaranteeing the correct contents of four boxes, I need to explain clearly that it’s not possible with just one draw from the mixed box. I have to demonstrate this effectively in three sentences.**Examining labeling strategies**
I need to illustrate that no strategy guarantees accurate labeling, although drawing from the mixed-labeled box seems to be the best option. If I draw an apple, I can identify the mixed box but face ambiguity with two potential assignments. To clarify, I'll label the boxes as Apple A, Orange O, Banana B, and Mixed M. If I draw an apple from M, the remaining contents could suggest two valid assignments for the other labels, which complicates things further.
[答案]
**不能保證推出四個盒子的正確內容。**例如從「混合」盒取出蘋果,可知該盒是純蘋果;但剩下仍可能是「蘋果標籤盒=混合、橘子標籤盒=香蕉、香蕉標籤盒=橘子」,也可能是「蘋果標籤盒=香蕉、橘子標籤盒=混合、香蕉標籤盒=橘子」,兩者都符合所有標籤貼錯,因此一次取樣不足以唯一判定。
token:輸入 118(快取 0)/輸出 652(其中推論 516)/總計 770
從上面的 Low & High 的執行結果可以看出,ReasoningEffort.Low 的推論較為簡單快速,但可能忽略一些細節,例如:無法完整展示所有可能的盒子排列,對於保證正確標籤的推論不夠全面。而 ReasoningEffort.High 則提供了更完整的分析,考慮了多種可能性,能更清楚地說明為什麼無法保證推出四個盒子的正確內容。
觀察上面的對照小結:第二輪(追問)可以發現,Responses API 只送出一則訊息,但服務端會自動帶入上一輪的完整對話歷史,因此能保留推論摘要;而 Chat Completions 代理則需要每輪重送完整對話歷史,導致訊息數增加,且無法保留上一輪的推論內容。這也說明了兩種代理在處理多輪對話時的差異:Responses API 依賴服務端保存對話,Chat Completions 則依賴本機管理對話歷史。對於 Token 使用量而言,Responses API 可能因為帶入完整對話歷史而增加輸入 token,但仍能減少訊息數;Chat Completions 則每輪都需重送完整對話歷史,訊息數增加,且無法保留推論摘要。
執行結果
現在來看看這個範例程式碼的執行結果。
在 Visual Studio 2026 下,按下 F5 鍵執行程式,將會看到程式輸出的結果。
使用的模型:gpt-5.6-luna
邏輯題:有四個盒子,標籤分別是「蘋果」「橘子」「香蕉」「混合」,但四個標籤全部貼錯了。你只能從其中一個盒子拿出一顆水果來看(不能看盒子裡面),能不能保證推出四個盒子的正確內容?請說明。
======================================================================
示範一:Responses API + 推論摘要(同一道題,effort = Low vs High)
======================================================================
【reasoning effort = Low】
[推論摘要]
**Explaining the puzzle setup**
I’m considering a standard puzzle with three labeled boxes: apple, orange, and mixed, but they’re all incorrectly labeled. Typical strategies involve drawing from the mixed box to find the correct fruit, but here there are four types with three fruit kinds, which complicates things. It seems like one sample isn’t enough to solve this, and I should clarify using counterexamples to support that idea while keeping the explanation concise and clear.
[答案]
**結論:不能保證推出四個盒子的正確內容。**
應從標籤「混合」的盒子取水果,因為它不可能是混合盒,若取到蘋果,只能確定該盒是純蘋果,但其餘三盒仍可能有多種符合「全錯」的排列,例如「蘋果標籤盒」可為混合或橘子盒。
因此一次取樣所得資訊不足以唯一確定四個盒子的內容。
token:輸入 118(快取 0)/輸出 418(其中推論 295)/總計 536
【reasoning effort = High】
[推論摘要]
**Solving the labeling puzzle**
I need to find a solution involving boxes labeled incorrectly with their contents. The mixed-labeled box will help identify what’s inside, which will then allow me to label the others correctly. If I draw an apple from the mixed box, I can eliminate that as a possibility for the remaining boxes, given the constraints of labeling. For instance, if I label one box correctly, I can’t have the others labeled correctly. I’ll explore all possible arrangements next.**Analyzing the box labeling puzzle**
I’m trying to determine if the arrangement A-box B, O-box M, and B-box O is valid. Drawing from the mixed box could help identify one pure box, but it might not uniquely solve the problem with three remaining boxes. To answer the user’s question about guaranteeing the correct contents of four boxes, I need to explain clearly that it’s not possible with just one draw from the mixed box. I have to demonstrate this effectively in three sentences.**Examining labeling strategies**
I need to illustrate that no strategy guarantees accurate labeling, although drawing from the mixed-labeled box seems to be the best option. If I draw an apple, I can identify the mixed box but face ambiguity with two potential assignments. To clarify, I'll label the boxes as Apple A, Orange O, Banana B, and Mixed M. If I draw an apple from M, the remaining contents could suggest two valid assignments for the other labels, which complicates things further.
[答案]
**不能保證推出四個盒子的正確內容。**例如從「混合」盒取出蘋果,可知該盒是純蘋果;但剩下仍可能是「蘋果標籤盒=混合、橘子標籤盒=香蕉、香蕉標籤盒=橘子」,也可能是「蘋果標籤盒=香蕉、橘子標籤盒=混合、香蕉標籤盒=橘子」,兩者都符合所有標籤貼錯,因此一次取樣不足以唯一判定。
token:輸入 118(快取 0)/輸出 652(其中推論 516)/總計 770
======================================================================
示範二:服務端保存對話(Responses API,只傳上一輪的 response id)
======================================================================
【第一輪:原題】
[推論摘要]
**Explaining a classic puzzle**
I need to answer in traditional Chinese, starting with a clear conclusion followed by an explanation of three sentences maximum. The puzzle involves labeling where the contents are pure apple, orange, banana, or a mixed fruit, all with wrong labels. The strategy is to draw from the box labeled mixed, as it cannot contain mixed fruit, allowing identification of the true contents of the other boxes too.
[答案]
可以保證。先從標示「混合」的盒子取一顆,因標籤全錯,它不可能是混合盒,因此看到的水果即可確定該盒是對應的單一水果盒;再依「其餘標籤全錯」的條件,排除已知內容,唯一確定另外三盒的正確配置。
實際送出訊息數:1 則
帶出的對話 id :(無)
回來後 session.ConversationId:resp_09570987efccb64b006af16ce2a45c8193bf29d2ab8c90fe24
token:輸入 118(快取 0)/輸出 172(其中推論 81)/總計 290
【第二輪:追問(不重述題目)】
[推論摘要]
(沒有收到推論摘要:Chat Completions 不提供;Responses 則在推論太短時會省略)
[答案]
應從標示「混合」的盒子拿。因為標籤全錯,該盒必定是純蘋果或純橘子;若拿到蘋果,它就是蘋果盒,標示「橘子」的盒子只能是混合盒,剩下的是橘子盒(拿到橘子時反之亦然)。
實際送出訊息數:1 則
帶出的對話 id :resp_09570987efccb64b006af16ce2a45c8193bf29d2ab8c90fe24
回來後 session.ConversationId:resp_09570987efccb64b006af16d266f98819398624f4df0d0cb1b
token:輸入 331(快取 0)/輸出 89(其中推論 0)/總計 420
======================================================================
示範三:對照組 Chat Completions(每一輪都把整段歷史重送)
======================================================================
【第一輪:原題】
[推論摘要]
(沒有收到推論摘要:Chat Completions 不提供;Responses 則在推論太短時會省略)
[答案]
**不能保證推出四個盒子的正確內容。**
例如從「混合」盒取出蘋果,只能確定該盒是「蘋果」,但其餘仍可能是「蘋果標籤=橘子、橘子標籤=香蕉、香蕉標籤=混合」,也可能是「蘋果標籤=混合、橘子標籤=香蕉、香蕉標籤=橘子」,兩者都符合所有標籤貼錯。
因此一次取出一顆水果的資訊不足以唯一確定四盒內容。
實際送出訊息數:1 則
帶出的對話 id :(無)
回來後 session.ConversationId:(無,歷史存在本機 session)
token:輸入 118(快取 0)/輸出 660(其中推論 512)/總計 778
【第二輪:追問(不重述題目)】
[推論摘要]
(沒有收到推論摘要:Chat Completions 不提供;Responses 則在推論太短時會省略)
[答案]
**應該從標籤為「混合」的盒子拿一顆水果。**
因為所有標籤都錯,「混合」盒不可能是混合;若拿出蘋果,它就是蘋果盒,接著標籤「橘子」的盒只能是混合,標籤「蘋果」的盒則是橘子。
若拿出橘子,推理對調即可,因此一定能推出三盒內容。
實際送出訊息數:3 則
帶出的對話 id :(無)
回來後 session.ConversationId:(無,歷史存在本機 session)
token:輸入 307(快取 0)/輸出 177(其中推論 58)/總計 484
======================================================================
對照小結:第二輪(追問)
======================================================================
實際送出的訊息數:Responses = 1 則|Chat Completions = 3 則
帶出的對話 id:Responses = 上一輪的 response id|Chat Completions = (無)
輸入 token(其中快取):Responses = 331(0)|Chat Completions = 307(0)
推論 token:Responses = 0|Chat Completions = 58
兩輪中拿到推論摘要:Responses = 是|Chat Completions = 否
對話歷史存在哪裡:Responses = OpenAI 服務端|Chat Completions = 本機 AgentSession
觀察:Responses 第二輪只送 1 則訊息,但服務端會把上一輪的完整內容(含推論項目)接回上下文,
所以輸入 token 照樣計費,甚至可能比 Chat Completions 多;Chat Completions 重送的只有看得見的文字,
上一輪的推論內容直接丟掉。(提示快取要前綴超過約 1,024 token 才會命中,這個範例太短所以是 0)