Vai al contenuto

L'optimistic UI per agenti AI funziona solo se l'annullamento è reale

AI · 10 novembre 2026 · 9 min di lettura

Glowing outlines on black: a row of five tiles on a line, the first three lit white with a curved arrow looping back over them and the third inside a three-quarter ring, then two tall white bars like a closed gate, and two faint grey tiles waiting beyond it with nothing above them

L'optimistic UI per le azioni di un agente AI è un modo di dare riscontro che mostra il risultato del lavoro dell'agente prima che il server lo confermi, e resta onesta solo se il prodotto può riprendersi quel risultato. Un pulsante "mi piace" può diventare pieno in 50 millisecondi perché la richiesta non fallisce quasi mai e, quando fallisce, non costa nulla. Un agente che rimborsa un ordine, scrive al cliente e chiude il ticket non fa niente di tutto questo in 50 millisecondi. Sbaglia più spesso, e lascia effetti fuori dal prodotto che nessun ripristino dello stato può raggiungere.

Questo articolo è per i team di prodotto che stanno mettendo agenti dentro un SaaS e vogliono che lo schermo reagisca appena l'utente chiede, senza mai scrivere "Fatto" per qualcosa che non è successo. La regola che seguiamo sta in una riga: l'intenzione si mostra subito, un effetto solo quando è avvenuto.

Perché un agente manda in crisi l'optimistic UI?

L'optimistic UI classica si regge su tre presupposti. Il server risponde in fretta. La richiesta va quasi sempre a buon fine. Un errore costa poco, perché annullarlo vuol dire rimettere sullo schermo il valore di prima. Le azioni di un agente li smentiscono tutti e tre.

Prima la velocità. I tre limiti dei tempi di risposta di Nielsen Norman Group descrivono ancora bene il problema: 0,1 secondi danno la sensazione di aver causato il risultato, 1 secondo non interrompe il filo del pensiero, 10 secondi sono più o meno il limite oltre il quale l'attenzione si sposta altrove. Da lì in poi, dice lo stesso articolo, chi usa il prodotto ha bisogno di sapere quando il lavoro finirà, e quell'informazione conta di più quando i tempi variano molto. L'esecuzione di un agente è variabile per definizione: la stessa richiesta può chiedere una chiamata a uno strumento o dodici.

Poi la probabilità di riuscita. Un'esecuzione fallisce quando il modello fraintende la richiesta, quando uno strumento va in timeout, quando manca un permesso. Ogni passo è una nuova occasione di errore, quindi un'esecuzione di sette passi fallisce più spesso di una singola scrittura nel proprio database.

Infine il ripristino, ed è il punto che fa più male. useOptimistic di React mostra un valore temporaneo mentre un'Action è in corso. Se l'Action lancia un errore, la Transition finisce e React torna a mostrare il valore reale: l'elemento ottimistico sparisce. La documentazione lascia a te il compito di avvisare l'utente. Lo schermo torna indietro, la spiegazione no. E se il passo era un'email già partita, rimettere a schermo il valore di prima non cambia nulla nella casella del cliente.

Perché uno spinner non risolve

La ritirata più comune è un solo indicatore "Sto pensando..." per tutta l'esecuzione. È onesto e non serve a niente. Quaranta secondi della stessa animazione non dicono quale passo è in corso, non danno nulla da annullare e invitano a cliccare di nuovo, il che fa partire una seconda esecuzione. Scrivere "Fatto" in anticipo è utile e falso. Le pratiche che seguono stanno nel mezzo.

Classificare ogni azione in base a quanto costa annullarla

Prima di disegnare qualsiasi schermata, le azioni che l'agente può compiere vanno divise in tre classi. La classe decide cosa l'interfaccia può mostrare prima della conferma.

ClasseEsempiCosa mostra subito lo schermoCome si annulla
Locale e reversibileScrivere una bozza, assegnare un'etichetta, riordinare una lista dentro il prodottoIl risultato, subitoSi ripristina lo stato di prima e si spiega perché
Invio differitoInviare un'email, pubblicare un messaggio, fissare una riunioneL'effetto in attesa, con un conto alla rovescia e il tasto AnnullaSi annulla prima che scada la finestra: non è ancora partito niente
Esterna e irreversibileAddebitare o rimborsare una carta, cancellare dati in un altro sistemaIl piano, poi una conferma, poi l'avanzamento realeDopo l'invio non si annulla: serve una seconda azione che compensi

Quasi tutti i guai nascono quando un'azione di classe 3 riceve il riscontro di una di classe 1. Le sei pratiche che seguono applicano la tabella.

1. Essere ottimisti sul piano

Entro 100 millisecondi dalla richiesta, lo schermo mostra il piano dell'agente come una lista di passi segnati "previsto". È un'affermazione vera: la richiesta è arrivata e l'agente sa come trattarla. Sui risultati non afferma nulla. Victor Yocco, nei suoi pattern per l'AI agentica su Smashing Magazine, la chiama Intent Preview e la colloca prima che l'agente agisca, accanto all'Autonomy Dial, la regolazione di quanto l'agente può fare senza chiedere. Se il modello non ha ancora prodotto un piano, la prima riga ripete la richiesta stessa. Lo schermo si muove e niente di quello che mostra è falso.

2. Uno stato per ogni passo

