Per molto tempo integrare l'intelligenza artificiale in un'applicazione ha significato soprattutto una cosa: aggiungere una chat.
Una finestra laterale, un prompt, una risposta generata da un LLM.
Con i nuovi componenti sperimentali Microsoft.AspNetCore.Components.AI, Microsoft sta però esplorando un modello molto più interessante: portare gli agenti direttamente dentro l'architettura e lo stato delle applicazioni Blazor.
Non più soltanto:
Utente → Prompt → LLM → Testo
ma qualcosa di molto più vicino a:
Utente → UI → Agent → Tools → Application State → UI
Microsoft definisce questo modello Agentic UI.
Microsoft.AspNetCore.Components.AI
Il nuovo package sperimentale introduce componenti e astrazioni pensati per integrare interazioni agentiche direttamente nelle applicazioni Blazor.
Al momento il package richiede il .NET 11 RC1 SDK e può essere installato come prerelease:
dotnet add package Microsoft.AspNetCore.Components.AI --prerelease
Uno degli elementi centrali è UIAgent.
Partendo dall'astrazione IChatClient di Microsoft.Extensions.AI possiamo creare un agente utilizzabile direttamente dalla UI:
IChatClient chatClient = GetChatClient();
var agent = new UIAgent(chatClient);
Per ottenere rapidamente una classica interfaccia conversazionale possiamo utilizzare ChatPage:
<ChatPage Agent="_agent"
Placeholder="Ask me anything…" />
ChatPage gestisce già diversi aspetti dell'interazione, tra cui lista dei messaggi, input, streaming e retry.
Ma la parte più interessante non è la chat.
UIAgent trasforma infatti l'output progressivo dell'agente in ContentBlock osservabili che i componenti Blazor possono renderizzare e aggiornare mentre l'interazione procede.
Dal testo alla UI strutturata
In una normale applicazione AI il risultato di un tool finirebbe spesso all'interno della risposta testuale del modello.
Immaginiamo per esempio un agente che invochi:
get_weather("Milano")
Potremmo semplicemente visualizzare:
Milano: 18°C
Con Agentic UI possiamo invece associare quella chiamata a un blocco fortemente tipizzato:
[ToolBlock("get_weather")]
public partial class WeatherToolBlock
: FunctionInvocationContentBlock
{
[ToolParameter(Name = "location")]
public string? Location { get; set; }
[ToolResult]
public WeatherInfo? Weather { get; set; }
}
Blazor può quindi decidere come rappresentare quel risultato:
<BlockRenderer TBlock="WeatherToolBlock">
<div class="weather-card">
<strong>@context.Location</strong>
<div>@context.Weather?.Temperature °C</div>
</div>
</BlockRenderer>
Il punto architetturalmente interessante è questo:
l'agente decide cosa fare, mentre l'applicazione mantiene il controllo su come rappresentarlo.
L'LLM non deve quindi generare HTML arbitrario. Può produrre tool call e dati strutturati, mentre Blazor continua a gestire componenti, dependency injection, CSS, localizzazione e logica applicativa.
Backend Tools e Frontend Tools
Agentic UI distingue anche tra operazioni eseguite sul backend e operazioni che appartengono direttamente alla UI.
Un backend tool potrebbe interrogare:
- database;
- API REST;
- servizi aziendali;
- motori di ricerca;
- sistemi GIS;
- servizi cloud.
L'architettura potrebbe essere:
Agent
↓
Backend Tool
↓
ASP.NET Core
↓
Database / API / Service
Ma possiamo anche definire frontend tools, cioè funzioni eseguite direttamente dall'applicazione Blazor.
L'esempio Microsoft modifica il colore dell'interfaccia:
var setAccentColor =
AIFunctionFactory.Create(
async (string color) =>
{
await InvokeAsync(() => _accent = color);
return $"Accent color set to {color}.";
},
name: "set_accent_color",
description: "Set the accent color of the page.");
Questo concetto può essere applicato a operazioni molto più interessanti:
set_status_filter("Unavailable")
select_service("GIS03")
open_details_panel("GIS03")
Un utente potrebbe quindi scrivere:
Mostrami solamente i servizi ArcGIS che hanno problemi.
L'agente potrebbe interpretare l'intenzione e modificare direttamente lo stato dell'interfaccia.
Non stiamo più semplicemente generando una risposta.
L'agente sta interagendo con l'applicazione.
Human in the Loop
Quando gli agenti iniziano a utilizzare strumenti capaci di modificare sistemi reali, il controllo dell'utente diventa fondamentale.
I nuovi componenti supportano esplicitamente il pattern Human in the Loop.
Un'operazione sensibile può quindi richiedere un'approvazione:
<BlockRenderer TBlock="FunctionApprovalBlock"
Context="block">
@if (block.Status == ApprovalStatus.Pending)
{
<button @onclick="block.Approve">
Approve
</button>
<button @onclick="() => block.Reject()">
Reject
</button>
}
</BlockRenderer>
Immaginiamo un sistema di monitoraggio GIS.
L'utente chiede:
Riavvia tutti i servizi che risultano Unavailable.
L'agente individua tre servizi, ma invece di eseguire immediatamente l'operazione visualizza:
The agent wants to restart:
MapService01
FeatureService07
ImageService02
[ Approve ] [ Reject ]
Solo dopo l'approvazione dell'utente il backend esegue realmente l'operazione.
È un pattern fondamentale per qualsiasi applicazione enterprise che esponga agli agenti strumenti con effetti reali.
UIAgent<TState>: agente e applicazione condividono lo stato
Probabilmente una delle funzionalità più interessanti è UIAgent<TState>.
Possiamo definire uno stato applicativo fortemente tipizzato:
public class MonitorState
{
public List<ServiceStatus> Services { get; set; } = [];
public string? SelectedServer { get; set; }
public string? Filter { get; set; }
}
e utilizzarlo attraverso:
UIAgent<MonitorState>
A questo punto l'interfaccia e l'agente possono collaborare sullo stesso stato.
Blazor Components
↘
Shared State
↗
Agent
Una Grid può visualizzare Services.
L'utente può cambiare manualmente Filter.
L'agente può impostare SelectedServer.
Una modifica dello stato provoca automaticamente l'aggiornamento dei componenti interessati.
È un modello molto più potente rispetto alla continua trasformazione dello stato dell'applicazione in testo da inserire nei prompt.
Predictive State: l'AI propone, l'utente decide
Un'altra idea particolarmente interessante è quella del Predictive State.
L'agente può proporre una modifica dello stato senza applicarla immediatamente.
Current State
↓
AI Proposal
↓
Diff
↓
Accept / Reject
Possiamo quindi mostrare all'utente la differenza tra lo stato corrente e quello suggerito dall'AI prima di modificare realmente l'applicazione.
Il modello diventa:
AI proposes → Human reviews → Application applies
Per applicazioni gestionali, DevOps, GIS, configuratori o strumenti amministrativi è un pattern estremamente interessante.
AG-UI: collegare l'interfaccia agli agenti remoti
I componenti Blazor possono funzionare con qualsiasi IChatClient, ma Microsoft mostra anche l'integrazione con AG-UI.
AG-UI è un protocollo open ed event-based progettato per standardizzare la comunicazione tra agenti e applicazioni rivolte agli utenti.
Non definisce come deve essere costruita la UI: definisce gli eventi scambiati tra agente e applicazione.
Un'architettura completa può diventare:
Blazor
│
│ AG-UI
│ HTTP + Server-Sent Events
▼
ASP.NET Core
│
▼
Microsoft Agent Framework
│
▼
Microsoft Foundry
│
▼
LLM
Lato Blazor, AGUIChatClient implementa ancora IChatClient.
Questo permette di mantenere una separazione interessante tra interfaccia e implementazione dell'agente.
Dal punto di vista di Blazor l'agente potrebbe essere:
- in-process;
- remoto;
- basato su Microsoft Agent Framework;
- collegato a Microsoft Foundry;
- implementato attraverso altri provider compatibili con
IChatClient.
Microsoft Agent Framework e Aspire
Nel sample completo Microsoft combina diversi elementi dell'ecosistema .NET:
Blazor
↓
Microsoft.AspNetCore.Components.AI
↓
UIAgent
↓
IChatClient
↓
AG-UI
↓
ASP.NET Core
↓
Microsoft Agent Framework
↓
Microsoft Foundry
↓
LLM
Aspire viene utilizzato per orchestrare i diversi progetti, fornire configurazione e service discovery e centralizzare log e tracing.
Inizia quindi a emergere uno stack Microsoft abbastanza completo per lo sviluppo di applicazioni agentiche.
Generative UI senza lasciare il controllo all'LLM
Quando si parla di Generative UI si potrebbe immaginare un LLM che genera direttamente HTML e interfacce arbitrarie.
L'approccio mostrato da Microsoft è più controllato.
L'agente può produrre o aggiornare uno stato strutturato:
{
"steps": [
{
"name": "Connect to Portal",
"status": "completed"
},
{
"name": "Analyze services",
"status": "running"
},
{
"name": "Generate report",
"status": "pending"
}
]
}
Blazor può trasformarlo in un'interfaccia:
✓ Connect to Portal
◉ Analyze services
○ Generate report
e aggiornarla progressivamente durante l'esecuzione dell'agente.
La distinzione è importante:
l'agente genera e modifica dati e stato; Blazor mantiene il controllo del rendering.
Questo permette di conservare tipizzazione, sicurezza, componentizzazione e prevedibilità dell'interfaccia.
Un esempio concreto: un GeoService Monitor agentico
Immaginiamo una dashboard dedicata al monitoraggio di servizi ArcGIS.
La soluzione più semplice sarebbe aggiungere una classica finestra:
Ask AI...
Ma con un'architettura agentica potremmo andare molto oltre.
L'utente potrebbe chiedere:
Analizza GIS03 e cerca di capire perché il servizio non risponde.
L'agente potrebbe automaticamente:
- interrogare ArcGIS REST;
- verificare la raggiungibilità HTTPS;
- controllare il certificato TLS;
- analizzare lo storico del monitoraggio;
- recuperare gli ultimi errori;
- confrontare il comportamento con altri servizi.
La UI potrebbe aggiornarsi progressivamente:
GIS03 Analysis
✓ HTTPS reachable
✓ Certificate valid
✓ ArcGIS Server reachable
✗ Service initialization failed
Possible cause:
Data source unavailable
L'agente potrebbe quindi proporre:
Restart GIS03?
[ Approve ] [ Reject ]
Dopo l'approvazione, il backend esegue l'operazione e lo stato della dashboard viene aggiornato.
Questa non sarebbe più semplicemente una dashboard con una chat AI.
Sarebbe una vera applicazione agentica.
Dalla AI feature all'AI-native application
Negli ultimi anni abbiamo spesso aggiunto l'intelligenza artificiale alle applicazioni secondo questo modello:
Application
+
AI Chat
Agentic UI suggerisce invece qualcosa di diverso:
┌── UI
│
User ──→ Agent ──→ State
│
├── Tools
│
└── Backend
L'agente diventa un partecipante dell'architettura applicativa.
Può utilizzare strumenti, osservare e modificare stato, proporre operazioni e coordinare workflow complessi, mentre l'applicazione continua a mantenere il controllo su autorizzazioni, rendering e operazioni sensibili.
È probabilmente questo il cambiamento più interessante.
Non si tratta semplicemente di costruire chatbot migliori.
Si tratta di progettare applicazioni nelle quali utente, UI, stato, agenti e tool collaborano all'interno dello stesso workflow.
Lo stack .NET da tenere d'occhio
Lo stack che sta emergendo nell'ecosistema Microsoft è particolarmente interessante:
.NET 11
Blazor
Microsoft.AspNetCore.Components.AI
Microsoft.Extensions.AI
Microsoft Agent Framework
AG-UI
ASP.NET Core
Microsoft Foundry
Aspire
Microsoft.AspNetCore.Components.AI è ancora un package sperimentale, quindi oggi eviterei di trasformarlo in una dipendenza critica di un'applicazione production senza un opportuno livello di astrazione.
Ma il modello architetturale che propone merita attenzione già adesso.
Per chi sviluppa applicazioni enterprise .NET, la domanda nei prossimi anni potrebbe quindi non essere più:
Come aggiungo una chat AI alla mia applicazione?
ma:
Quali parti della mia applicazione possono diventare agentiche?
Fonte e approfondimenti
Microsoft .NET Blog — Build Agentic UI with the new Blazor AI components
devblogs.microsoft.com/dotnet/build-agentic-ui-blazor/
Nessun commento:
Posta un commento