Riccardo Vagli

Agenti AI · Una serie in cinque puntate

Costruire un agente AI.
Si comincia dal frigo.

Chef Ubaldo è burbero, pragmatico e allergico agli sprechi. In questa serie lo costruiamo con ADK: dalle prime istruzioni agli strumenti, fino alla collaborazione tra agenti.

Qui raccolgo i post pubblicati su LinkedIn e le guide per seguire il progetto, una versione alla volta.

Le cinque puntate sono disponibili qui sotto, dalle prime istruzioni alla collaborazione tra agenti.

Le puntate

  1. 01Le basi: nasce Chef UbaldoRuolo, vincoli e prima conversazione.
  2. 02Gli strumenti: leggere e aggiornare la dispensaDal modello alle funzioni Python, con controlli sui dati.
  3. 03Sessione e stato: la cena cambiaPersone, preferenze e tempo disponibili durante la conversazione.
  4. 04Profilo utente e ambiti dello statoNome, preferenze abituali e informazioni della conversazione.
  5. 05Una squadra di agentiSpecializzazione, sequenza e passaggio dei risultati.

Puntata 01

Le basi: nasce Chef Ubaldo

Ruolo, vincoli e prima conversazione.

Torni a casa stanco, stressato, fuori c'è un tempo da lupi.
Sono le 20:00, hai fame, apri il frigo: due uova, un barattolo di ceci, del rosmarino e mezzo zucchino triste.

Cosa cucini in 15 minuti sporcando una sola padella?

Ci sono varie possibilità: ti arrangi o lo chiedi a ChatGPT.

Oppure ti crei il tuo agente AI, lo Chef Ubaldo.

Ubaldo, uno chef burbero, pragmatico e allergico agli sprechi. Un agente AI da costruire partendo da zero.

Insomma, con questo post vorrei incignare una serie in cinque puntate per spiegare come si progettano gli agenti AI, con un esempio che dovrebbe interessare anche chi non lavora nell’informatica: uno Svuota-Frigo & Pianificatore della Spesa.

Per costruirlo useremo ADK (Agent Development Kit), un framework open source sviluppato da Google per creare agenti AI.

In pratica, una raccolta di componenti e strumenti con cui definire il comportamento degli agenti, collegarli a funzioni esterne, farli collaborare e testarli.

Perché ho scelto ADK? Perché permette di iniziare con pochi comandi, poche righe di Python e di aggiungere funzionalità man mano.

Inoltre, pur essendo sviluppato da Google, non obbliga a usare i suoi modelli: attraverso le apposite integrazioni possiamo usare anche quelli di altri fornitori o addirittura modelli eseguiti sul nostro computer.

Ma noi partiremo con Gemini tramite Google AI Studio.

Puntata dopo puntata, daremo a Ubaldo strumenti per leggere la dispensa e preparare la lista della spesa. Vedremo come far collaborare più agenti e come verificare che il sistema faccia quello che gli chiediamo.

Quindi, partiamo dalle basi: chi è Ubaldo e come deve rispondere?

Prima di scrivere codice, definiamo tre cose:

🍳 Il ruolo. Un cuoco di vecchia scuola, schietto e poco incline ai complimenti, che ti aiuta a cucinare con quello che hai.

⏱️ I vincoli. Solo gli ingredienti indicati, con acqua, sale, pepe e olio come unici extra. Massimo 15 minuti, una padella e un tagliere.

📋 Il formato della risposta. Nome del piatto, tempo e difficoltà, passaggi in ordine cronologico e un consiglio pratico.

Le istruzioni orientano le risposte, ma non garantiscono che Ubaldo le rispetti sempre.

Potrebbe inventarsi un ingrediente o sottovalutare un tempo di cottura. Anche per questo impareremo a testarlo.

Lo so, potremmo dare le stesse istruzioni a un normale chatbot, ma è troppo facile: molto meglio crearsi il proprio agente.

Questa prima versione serve a definire il comportamento di Ubaldo e ad avviarlo in ADK. Nelle prossime puntate gli daremo gli strumenti per agire sui dati della nostra dispensa.

Lo scopo è anche quello di capire la distinzione tra modello, agente e chatbot. O almeno lo spero.

Per seguire la serie non serve saper programmare. Per chi vuole anche provarci, ho preparato una guida PDF che spiega i passaggi e il loro scopo, dalla preparazione dell’ambiente alla prima conversazione con Ubaldo.

Link nel primo commento.
Il mezzo zucchino, invece, è in frigo.

Puntata 02

Gli strumenti: leggere e aggiornare la dispensa

Dal modello alle funzioni Python, con controlli sui dati.

«Ubaldo, cosa cucino stasera?»
«Se non mi dici cosa hai in casa, che ne so? Il frigorifero mica ce l’ho davanti.»

