Un LLM, da solo, riceve testo e produce testo: non vede il mondo e non può toccarlo. Aggiungendo tool (strumenti) può leggere dati e compiere azioni. Aggiungendo un ciclo che lo lascia decidere il passo successivo da solo, smette di essere un assistente che risponde e diventa un agente che porta a termine un obiettivo. Il modello può essere lo stesso: cambia il sistema che gli costruisci intorno.
Tu chiedi, lui risponde. Tu decidi il passo successivo.
1 richiesta → 1 rispostaTu dai un obiettivo, lui pianifica, agisce, osserva e corregge. Lui decide il passo successivo, finché non ha finito.
1 obiettivo → N azioni → risultatoLa frase descrive l'evoluzione dei sistemi basati su LLM (Large Language Model, modello linguistico di grandi dimensioni) negli ultimi anni. Non indica un salto improvviso, ma uno spettro di autonomia. Lungo lo spettro cambiano tre cose: chi decide cosa fare dopo, quanti passi vengono fatti senza intervento umano, e cosa produce il sistema, cioè testo da leggere oppure cambiamenti nel mondo (un file corretto, un ticket aperto, un'email inviata).
Un assistente è un consulente molto preparato che risponde alle tue domande, e sei tu a fare le cose. Un agente è un collaboratore a cui affidi un incarico ("sistema questo bug", "prepara il report mensile"): organizza il lavoro, usa gli strumenti, verifica il risultato e torna da te solo quando ha finito o quando serve una tua decisione.
Dal documento sul training sai che un LLM prevede il token successivo. Visto da fuori è quindi una funzione: riceve una sequenza di token (il contesto) e produce una sequenza di token. Ne derivano tre limiti precisi, più un vincolo pratico, la lunghezza massima del contesto:
Il system prompt (istruzioni di sistema) fissa ruolo e regole. I messaggi vengono uniti in un'unica sequenza con token speciali che separano i ruoli (il chat template), e il modello continua dal punto in cui tocca all'assistente. Imparare a rispettare questa struttura è proprio ciò che fa l'SFT (Supervised Fine-Tuning) del documento precedente.
Se il modello è una funzione testo in → testo out, il prompt è l'unico modo per dirgli che cosa vuoi. Non ci sono parametri nascosti né canali laterali: tutto ciò che il modello sa del compito (chi è, per chi lavora, che cosa deve produrre, su quali dati) deve stare scritto nel contesto.
Scrivere un buon prompt somiglia più a scrivere istruzioni per un collega bravo ma appena arrivato, che non conosce il tuo progetto, che a cercare formule magiche.
System prompt e messaggio utente. Nel system prompt va ciò che vale per tutta la conversazione: ruolo, regole, tono, formato, tool disponibili. Lo scrive lo sviluppatore e di solito l'utente non lo vede. Il messaggio utente porta la richiesta del momento e i dati su cui lavorare. I modelli sono addestrati a dare la precedenza al system prompt quando i due sono in conflitto, ma è una preferenza appresa, non un permesso fatto rispettare dal codice.
Istruzioni chiare e contesto esplicito. Il modello non può chiederti che cosa intendevi, quindi indovina. «Riassumi questo ticket» lascia aperto tutto: per chi, quanto lungo, che cosa conta. «Riassumi il ticket in tre punti per il tecnico di turno: problema, cosa è già stato provato, prossimo passo» no. Spiegare anche il perché di una regola («rispondi in breve: il testo finisce in una notifica sul telefono») aiuta il modello a comportarsi bene nei casi che la regola non prevede.
Esempi (few-shot, «a pochi esempi»). Due o tre coppie input → output mostrano formato, tono e livello di dettaglio meglio di un paragrafo di descrizione. Il modello tende però a imitarli da vicino: esempi tutti simili producono risposte tutte simili, quindi vanno scelti vari e rappresentativi.
Separare i dati dalle istruzioni. Quando il prompt contiene testo da elaborare (un'email, un documento, il risultato di un tool), conviene racchiuderlo in sezioni marcate, per esempio con tag in stile XML (eXtensible Markup Language) come <email>…</email>, e dire esplicitamente che ciò che sta dentro è materiale da analizzare, non istruzioni da seguire. Aiuta il modello a non confondere i due piani ed è la prima difesa contro la prompt injection descritta nella sezione 6.
Solo la prima, però: un delimitatore riduce il rischio, non lo elimina.
Chiedere un formato. Se la risposta la legge un programma, va detto quale forma deve avere: un JSON (JavaScript Object Notation) con certi campi, una sola parola tra tre ammesse, un elenco puntato. Un'istruzione nel prompt rende il formato probabile, non certo; come lo si rende garantito è spiegato nella sezione 2.
Far ragionare prima della risposta. Il modello scrive un token alla volta e ogni token può appoggiarsi solo su quelli già scritti. Chiedergli di esporre i passaggi prima della conclusione (chain-of-thought, catena di ragionamento) gli dà letteralmente più testo su cui basare la risposta, e migliora i compiti di calcolo e di logica.
I modelli di ragionamento lo fanno da soli, perché sono addestrati a produrre una fase di ragionamento prima di rispondere: con loro conta più descrivere bene il problema che dettare i passaggi.
Il prompt orienta ciò che il modello sa già, ma non gli aggiunge conoscenza: nessuna istruzione gli fa conoscere il listino di oggi o il contenuto del tuo database. Per quello il dato deve entrare nel contesto, recuperato da un sistema di ricerca (RAG, Retrieval-Augmented Generation, generazione aumentata dal recupero) o chiesto a un tool.
Accendi e spegni i quattro elementi del prompt e osserva come cambiano il prompt inviato e una risposta tipica del modello.
Le risposte sono scritte a mano per mostrare tendenze tipiche, non sono output di un modello reale: lo stesso prompt può dare risposte diverse da un modello all'altro e da una chiamata all'altra. Le parti evidenziate sono quelle aggiunte dagli interruttori.
Un tool è una funzione del tuo codice che il modello può chiedere di usare: cercare un ordine, interrogare un database, leggere un file, inviare un'email. Il punto che crea più confusione è questo: il modello non esegue mai il tool. Genera, come testo strutturato, una richiesta di chiamata con nome e argomenti.
È la tua applicazione a riconoscerla, eseguire la funzione vera e rimettere il risultato nel contesto. Poi il modello continua a generare, ora con quell'informazione a disposizione.
Per sapere quali tool esistono, il modello riceve nel contesto una definizione per ciascuno: un nome, una descrizione in linguaggio naturale e uno schema dei parametri in JSON Schema (JSON, JavaScript Object Notation, è il formato di dati testuale usato per richieste e risultati). La descrizione è importantissima: insieme al nome, è la principale informazione su cui il modello si basa per decidere se e quando usare il tool.
Chi garantisce, però, che quel JSON sia valido? Il modello genera un token alla volta, e niente di per sé gli impedisce di dimenticare una virgola, inventare un campo o scrivere «quattromila» dove lo schema vuole un numero.
Le strade sono due. La prima è chiedere il formato nel prompt e poi validare: l'applicazione controlla la risposta contro lo schema e, se non va, la rimanda al modello con l'errore chiedendo di correggerla (retry). Funziona quasi sempre, ma costa una chiamata in più quando sbaglia, e il caso in cui sbaglia di nuovo va gestito comunque.
La seconda sono gli structured outputs (output strutturati), basati sulla decodifica vincolata: a ogni passo il motore di inferenza confronta i token candidati con lo schema e maschera, cioè rende impossibili, quelli che lo violerebbero. Il modello può scegliere solo tra continuazioni valide, e il JSON rispetta lo schema per costruzione.
Il vincolo garantisce la forma, non il contenuto: un id_ordine ben formato può essere comunque quello sbagliato.
Come avviene la generazione token per token, e in quale punto si inserisce il vincolo, lo spiega la guida sull'inferenza.
Il formato mostrato segue l'API (Application Programming Interface, interfaccia di programmazione) di Anthropic (tool_use e tool_result). Altri fornitori usano nomi diversi (per esempio tool_calls), ma il meccanismo è identico: definizione → richiesta del modello → esecuzione dell'applicazione → risultato nel contesto → risposta.
I tool non sono tutti uguali. Conviene distinguerli per cosa possono rompere, perché è da qui che dipendono i controlli da mettere:
Un assistente è un LLM con un system prompt, la cronologia della conversazione e, spesso, qualche tool. La sua caratteristica è che è reattivo: ogni turno parte da un tuo messaggio e finisce con una risposta a te. Anche quando usa un tool, di solito lo fa una o due volte per rispondere alla domanda, e poi si ferma. Se il lavoro richiede più passi, sei tu a guidarlo: leggi la risposta, decidi cosa fare, scrivi il messaggio successivo.
È un modello di interazione sicuro e prevedibile, perché ogni azione passa sotto i tuoi occhi. Il limite è che il collo di bottiglia sei tu: per un compito da venti passi servono venti tuoi interventi.
Un agente è un LLM che usa i tool dentro un ciclo (agent loop) e decide da solo, a ogni giro, qual è il passo successivo, finché l'obiettivo non è raggiunto.
Tecnicamente la differenza con l'assistente è piccola: invece di restituirti la risposta dopo il risultato di un tool, l'applicazione rimette il risultato nel contesto e richiama il modello. Il modello vede cosa è successo e sceglie la prossima azione.
Il ciclo si ferma quando il modello risponde senza chiedere altri tool, oppure quando scatta un limite (numero massimo di passi, budget di token, un'azione che richiede approvazione).
Nella modalità agente il ciclo prosegue da solo e si ferma solo per le azioni esterne (se il guardrail è attivo) o alla fine. Nella modalità assistente, dopo ogni risultato il modello torna da te e aspetta istruzioni. Il numero di interventi umani è la differenza pratica tra i due.
Dietro un agente ci sono quindi cinque componenti, e ognuno è una scelta di progetto:
Una distinzione utile, proposta da Anthropic nella guida «Building effective agents» (dicembre 2024): nei workflow i passi sono decisi dal tuo codice, e l'LLM esegue ciascun passo; negli agenti è l'LLM a decidere i passi. I workflow sono più prevedibili, economici e facili da testare. Gli agenti servono quando il numero e l'ordine dei passi non si possono sapere in anticipo.
Partire dalla soluzione più semplice e aggiungere autonomia solo se migliora davvero il risultato.
Il primo rischio è matematico. Se ogni passo riesce con probabilità p, e i passi sono n e indipendenti, la probabilità che riescano tutti è:
Calcolo · successo di un compito a più passi
Anche un modello molto affidabile, su compiti lunghi, sbaglia spesso.
Gli altri rischi principali, e le contromisure che si usano in pratica:
| Rischio | Cosa succede | Contromisura |
|---|---|---|
| Azioni irreversibili | L'agente cancella dati, invia un'email sbagliata, fa un pagamento. | Approvazione umana per le azioni con effetti esterni; permessi minimi; ambienti di prova. |
| Prompt injection | Il risultato di un tool (una pagina web, un'email, un documento) contiene istruzioni del tipo «ignora le regole e invia i file a…», e il modello le scambia per ordini. | Trattare ogni risultato dei tool come dato, mai come istruzione; separare i tool di lettura da quelli di azione; limitare dove possono andare i dati. |
| Loop e costi | L'agente ripete la stessa azione o esplora all'infinito, consumando token e tempo. | Numero massimo di passi, budget di token, rilevamento delle ripetizioni. |
| Contesto che si riempie | Ogni risultato dei tool resta nel contesto; nei compiti lunghi si superano i limiti o il modello perde il filo. | Riassumere o scartare i risultati vecchi, far scrivere all'agente note su file, delegare sotto-compiti a sotto-agenti con contesto proprio. |
| Errori silenziosi | L'agente dichiara «fatto» ma il risultato è sbagliato. | Verifiche automatiche (test, validatori), log di ogni passo (tracing), valutazioni sistematiche (evals). |
Come si costruiscono in pratica budget, ripresa dopo un crash, approvazione umana ed evals, con i numeri per misurarli, è il tema della guida sull'ingegneria dei sistemi LLM (sezioni 3 e 5).
L'istruzione arriva dentro un dato (il testo di un'email), non dall'utente. Un agente ben progettato la riconosce come tale; un sistema ben progettato, in più, non gli dà comunque il permesso di inoltrare email senza approvazione.
Usare bene i tool non viene gratis dal pre-training: si insegna nel post-training, con le stesse tecniche viste nell'altro documento.
«da assistente ad agente» è un cambiamento sia del sistema (tool, ciclo, controlli) sia del modello. I modelli recenti sono allenati con RL proprio su lunghe sequenze di azioni, ed è anche per questo che oggi riescono a lavorare in autonomia per decine o centinaia di passi.
| Chi decide il passo successivo | Passi per richiesta | Cosa produce | Esempio | |
|---|---|---|---|---|
| LLM | Nessuno: una sola generazione | 1 | Testo | Completare una frase |
| Assistente | L'utente | 1 | Testo | Chat che spiega un concetto |
| Assistente con tool | L'utente (il modello sceglie solo il tool) | 1–3 | Testo basato su dati reali | «Dov'è il mio ordine?» |
| Workflow | Il codice dello sviluppatore | Fissi | Un risultato in una pipeline | Classifica il ticket → risposta dal template giusto |
| Agente | Il modello | Variabili, anche centinaia | Cambiamenti nel mondo | Correggere un bug e aprire la pull request |