
Intelligenza Artificiale
Architetture AI on-premise, LLM locali, RAG, agenti autonomi. Progettazione e sviluppo di sistemi agentici governati.
Scopri →
Admina Enterprise
Governance AI Open Source: audit trail, PII redaction, policy bidirezionali ALLOW/BLOCK/REDACT su ogni chiamata e tool.
Scopri Admina →
Cybersecurity
Sicurezza degli agenti: prompt injection, least privilege, sandboxing, human-in-the-loop, compliance NIS2.
Scopri →
Ricerca & Sviluppo
Ricerca applicata su sistemi agentici, orchestrazione multi-agente e valutazione.
Scopri →Serie in 3 parti. Come funziona davvero un agente AI: (1) anatomia del ciclo · (2) contesto, pattern e multi-agente (dall’8 luglio) · (3) sicurezza e governance (dal 10 luglio). Questa è la parte 1.
Un LLM non è un agente
Un modello linguistico, di per sé, è una funzione senza stato: riceve una sequenza di token e ne produce un’altra. Non “fa” nulla, non ricorda nulla tra una chiamata e l’altra, non osserva il mondo. Un agente è ciò che si ottiene mettendo quel modello dentro un loop che, a partire da un obiettivo, gli permette di invocare strumenti, osservarne i risultati e decidere il passo successivo, finché il compito non è risolto. In una frase: il loop è l’agente. Il modello è solo l’organo decisionale al suo interno.
Questa distinzione sposta l’attenzione dal punto sbagliato (il prompt, il modello) a quello giusto: l’harness, cioè il codice che tiene il modello nel ciclo, esegue le sue richieste, gestisce contesto ed errori e applica le policy. È lì che un sistema agentico diventa affidabile, governabile e sicuro, o non lo diventa.
Il ciclo minimo
Il ciclo parte da un obiettivo (più il system prompt): è l’unico ingresso “umano”. Da lì in avanti l’agente procede da solo. Ridotto all’osso:
messages = [system_prompt, user_goal] # l'obiettivo entra nel contesto
for step in range(MAX_STEPS):
# 1. DECIDE: il modello sceglie la prossima azione
reply = llm(messages, tools=TOOLS, temperature=0)
messages.append(reply)
# 2. TERMINA? il modello segnala di aver finito
if reply.stop_reason == "end_turn":
return reply.text # risposta finale
if reply.stop_reason != "tool_use":
raise UnexpectedStop(reply.stop_reason) # es. max_tokens, refusal
# 3. AGISCE + ESEGUE: l'harness esegue le tool call richieste
results = []
for call in reply.tool_calls:
try:
args = validate(call.arguments, SCHEMA[call.name]) # niente input non validato
results.append(tool_result(call.id, execute(call.name, args))) # side effect nell'ambiente
except ValidationError as e:
results.append(error_result(call, e)) # l'errore torna nel contesto, il modello si corregge
# 4. OSSERVA: il risultato rientra nel contesto
messages.append(tool_results(results))
raise BudgetExceeded("nessuna soluzione entro MAX_STEPS")
Ogni iterazione il modello emette o una risposta finale o una o più tool call. L’harness esegue le chiamate, ne rimette gli esiti nel contesto, e si ricomincia. Il punto cruciale: il modello è senza stato, tutto lo stato del run vive in messages. Non esiste “memoria” magica: c’è solo ciò che, ad ogni giro, viene serializzato nel contesto, a partire dall’obiettivo iniziale.
I componenti, uno per uno
- Obiettivo: il compito da risolvere, l’unico input esterno che avvia il ciclo.
- System prompt / policy: ruolo, vincoli, descrizione degli strumenti, criteri di stop. È il contratto comportamentale, non un suggerimento.
- Tool schema: nome, descrizione e parametri (JSON Schema) di ogni strumento. È l’interfaccia che il modello vede; la qualità di questa descrizione conta quanto il modello.
- Contesto (
messages): l’unica memoria del modello dentro il run. Cresce a ogni passo. - Il modello: decide, non esegue. Produce testo e richieste di azione strutturate.
- L’harness / executor: esegue le tool call, valida gli argomenti, gestisce errori e timeout, applica le policy, traccia tutto. Qui vive la sicurezza.
- La condizione di terminazione: senza, il loop è potenzialmente infinito.
Tool calling, nel dettaglio
Il tool calling è il meccanismo con cui il modello passa dal “dire” al “fare”. Il modello non chiama nulla: emette una struttura (nome dello strumento più argomenti conformi a uno schema) che l’harness interpreta ed esegue. Tre punti tecnici che separano un giocattolo da un sistema serio:
- Validazione degli argomenti. I modelli allucinano parametri: un intero fuori range, un campo mancante, un path arbitrario. Gli argomenti vanno validati contro lo schema prima dell’esecuzione. Se non passano, non si esegue: si rimanda l’errore nel contesto come osservazione, e il modello si auto-corregge al giro successivo. Il messaggio d’errore è parte del ciclo di controllo.
- Chiamate parallele. In un singolo passo il modello può emettere più tool call indipendenti, eseguibili in parallelo (fan-out). Riduce il numero di iterazioni, quindi latenza e costo.
- Strumenti deterministici e non. Una query SQL è deterministica; un altro LLM usato come strumento (un sub-agente, un classificatore) non lo è. Un sub-agente, in particolare, è di fatto un loop annidato dentro il loop.
Terminazione: sapere quando fermarsi
Un loop senza una buona condizione di stop è un modo elegante per bruciare budget. Le condizioni tipiche, in AND/OR tra loro:
end_turn: il modello segnala esplicitamente di aver concluso (risposta finale).- Budget: numero massimo di passi, di token o di tempo.
- No-progress / anti-loop: rilevare che l’agente oscilla (ripete la stessa azione, alterna due stati) e interrompere. È una difesa essenziale: un loop reattivo ingenuo può girare all’infinito.
- Handoff umano: l’agente cede il controllo quando incontra una decisione fuori dal suo mandato.
Un esempio concreto. In Claude Code, il comando /goal <condizione> fonde obiettivo e terminazione: si dà all’agente una condizione di completamento (ad esempio /goal tutti i test in test/auth passano e il lint è pulito) e l’agente prosegue turno dopo turno, in autonomia, finché un modello valutatore leggero (di default Haiku) non conferma che la condizione è soddisfatta; a quel punto si ferma. È esattamente il ciclo di questo articolo, con la condizione di stop resa esplicita e verificata da un secondo modello. Da non confondere con /loop, che ripete un comando a intervalli di tempo: scopo diverso (polling, controlli di stato, task ricorrenti), non un obiettivo da raggiungere.
Questo è lo scheletro. Ma un agente che deve durare più di pochi passi si scontra subito con il limite del contesto, e un agente che tocca dati o azioni reali si scontra con la sicurezza. Sono i temi delle prossime due parti.
La parte 2 (contesto, pattern e multi-agente) arriva l’8 luglio, la parte 3 (sicurezza e governance) il 10 luglio.
