
Mi presento e chiarisco l'approccio didattico: pochi concetti astratti, esempi brevi, attenzione a cosa rende un agente realmente utile e verificabile. Impostiamo anche le aspettative sul livello tecnico richiesto e sul tipo didecisioni che prenderemo durante il percorso.
Spieghiamo cosa costruiremo nel corso, come sono organizzate le sezioni e quali competenze pratiche acquisiremo. Introduciamo il filo logico del percorso: partire da un esempio semplice, comprenderne i componenti, aggiungere tool, memoria, controlli, workflow e osservabilità. Chiariamo prerequisiti, ritmo del corso e criterio principale di successo: saper progettare piccoli agenti che producano output utili e controllabili.
Mostriamo subito un piccolo esempio funzionante per dare concretezza al risultato finale. Osserviamo un agente che riceve un input, interpreta l'obiettivo, usa una logica guidata e restituisce una risposta utile. L'esercizio non punta ancora alla spiegazione completa del codice, ma a far vedere il comportamento atteso, gli input richiesti, l'output prodotto e il criterio con cui capire se l'esecuzione è andata a buon fine.
Definiamo cosa si intende per agente AI e distinguiamo in modo pratico una semplice chat, un workflow deterministico e un sistema agentico. Discutiamo i casi in cui un agente ha senso, per esempio quando deve scegliere tool, usare contesto, gestire passaggi multipli o produrre un risultato strutturato. Indichiamo anche i casi in cui un agente è eccessivo e conviene usare una
funzione, un prompt singolo o un workflow più semplice.
Presentiamo i componenti minimi di un agente: modello, istruzioni, input dell'utente, eventuale contesto e output. Spieghiamo il ruolo di PydanticAI come contenitore che collega il modello linguistico a strumenti, vincoli e tipo di risultato atteso. Acquisiamo il modello mentale necessario per leggere il codice
delle lezioni pratiche successive e per capire dove intervenire quando una risposta non è sufficientemente precisa.
Usiamo l'agente minimo per far produrre al modello una risposta in formato JSON e la validiamo manualmente con un modello Pydantic. Vediamo cosa significa trasformare testo libero in dati tipizzati, quali errori emergono quando mancano campi o i tipi non rispettano lo schema, e perché regex e split sono fragili. La
pratica prepara l'output strutturato di PydanticAI della teoria successiva: prima controlliamo a basso livello con BaseModel e ValidationError, poi capiamo cosa automatizza output_type.
Riprendiamo la validazione manuale con Pydantic vista nella pratica precedente e mostriamo come PydanticAI la semplifica tramite output_type. Capiamo che lo schema Pydantic resta il contratto dell'output, ma parsing, validazione e retry vengono integrati nel ciclo dell'agente. Restiamo concentrati su un solo passaggio: da testo JSON validato a mano a result.output come oggetto tipizzato pronto da usare.
Prendiamo lo schema Pydantic della validazione manuale e lo passiamo direttamente all'agente con output_type. Confrontiamo la versione precedente, basata su JSON grezzo e model_validate_json, con la versione PydanticAI in cui result.output è già un oggetto tipizzato. L'obiettivo è vedere meno codice di gestione, nessun parsing manuale e un output riutilizzabile campo per campo.
Spieghiamo perché i tool trasformano un agente da generatore di testo a componente operativo. Chiarifichiamo che un modello linguistico non dovrebbe inventare dati, eseguire azioni non disponibili o fingere accesso a sistemi esterni. I tool permettono invece di recuperare informazioni, calcolare risultati, interrogare servizi e applicare logica applicativa. Impariamo quando introdurre un tool e quali responsabilità lasciare al codice invece che al modello.
Guidiamo la creazione di un primo tool collegato all'agente. Definiamo una funzione esterna con input chiari, output leggibile e responsabilità limitata, poi la integriamo nel flusso dell'agente. L'esercizio mostra come il modello decide di usare il tool, quali dati gli vengono passati e come il risultato torna nella risposta finale. Il completamento richiede che il tool venga invocato
correttamente e produca un effetto verificabile.
Presentiamo i criteri per progettare più tool senza creare confusione. Trattiamo nomi espliciti, descrizioni operative, limiti di responsabilità, gestione degli errori, scelta automatica dello strumento più adatto e ruolo dei model settings come temperature, chiamate tool parallele e reasoning budget quando supportato dal modello. Impariamo a evitare tool troppo generici, sovrapposti o fragili, e a ragionare su come un agente può combinare recupero dati, trasformazioni e controlli mantenendo il comportamento comprensibile.
Realizziamo un mini progetto in cui l'agente consulta dati, li elabora e restituisce una risposta utile. Colleghiamo più passaggi pratici: definizione del problema, scelta dei tool, configurazione dei model settings, preparazione degli input, interpretazione del risultato e formattazione dell'output finale. Il criterio di completamento è avere un agente che non si limita a conversare, ma usa dati o funzioni esterne in modo trasparente, controllabile e ripetibile.
Distinguiamo memoria conversazionale, stato di sessione e persistenza. Spieghiamo che non tutta la cronologia è utile e che una memoria efficace deve conservare informazioni rilevanti, aggiornabili e verificabili. Impariamo a ragionare su cosa salvare, per quanto tempo, con quale struttura e con quali rischi.Prepariamo il terreno per implementare una memoria semplice senza confondere contesto temporaneo e dati duraturi.
Implementiamo una memoria semplice distinguendo due canali: cronologia conversazionale tramite message_history e stato di sessione tipizzato tramite deps/deps_type. Creiamo un profilo di sessione, lo passiamo all'agente a ogni run, manteniamo la cronologia tra turni e la persistiamo su file. L'output atteso è un agente capace di usare sia informazioni dette nel dialogo sia dati stabili forniti dal codice, senza mescolare profilo e cronologia.
Introduciamo in modo essenziale il problema delle cronologie che crescono troppo: costi, latenza e rumore nel contesto passato al modello. Vediamo due strategie semplici e pragmatiche: finestra mobile sugli ultimi messaggi e sintesi della
parte esclusa. La teoria resta breve e prepara direttamente la pratica successiva, mostrando solo gli snippet necessari rispetto al progetto con message_history e deps.
Estendiamo l'agente con memoria della lezione precedente aggiungendo una gestione controllata delle chat lunghe. Di default il programma passa al modello solo una finestra mobile degli ultimi messaggi, mantenendo comunque la cronologia completa su file. Con un'opzione da riga di comando, quando la cronologia supera la finestra, i messaggi esclusi vengono sintetizzati e inseriti come primo messaggio della finestra mobile. L'obiettivo è ridurre il contesto passato al modello senza perdere del tutto il filo storico.
Introduciamo guardrail e controlli come strumenti per ridurre errori, risposte incoerenti e comportamenti indesiderati. Spieghiamo quali controlli possono essere espressi nelle istruzioni, quali conviene implementare nel codice e quali richiedono validazione o normalizzazione dell'output. Impariamo a distinguere sicurezza, qualità e coerenza funzionale, e a progettare regole semplici che non blocchino inutilmente l'esperienza ma rendano l'agente più affidabile.
Applichiamo due controlli concreti a un mini agente riassuntore: validazionedell'input prima della chiamata al modello e validazione dell'output strutturato dopo la risposta. Eseguiamo casi validi e non validi, osserviamo input respinti a monte, conteggio parole normalizzato in codice e retry quando il riassunto supera il limite. Il risultato atteso è un comportamento più prevedibile e messaggi di errore leggibili.
Presentiamo il progetto che chiude il blocco sui singoli agenti prima di introdurre LangChain: una chat CLI che usa Tavily come tool di ricerca online, risponde sulla base delle fonti trovate, conserva le fonti numerate in memoria, usa cronologia conversazionale, output Pydantic, guardrail sulle citazioni e log
locale.
Costruiamo l'agente conversazionale end-to-end in un'unica pratica. Il progetto include README completo, input validato, Agent PydanticAI con tool Tavily, memoria della cronologia, memoria delle fonti su file, comando :sources, output con citazioni [1][2], output_validator e log locale.
Collochiamo LangChain rispetto a PydanticAI e agli agenti costruiti finora. Spieghiamo quando un framework di composizione aiuta davvero: workflow con più passaggi, integrazioni, strumenti riusabili, orchestrazione e osservabilità.
Chiariamo anche i casi in cui LangChain sarebbe eccessivo rispetto a una soluzione più diretta. Impariamo a scegliere lo strumento in base al problema, non alla moda tecnologica.
Costruiamo un primo workflow semplice con LangChain. Definiamo i passaggi minimi, colleghiamo input, modello e trasformazione dell'output, quindi eseguiamo il flusso con un caso concreto. L'obiettivo pratico è vedere come una catena o
composizione renda esplicito il percorso dei dati. Il completamento richiede che lo stesso input attraversi i passaggi previsti e produca un risultato finale leggibile e verificabile.
Approfondiamo come ragionare su chains, tool e composizione modulare in LangChain. Presentiamo RunnableLambda, RunnableParallel, tool chiamati esplicitamente, parsing strutturato e criteri per assegnare a ogni nodo una responsabilità chiara. Impariamo a distinguere cosa deve interpretare il modello
e cosa deve restare in codice verificabile. Prepariamo il mini workflow agentico successivo, in cui la composizione diventa una scelta architetturale concreta.
Realizziamo un workflow LangChain che qualifica richieste di automazione AI. Puliamo l'input, estraiamo in parallelo tipo di automazione, integrazioni e rischio dati, invochiamo tool per recuperare policy e stimare complessità, poi produciamo una scheda Pydantic tipizzata. L'esercizio evidenzia quando usare
sotto-chain, quando usare tool deterministici e come mantenere il processocomprensibile senza anticipare grafi o agenti autonomi.
Compattiamo i concetti essenziali di osservabilità e test degli agenti. Distinguiamo tracing e testing, introduciamo BM25 come retrieval deterministico, LCEL come composizione del workflow e PydanticAI come livello agente tipizzato. Gli snippet preparano il progetto pratico: retriever LangChain, chain con Runnable, agente con output Pydantic, Agent.override, TestModel e FunctionModel.
Costruiamo un mini RAG su una knowledge base markdown locale. Usiamo LangChain per caricare i documenti, creare un BM25Retriever e comporre con LCEL il workflow
retrieval -> prompt -> agente; usiamo PydanticAI per la risposta tipizzata e un tool semplice. Completiamo con test deterministici su BM25 e con due modalita' CLI senza API: TestModel per la chain completa e FunctionModel per la tool call simulata.
Chiariamo la differenza tra un agente con molti tool e un sistema multi-agente. Introduciamo i pattern PydanticAI di agent delegation, programmatic handoff e graph-based control flow, il ruolo del judge/evaluator, il pattern minimale
researcher -> judge -> writer e i tradeoff di costo, latenza e diagnostica. Capiamo quando aggiungere un router e quando invece mantenere un flusso più semplice.
Costruiamo un sistema multi-agente con PydanticAI e pydantic-graph. Il flusso parte da una domanda, passa da researcher_agent, judge_agent e writer_agent, e torna al researcher quando le fonti locali simulate sono insufficienti. Usiamo output Pydantic tipizzati, stato condiviso, limite massimo di tentativi e un tool di web search deterministico su file JSON locale.
Introduciamo LangGraph come strumento per workflow e agenti stateful. Spieghiamo StateGraph, stato, nodi, edge, conditional edges, routing, orchestrator-workers, evaluator-optimizer, agents as tools e supervisor. Il confronto con PydanticAI e pydantic-graph ci aiuta a scegliere lo strumento giusto in base alla topologia del problema.
Realizziamo il progetto finale avanzato: un sistema multi-agente di assistenza clienti/e-commerce con LangGraph. Il workflow usa StateGraph, stato condiviso, routing condizionale, specialisti per ordini, policy e reclami, resolution agent, compliance judge, response editor e human review simulata. I dati sono locali e i
tool sono puri, senza database, invio email reale o servizi esterni obbligatori.
Questo corso ti guida nella costruzione di agenti AI pratici con Python, partendo dai concetti essenziali fino a sistemi multi-agente con grafi di controllo complessi, architettati per la delegazione delle responsabilità a ciascun agente specialista.
Imparerai a distinguere chat, workflow e agenti, a creare un primo agente con PydanticAI, a progettare istruzioni affidabili, output strutturati e tool esterni, e a introdurre memoria, guardrail e controlli di qualità.
Integrerai poi i componenti base in un agente singolo completo, prima di vedere quando usare LangChain, come comporre workflow semplici e come osservare il comportamento del sistema con tracing, diagnosi e test pratici. Il percorso prosegue con una sezione avanzata su sistemi multi-agente, pydantic-graph e LangGraph, in cui apprenderai:
come realizzare un sistema agentico RAG che fornisce risposte sulla base di contenuti ottenuti da una ricerca sul web
come realizzare un sistema agentico per la gestione automatica dell'assistenza ai clienti
Lavorerai su esempi via via più realistici, in cui ogni componente dell'agente, dalle istruzioni ai tool, dalla memoria ai controlli, ha un ruolo verificabile.
Arriverai a progettare flussi con ruoli specializzati, judge/evaluator, stato condiviso, routing condizionale, loop controllati e human review simulata, mantenendo infrastruttura locale e didattica.
Il corso non richiede esperienza preliminare con framework agentici, ma si appoggia a una conoscenza di base di Python.
Tutti i marchi e i loghi eventualmente citati appartengono ai rispettivi proprietari e sono utilizzati a solo scopo didattico, senza alcuna affiliazione o sponsorizzazione implicita.