Ieri abbiamo creato Ubaldo, uno chef burbero che propone ricette con gli ingredienti indicati dall’utente. Ogni volta, però, dobbiamo scrivergli cosa abbiamo.

Oggi gli diamo uno strumento per leggere la dispensa.

Per questo esempio basta aggiungere un file, 'dispensa.json', che contiene ingredienti e quantità.

Niente di complicato: ceci, uova, zucchine e quello che vogliamo aggiungere.

Il modello, da solo, non può aprire quel file. Dobbiamo collegargli un tool, cioè una funzione che il nostro programma mette a sua disposizione per svolgere un’operazione.

Ne prepariamo due:
📖 Leggi la dispensa: restituisce gli ingredienti disponibili e le loro quantità.
✏️ Aggiorna la dispensa: registra le quantità consumate dopo aver cucinato.

Quando chiediamo una ricetta, Ubaldo può richiedere l’esecuzione del primo tool. Il programma legge il file e gli restituisce il contenuto; Ubaldo usa quei dati per formulare la proposta.

Quindi il modello sceglie di richiamare lo strumento, il codice esegue l’operazione, e il risultato torna al modello, che può usarlo per proseguire la conversazione.

Ma c’è un dettaglio da considerare: proporre una frittata non significa che qualcuno l’abbia cucinata.

Se Ubaldo suggerisce di usare due uova, quelle uova devono restare nella dispensa finché non confermiamo di averle consumate. Potremmo cambiare idea e ordinare una pizza.

Quindi Ubaldo propone la ricetta, aspetta la conferma e solo allora richiede l’aggiornamento.

La funzione controlla che le quantità siano valide: non deve essere possibile consumare tre uova se nel file ne risultano due.

Progettare questo passaggio significa decidere quando l’agente può modificare un dato e quali controlli deve eseguire il programma.

Insomma, scrivere nelle istruzioni "stai attento" non basta.

Il test è semplice: si chiede una ricetta, si rifiuta e si controllate la dispensa. Poi si accetta una ricetta e si conferma cosa abbiamo utilizzato.

Se le uova spariscono dalla dispensa prima che di accendere i fornelli, c'è qualcosa da correggere.

Nel primo commento c'è il link alla guida con il codice e le istruzioni per provare questa seconda versione di Ubaldo.

Puntata 03

Sessione e stato: la cena cambia

Persone, preferenze e tempo disponibili durante la conversazione.

«Ubaldo, siamo in quattro e vorremmo una cena vegetariana.»
«Bene. Basta che non me lo dici dopo che ho messo la salsiccia in padella.»
«Anzi, siamo in sei. E abbiamo mezz’ora.»

Una conversazione cambia mentre parliamo. Aggiungiamo informazioni, correggiamo quelle precedenti, cambiamo idea.

Ieri abbiamo dato a Ubaldo, il nostro agente chef, due strumenti per leggere e aggiornare la dispensa. Ora gli serve un modo per tenere in ordine le informazioni sulla cena che stiamo organizzando.

Oggi parliamo di sessione e stato, sempre usando ADK, il framework con cui stiamo costruendo il nostro chef AI.

La sessione raccoglie gli eventi di una conversazione: messaggi, richieste agli strumenti e risultati.

Lo stato della sessione contiene invece informazioni esplicite che il programma può leggere e aggiornare.

Nel nostro esempio:
👥 Commensali: 6
🥬 Preferenza: vegetariana
⏱️ Tempo disponibile: 30 minuti

La cronologia conserva anche il messaggio in cui avevamo detto “siamo in quattro”.
Nello stato vogliamo registrare il valore aggiornato: sei.

Il modello può già ricavare queste informazioni dai messaggi precedenti. Salvarle in modo strutturato permette anche al codice di utilizzarle e controllarle, senza dover ogni volta interpretare tutta la conversazione.

Daremo quindi a Ubaldo uno strumento per aggiornare le preferenze della cena.
Se cambiamo il numero di persone, aggiornerà quel dato mantenendo gli altri. Se una richiesta è ambigua, dovrà chiedere un chiarimento:

«Si aggiungono due amici» significa passare da quattro a sei;

«Forse vengono anche due amici» lascia ancora una decisione da prendere.

E la dispensa? Rimane nel suo file: descrive ciò che abbiamo in casa.

Lo stato della sessione descrive invece la cena di cui stiamo parlando.

Sono informazioni con scopi diversi. Aprire una nuova conversazione non deve far ricomparire le uova che abbiamo consumato, né significa automaticamente ritrovare le preferenze della cena precedente.

Il test, quindi, sarà cambiare un’informazione alla volta e controllare che Ubaldo aggiorni quella giusta, conservando le altre.

Nel primo commento c'è il link al file della guida e del codice della terza versione.