Gli stati sono cinque: previsto, in corso, fatto, fallito, saltato. Il server li invia uno alla volta, appena un passo cambia, e la lista si riempie sotto gli occhi dell'utente. Un'esecuzione di sette passi diventa "passo 3 di 7, cerco l'ordine", che risponde alla domanda di NN/g su quando finirà meglio di una barra in percentuale, visto che nessuno sa quanto durerà il passo 5. Uno spinner unico nasconde proprio l'informazione che serve quando l'esecuzione fallisce: dove si è fermata.

3. Una finestra di attesa per tutto ciò che esce dal prodotto

L'annullamento dell'invio di Gmail fa scegliere un periodo di 5, 10, 20 o 30 secondi. Funziona perché il messaggio non è ancora partito: Gmail aspetta prima di consegnarlo. Agli agenti serve lo stesso meccanismo. L'effetto verso l'esterno va in coda, lo schermo lo mostra come "Invio al cliente tra 10 s" con il tasto Annulla, e l'invio avviene allo scadere del tempo. L'annullamento è reale perché non è ancora successo nulla. Richiamare un messaggio già consegnato è un'altra funzione, molto più debole.

4. Chiedere conferma prima degli effetti irreversibili

OpenAI l'ha messo dentro Operator: l'agente chiede conferma prima di concludere compiti con effetti esterni, come confermare un ordine o inviare un'email. Le linee guida per l'interazione uomo-AI di Microsoft descrivono il caso generale nella G10: quando il sistema non è sicuro dell'obiettivo dell'utente, chiede prima di agire. Un effetto irreversibile è il caso in cui quel dubbio costa di più. La conferma nomina l'effetto esatto: l'importo, il destinatario, il conto. Per un'operazione in blocco si chiede una volta sola, con l'elenco completo: 40 rimborsi diventano una decisione, non 40 interruzioni.

5. Rendere sicuro il secondo tentativo prima di rendere veloce il pulsante

Un riscontro rapido invita a riprovare, e chi non è sicuro clicca di nuovo. Ogni azione dell'agente riceve una chiave di idempotenza, creata insieme al piano, così un'esecuzione ripetuta porta la stessa chiave. Le richieste idempotenti di Stripe mostrano il contratto: un secondo tentativo con la stessa chiave entro 24 ore restituisce il primo risultato, e dopo quel termine le chiavi possono essere eliminate. Senza chiave, uno schermo ottimista più un utente in ansia fanno un rimborso doppio.

6. Quando un passo fallisce, tornare indietro sullo schermo e dire cosa è successo

La linea guida G9 di Microsoft chiede di rendere facile la correzione: modificare, rifinire o recuperare quando il sistema sbaglia. In un'esecuzione vuol dire che il passo fallito diventa rosso con il motivo in parole semplici, i passi già fatti restano segnati come fatti (l'email è partita, il rimborso no), quelli che ne dipendevano passano a saltati, e lo schermo propone una sola azione: riprovare il passo, cambiare la richiesta o passarla a una persona. Per le parole da usare c'è il nostro articolo sugli stati di errore nella UX.

Come appare su una schermata vera

Prendiamo un ipotetico agente di supporto dentro un software di helpdesk. L'utente scrive: "Rimborsa l'ordine 4417 e avvisa il cliente".

  1. A 0,1 secondi compare un piano: cerco l'ordine 4417, rimborso 84,00 € sulla carta registrata, scrivo al cliente, chiudo il ticket. Tutti e quattro i passi sono "previsti".
  2. Il passo 1 parte e diventa fatto in circa due secondi. Legge soltanto dei dati, quindi non c'è niente da proteggere.
  3. Il passo 2 si ferma su una conferma con l'importo e le ultime quattro cifre della carta. L'utente conferma. Il rimborso parte con la chiave di idempotenza creata insieme al piano, e il passo diventa fatto quando il fornitore dei pagamenti conferma il rimborso, non quando parte la richiesta.
  4. Il passo 3 mostra "Invio al cliente tra 10 s" con il tasto Annulla. L'email aspetta in coda dietro il passo 2.
  5. Il passo 4 chiude il ticket. Vive dentro il prodotto e si può riaprire, quindi lo schermo lo mostra chiuso subito.

Se il rimborso fallisce, il passo 2 diventa fallito con il motivo dato dal fornitore, i passi 3 e 4 passano a saltati e l'email non parte mai, perché era in coda dietro un passo che non si è concluso. L'utente ha davanti una sola cosa da decidere.

Quanto costa questo approccio

Tre costi, da conoscere prima di adottarlo. La finestra di attesa aggiunge la sua durata a ogni invio: con 10 secondi, ogni email scritta dall'agente arriva 10 secondi dopo. Le conferme rallentano chi usa l'agente più spesso; la soluzione è un'impostazione di autonomia con cui un team approva in anticipo una classe di azioni, per esempio i rimborsi sotto i 50 €, e tiene le conferme per il resto. E inviare lo stato di ogni passo richiede un backend che emetta un evento per passo, più lavoro di una richiesta e una risposta. Se l'agente è ancora un unico prompt dietro un pulsante, le decisioni da prendere prima sono nel nostro articolo sugli agenti AI dentro un SaaS.

In cambio si ottiene uno schermo che reagisce in 100 millisecondi e non dice mai qualcosa che il sistema dovrà poi rimangiarsi.

Domande frequenti

Preferisci che lo facciamo noi?

Progettiamo e sviluppiamo questo tipo di lavoro per i clienti. Raccontaci di cosa hai bisogno.