Ubaldo continuerà a borbottare, ma almeno saprà quante persone sono invitate.

Puntata 04

Profilo utente e ambiti dello stato

Che cosa ricordare della persona e che cosa conservare soltanto per la cena.

Un agente AI dovrebbe ricordarsi il tuo nome?

Dipende.

Se gli dici:

«Mi chiamo Riccardo, sono vegetariano e stasera siamo in quattro»

hai fornito tre informazioni apparentemente simili, ma con una durata molto diversa.

Il nome appartiene alla persona.
La preferenza alimentare potrebbe essere valida anche nelle conversazioni future.
Il numero dei commensali riguarda soltanto la cena di stasera.

Mettere tutto nello stesso calderone significherebbe costruire un agente che dimentica ciò che serve oppure che ricorda ciò che dovrebbe dimenticare.

In questa serie sto costruendo Ubaldo, uno chef AI burbero, pragmatico e allergico agli sprechi. Lo sto facendo con ADK, l’Agent Development Kit open source di Google, che permette di creare agenti, assegnare loro strumenti e gestirne conversazioni e stato senza essere vincolati ai soli modelli Google.

Nelle prime puntate abbiamo definito il comportamento di Ubaldo, gli abbiamo dato accesso a una dispensa e gli abbiamo insegnato a conservare le informazioni necessarie durante una conversazione.

Oggi approfondiamo lo stato (state): il luogo in cui un agente conserva le informazioni utili al proprio lavoro.

ADK permette di distinguere diversi ambiti:

  1. Sessione: informazioni valide nella conversazione corrente, come commensali e tempo disponibile.
  2. Utente: informazioni appartenenti alla persona, come nome e preferenze alimentari.
  3. Applicazione: configurazioni condivise da tutti gli utenti dell’agente.
  4. Invocazione corrente: dati temporanei che possono essere eliminati appena terminata una singola operazione.

Faremo quindi ricordare a Ubaldo il nome dell’utente e la sua alimentazione abituale, senza trascinarci dietro i dettagli di tutte le cene precedenti.

Vedremo anche come usare una variabile dentro le istruzioni dell’agente:
{user:nome_utente?}

Il punto interrogativo significa che il valore può non esistere ancora. Se Ubaldo non conosce il nome della persona, non deve bloccarsi, inventarlo o chiamarla "utente".

Poi faremo una prova: gli diremo chi siamo, apriremo una nuova sessione e controlleremo che ricordi la persona, ma non il numero dei commensali della sera precedente.

Progettare lo stato di un agente non è soltanto decidere che cosa deve ricordare, ma significa decidere a quale ambito appartiene ogni informazione e per quanto tempo deve esistere.

Codice e guida completa nel primo commento 👇

Puntata 05

Una squadra di agenti

Specializzazione, sequenza e passaggio dei risultati.

Un agente AI deve fare tutto da solo?

«Ubaldo, organizza la cena, controlla le porzioni e dimmi se devo comprare qualcosa.»

Ubaldo è lo chef AI burbero che sto costruendo con ADK: legge la dispensa, tiene conto delle preferenze e cerca di non sprecare ingredienti.

Nelle prime quattro puntate ha fatto tutto da solo.

Nella quinta, e per ora ultima, gli affido una squadra di tre specialisti:

🍳 Lo Chef creativo propone una ricetta.

🥗 Il Nutrizionista la rivede, con un ruolo puramente dimostrativo.

🧾 Il Contabile di casa controlla scorte, quantità e ingredienti mancanti.

Ubaldo resta il coordinatore: parla con l’utente, raccoglie i dati e presenta il risultato finale.

In ADK i subagent possono lavorare in sequenza, in parallelo o in un ciclo. Si possono anche combinare tra loro.

Qui vediamo una squadra sequenziale:

Chef → Nutrizionista → Contabile

Le risposte degli LLM possono cambiare. Il routing no: una volta invocata la squadra, il codice stabilisce chi lavora prima e chi dopo. Non è un modello a decidere il prossimo passaggio.

Ogni specialista salva il proprio risultato nello stato con output_key, così quello successivo può usarlo.

Il punto non è avere più agenti, ma non concentrare troppi compiti nello stesso prompt.

Se Ubaldo dovesse fare tutto, le istruzioni diventerebbero più lunghe e piene di vincoli, eccezioni e ruoli diversi: aumenterebbe il rischio di confondere i passaggi o ignorare una regola.

Qui ogni specialista riceve un compito circoscritto, mentre il codice ne stabilisce l’ordine.

Nella guida costruiamo questa prima squadra di Ubaldo.

Dal primo prompt a una squadra di agenti

Il percorso completo segue Ubaldo dalle istruzioni iniziali agli strumenti, dallo stato della conversazione al profilo utente, fino alla collaborazione tra agenti.

Rivedi le puntate ↑