v1.2 — Edizione 2026. Un corso audio approfondito sul framework di orchestrazione LangChain v1.0. Costruisci applicazioni AI multi-agente affidabili con tool calling standardizzato, output strutturati, validazione human-in-the-loop e context engineering avanzato.
Esploriamo perché LangChain si è evoluto da un semplice wrapper a un framework di orchestrazione completo. Scoprirai la storia dello sviluppo di applicazioni LLM e come il rilascio della v1.0 standardizza le interazioni con i modelli.
3m 54s
2
L'Astrazione Unificata dell'Agente
Ci immergiamo nella funzione principale create_agent che unifica le precedenti astrazioni di LangChain. Scoprirai come il ciclo ReAct opera dietro le quinte per gestire il ragionamento del modello e l'esecuzione dei tool.
3m 16s
3
Standardizzare il Caos
Esaminiamo come LangChain standardizza le interazioni con i modelli tra diversi provider. Imparerai come inizializzare i modelli di chat e passare senza problemi tra OpenAI, Anthropic e Google.
3m 17s
4
Il Linguaggio Universale degli LLM
Analizziamo l'unità fondamentale del contesto in LangChain: i Messages. Imparerai come strutturare i messaggi System, Human, AI e Tool per costruire cronologie di conversazione robuste.
3m 40s
5
Potenziare gli Agenti con i Tool
Esploriamo come dotare i tuoi modelli di azioni utilizzando il decoratore @tool. Scoprirai come i type hints e le docstring vengono convertiti automaticamente in JSON schema precisi per il modello.
3m 46s
6
Iniettare il Contesto nei Tool
Approfondiamo come passare informazioni di runtime direttamente ai tuoi tool senza esporle all'LLM. Imparerai a utilizzare il parametro ToolRuntime per configurazioni sicure tramite dependency injection.
3m 47s
7
Persistenza a Livello di Thread
Affrontiamo il tema della memoria a breve termine e di come mantenere la cronologia delle conversazioni. Imparerai come collegare i checkpointers al tuo agente per consentire alle conversazioni di essere messe in pausa, riprese e ricordate.
3m 57s
8
Comprimere il Contesto con i Middleware
Esploriamo come evitare che le lunghe conversazioni mandino in crash il tuo modello. Imparerai a utilizzare il SummarizationMiddleware per comprimere automaticamente i vecchi messaggi e risparmiare token.
3m 32s
9
Formati Dati Garantiti
Discutiamo di come forzare i modelli linguistici a restituire strutture dati rigorose e prevedibili. Scoprirai la differenza tra ProviderStrategy e ToolStrategy per la generazione di modelli Pydantic.
3m 24s
10
Intercettare il Ciclo dell'Agente
Introduciamo il paradigma dei middleware, che ti offre un controllo chirurgico sull'esecuzione del tuo agente. Imparerai a utilizzare gli hook wrap-style e node-style per intercettare le chiamate al modello.
3m 17s
11
Context Engineering Dinamico
Ci immergiamo nel context engineering generando dinamicamente i system prompt. Imparerai a utilizzare i middleware per alterare le istruzioni in base al ruolo dell'utente corrente e all'ambiente.
4m 03s
12
AI Sicura con Guardrail Deterministici
Mettiamo in sicurezza i nostri agenti contro le fughe di dati utilizzando i middleware integrati. Imparerai come applicare il PIIMiddleware per oscurare automaticamente le informazioni sensibili prima che raggiungano il modello.
3m 50s
13
In Pausa per l'Approvazione Umana
Esploriamo l'esecuzione di tool ad alto rischio aggiungendo un essere umano al ciclo. Imparerai come interrompere l'esecuzione di un agente per approvare, modificare o rifiutare azioni sensibili.
4m 08s
14
Feedback dell'Agente in Tempo Reale
Ci immergiamo nello streaming per migliorare drasticamente l'esperienza utente. Imparerai a interpretare le stream modes per visualizzare i token dell'LLM dal vivo insieme agli aggiornamenti personalizzati sull'esecuzione dei tool.
3m 41s
15
Persistenza Cross-Session
Esploriamo la memoria a lungo termine per costruire agenti che conoscano veramente i loro utenti. Imparerai a utilizzare gli store di LangGraph per salvare documenti JSON attraverso conversazioni completamente diverse.
3m 45s
16
Il Paradigma Multi-Agente
Spieghiamo perché i singoli agenti falliscono e introduciamo l'architettura Subagents. Imparerai come un agente supervisore principale coordina i subagents come context windows isolate per prevenire il sovraccarico di token.
4m 06s
17
Agenti State-Driven
Esploriamo come gli agenti possano alterare dinamicamente il loro comportamento. Imparerai il pattern Handoffs per trasferire il controllo e il pattern Skills per caricare prompt specializzati su richiesta.
3m 53s
18
Workflow Personalizzati e Router
Usciamo dal ciclo standard dell'agente. Imparerai a utilizzare LangGraph per costruire architetture di routing personalizzate, mescolando logica deterministica con ragionamento agentico non deterministico.
3m 44s
19
Comunicazione Agent-to-Agent
Esploriamo l'endpoint LangSmith A2A. Imparerai come agenti distribuiti su server completamente diversi possano conversare nativamente utilizzando il protocollo A2A RPC di Google.
4m 22s
20
Il Futuro è MCP
Guardiamo al futuro con il Model Context Protocol, che standardizza il modo in cui gli agenti accedono ai tool esterni. Imparerai come connettere server MCP remoti al tuo agente utilizzando i transport standard.
4m 44s
Episodi
1
L'Era dell'Orchestrazione
3m 54s
Esploriamo perché LangChain si è evoluto da un semplice wrapper a un framework di orchestrazione completo. Scoprirai la storia dello sviluppo di applicazioni LLM e come il rilascio della v1.0 standardizza le interazioni con i modelli.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 1 di 20. È incredibilmente facile creare il prototipo di un agente AI, ma è notoriamente difficile costruirne uno abbastanza affidabile da mandare in produzione. Il divario tra una bella demo fatta nel weekend e un'applicazione enterprise-grade è enorme. La soluzione per colmare questo divario è quella che chiamiamo l'Era dell'Orchestrazione.
Innanzitutto, chiariamo un malinteso molto comune. Spesso le persone confondono LangChain con un model provider. LangChain non addestra, non fa hosting e non fa serving di Large Language Models. È l'orchestration layer che si posiziona direttamente sopra questi modelli. Pensalo come il centro di controllo che gestisce il modo in cui la tua applicazione interagisce con qualsiasi modello tu scelga di usare.
Per capire perché un orchestration layer è necessario, dobbiamo guardare a come si è evoluta la tecnologia. Nel 2022, interagire con un language model era semplice. Inviavi una string di testo e ricevevi una string di testo in risposta. Delle semplici prompt chain erano sufficienti per fare il lavoro. Non ti serviva un framework pesante per gestire un workflow di base text-in, text-out. Potevi facilmente scrivere uno script in cui l'output del prompt A veniva semplicemente incollato nel prompt B.
Ma ora che attraversiamo il 2025 e guardiamo al 2026, il panorama è completamente diverso. I modelli non elaborano più solo plain text. Acquisiscono e generano blocchi multimodali complessi. Una singola interazione potrebbe includere il routing di un user prompt, l'attivazione di una tool call esterna, l'elaborazione di un'immagine e la restituzione di un blocco di dati strutturato. Un modello potrebbe restituire una richiesta per una database lookup proprio accanto a un riepilogo testuale. Se il codice della tua applicazione deve ispezionare manualmente ogni singola response per capire se si tratta di una string, di una tool invocation o di un file immagine, la tua codebase diventerà rapidamente un disastro fragile e non manutenibile.
Ecco il punto chiave. Passare l'esatto context a un modello nel momento esatto è molto più difficile che scegliere semplicemente il modello più potente sul mercato. Puoi fare lo swap con il reasoning engine più intelligente disponibile, ma se riceve dati disordinati e non standardizzati, l'intera interazione fallirà.
Ecco perché LangChain si è evoluto da una semplice chaining library a un orchestration layer standardizzato per la sua release 1.0. Fornisce un message format standard che funziona in modo coerente con tutti i principali model provider. Invece di scrivere una parsing logic custom per ogni diversa API, usi una struttura uniforme. Standardizzando il message format, LangChain garantisce che una tool call di un provider abbia esattamente lo stesso aspetto nel tuo codice di una tool call di un provider concorrente. Definisci una sequenza in cui entra uno user message, l'orchestration layer lo normalizza, lo invia al modello, cattura la response multimodale e traduce quella response in un formato standard che la tua applicazione può effettivamente usare. Scrivi la tua application logic una sola volta, e l'orchestration layer si occupa della traduzione.
Il modello in sé non è più l'intera applicazione, è semplicemente il reasoning engine, e l'orchestration layer è ciò che determina se quel motore risolve effettivamente il tuo business problem.
Se vuoi aiutarci a continuare a creare questi episodi, puoi supportare lo show cercando DevStoriesEU su Patreon. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
2
L'Astrazione Unificata dell'Agente
3m 16s
Ci immergiamo nella funzione principale create_agent che unifica le precedenti astrazioni di LangChain. Scoprirai come il ciclo ReAct opera dietro le quinte per gestire il ragionamento del modello e l'esecuzione dei tool.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 2 di 20. E se potessi sostituire l'intero e complesso reasoning loop con una singola function call di dieci righe? Passi ore a scrivere custom parser e while-loop solo per far sì che un language model attivi una funzione in modo affidabile. La Unified Agent Abstraction è l'architettura che ti libera da questo problema.
Per capire perché questo sia importante, dobbiamo chiarire un equivoco comune riguardante le versioni precedenti del framework. Nella versione zero punto x, gli sviluppatori dovevano navigare in un labirinto di classi agent specifiche. Avevi conversational agent, zero-shot agent e complesse custom chain. Se stai aggiornando il tuo codice, puoi dimenticare tutto questo. La Unified Agent Abstraction sostituisce completamente tutte le vecchie chain e i legacy agent. Fornisce un unico entry point chiaro e standardizzato tramite una funzione chiamata semplicemente create agent.
Questa funzione esiste per gestire il ReAct loop. ReAct sta per Reason and Act. Quando un utente pone una domanda complessa, un language model non può semplicemente eseguire del codice. Deve ragionare sul problema, decidere di intraprendere un'azione, produrre in output del testo che richieda tale azione, e quindi attendere un'observation prima di poter ragionare di nuovo. Gestire manualmente questo loop è noioso. Devi fare il parsing del testo generato dal modello, mapparlo a una funzione locale, eseguire quella funzione, formattare l'output, darlo di nuovo in pasto al modello e valutare se il task è terminato. La funzione create agent astrae l'intero processo di orchestrazione.
Vediamo una semplice implementazione utilizzando un tool per controllare il meteo. Per prima cosa, definisci il tuo tool specifico, magari una funzione chiamata get weather che prende in input il nome di una città. Successivamente, inizializzi il language model che hai scelto. Poi arriva l'astrazione. Chiami la funzione create agent e le passi tre argomenti. Le passi il tuo language model, una lista contenente il tuo tool get weather, e un system prompt che detta le regole per l'agent. Questa singola chiamata restituisce un oggetto agent eseguibile. Infine, invochi questo oggetto con una user query, chiedendo il meteo attuale a Londra.
Ecco l'aspetto fondamentale dell'execution flow. Quando invochi l'agent, stai avviando il ReAct loop. L'agent invia la query e le descrizioni dei tool al modello. Il modello decide di aver bisogno di dati in tempo reale e produce in output una tool call standardizzata. L'astrazione dell'agent intercetta automaticamente questa chiamata. Esegue il tuo tool get weather con l'argomento Londra, prende i dati di temperatura risultanti e li restituisce al modello come una nuova observation. Il modello valuta questi dati, si rende conto di avere la risposta alla user query e genera una risposta finale.
Non hai scritto un singolo loop, e non hai scritto un output parser. Hai fornito solo i tool, il modello e le istruzioni. La potenza della Unified Agent Abstraction risiede nello stabilire un rigoroso confine architetturale. Isola completamente i meccanismi del reasoning loop, consentendoti di dedicare tutto il tuo impegno ingegneristico al perfezionamento della qualità dei tuoi tool e alla chiarezza dei tuoi prompt.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
3
Standardizzare il Caos
3m 17s
Esaminiamo come LangChain standardizza le interazioni con i modelli tra diversi provider. Imparerai come inizializzare i modelli di chat e passare senza problemi tra OpenAI, Anthropic e Google.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 3 di 20. I diversi provider di modelli hanno API estremamente diverse, il che significa che provare un nuovo modello di solito ti costringe a riscrivere metà della tua applicazione. Finisci per essere vincolato a un vendor solo perché il costo tecnico per cambiare è troppo elevato. Standardizzare questo caos è esattamente l'argomento di questo episodio.
Prima di entrare nel dettaglio di come LangChain risolve questo problema, è utile chiarire un equivoco comune. Se hai lavorato con i primi language models, probabilmente hai familiarità con le classi LLM legacy che accettano una singola stringa di raw text come input. I moderni chat models sono diversi. Richiedono rigorosamente una sequenza strutturata di messaggi, in cui a ciascun messaggio è associato un ruolo specifico, come system, human o AI. Tutto ciò di cui parleremo ora si applica a questi moderni chat models, non a quelli legacy di text completion.
Quando sviluppi un'applicazione, hardcodare un provider specifico crea immediatamente un vendor lock-in. Per eliminare questa dipendenza, LangChain introduce una singola factory function chiamata init chat model. Pensala come un traduttore universale per inizializzare i client di intelligenza artificiale. Invece di importare una classe specifica per OpenAI, un'altra per Anthropic e un'altra ancora per Google, ti affidi esclusivamente a questa funzione.
Ecco il punto chiave. La funzione init chat model utilizza una semplice sintassi a stringa per sapere cosa costruire. Fornisci una stringa formattata con il nome del provider, seguito da due punti e dalla versione specifica del modello. Considera un agent attualmente in esecuzione sul GPT-5 di OpenAI. Inizializzi il tuo modello semplicemente passando la stringa openai due punti gpt-5.
Ora, supponi che Anthropic rilasci un nuovo modello che gestisce meglio la code generation e che tu voglia testarlo. Dato che hai usato la funzione init chat model, non devi toccare la logica del tuo agent. Non devi importare un nuovo package client. Devi semplicemente cambiare quella singola stringa di inizializzazione in anthropic due punti claude-sonnet-4-6. LangChain risolve dinamicamente la stringa e carica la corretta classe di integrazione sottostante.
Questo gestisce il modello in sé, ma i provider non concordano nemmeno sulle impostazioni di configurazione. Un'API potrebbe aspettarsi un parametro chiamato max sampled tokens, mentre un'altra si aspetta max length. La funzione init chat model risolve questo problema accettando parametri standard. Quando inizializzi il tuo modello, puoi passare argomenti come temperature o max tokens direttamente alla funzione.
Se imposti la temperature a zero punto due e i max tokens a mille, LangChain mappa questi termini generici alle esatte chiavi del payload richieste dal provider che hai specificato nella tua stringa. Configuri il tuo modello una sola volta usando la terminologia standard, e il framework lo traduce per l'API di destinazione.
Separando il codice della tua applicazione dai dettagli di implementazione specifici del vendor, ottieni agilità architetturale, permettendoti di valutare modelli concorrenti in pochi secondi anziché in giorni.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
4
Il Linguaggio Universale degli LLM
3m 40s
Analizziamo l'unità fondamentale del contesto in LangChain: i Messages. Imparerai come strutturare i messaggi System, Human, AI e Tool per costruire cronologie di conversazione robuste.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 4 di 20. Se continui a passare string in plain text ai tuoi language model, stai limitando pesantemente le tue applicazioni. Le string in plain text fanno perdere il contesto. Non possono contenere in modo sicuro riferimenti a immagini, risultati dell'esecuzione di tool o ruoli di interazione distinti. Per risolvere questo problema, LangChain utilizza oggetti messaggio standardizzati, che fungono da linguaggio universale degli LLM.
Un messaggio in LangChain è una struttura dati che contiene un ruolo specifico, il payload e dei metadati opzionali. Diversi API provider gestiscono i ruoli di conversazione e gli input multimodali in modo diverso nelle loro API raw. LangChain astrae questa frizione in quattro classi distinte.
La prima è il SystemMessage. Questo oggetto stabilisce le regole di background, la persona o i vincoli stringenti per l'interazione. Poi c'è lo HumanMessage, che rappresenta il prompt dell'utente o i file caricati. Quindi abbiamo l'AIMessage, che cattura la risposta generata dal modello. Infine, c'è il ToolMessage. Questo oggetto riporta specificamente al modello il risultato dell'esecuzione di una funzione esterna, separando nettamente il raw input dell'utente dai dati fattuali generati dal sistema.
Puoi orchestrare le conversazioni passando al modello un array di questi oggetti messaggio. Puoi costruire manualmente questo array per modellare l'output. Per prima cosa, crei una list e inserisci un SystemMessage che assegna al modello il ruolo di un esperto di poesia con una formattazione rigorosa. In secondo luogo, aggiungi in append uno HumanMessage che richiede un haiku sulle migrazioni di database. Ecco il punto chiave. Non devi aspettare che il modello generi la risposta successiva. Puoi istanziare manualmente un AIMessage contenente una specifica riga di apertura, e iniettarlo nell'array subito dopo il prompt umano. Quando passi questo intero array al modello, lui interpreta il tuo AIMessage iniettato come un suo comportamento passato. Continuerà l'haiku senza interruzioni esattamente dal tuo punto di partenza, attenendosi alla struttura che gli hai imposto.
Quando finalmente ricevi un AIMessage di ritorno dal modello, devi estrarre ciò che ha effettivamente prodotto. Gli sviluppatori spesso confondono l'attributo raw content con il payload parsato. Ogni oggetto messaggio ha una property content. Tuttavia, questo attributo raw content riflette direttamente qualsiasi cosa lo specifico provider LLM abbia restituito. A seconda del provider del modello e del prompt, potrebbe trattarsi di una semplice text string, oppure di una list altamente annidata di dizionari contenenti chunk di testo misti, URL di immagini e identificatori di tool. Fare il parsing manuale di tutto questo rende il tuo codice incredibilmente fragile.
Invece di leggere il raw content, dovresti usare la property content blocks. La property content blocks è la rappresentazione standardizzata e strettamente tipizzata del payload del messaggio in LangChain. Quando leggi dai content blocks, LangChain traduce la risposta specifica del provider in una list uniforme di oggetti block. Puoi iterare su questa list in modo sicuro. Per prima cosa controlli se un block è un text block, e se lo è, estrai il payload testuale. Successivamente controlli se è un tool call block, ed estrai gli argomenti. Costruire la tua logica di parsing attorno alla property standardizzata content blocks è l'unico modo per garantire che la tua applicazione rimanga completamente disaccoppiata dai formati di risposta mutevoli dei singoli provider di modelli.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
5
Potenziare gli Agenti con i Tool
3m 46s
Esploriamo come dotare i tuoi modelli di azioni utilizzando il decoratore @tool. Scoprirai come i type hints e le docstring vengono convertiti automaticamente in JSON schema precisi per il modello.
Ciao, sono Alex di DEV STORIES DOT EU. Framework di orchestrazione LangChain v1.0, episodio 5 di 20. Un agente IA senza accesso al mondo esterno è solo un generatore di testo. Per trasformarlo in un sistema che faccia davvero il suo lavoro, devi dargli delle mani. Oggi parliamo di come potenziare gli agenti con i tool, in particolare usando il decoratore at-tool.
Un tool in LangChain è un ponte tra il motore di ragionamento di un modello linguistico e i tuoi sistemi esterni. Ma qui c'è un malinteso comune. Molti sviluppatori danno per scontato che il modello linguistico in qualche modo analizzi la logica all'interno della loro funzione Python per capire come usarla. Non è così. Il modello linguistico non vede mai il tuo codice Python. Vede solo uno schema che descrive la funzione.
Per creare un tool, scrivi una funzione Python standard e ci metti sopra direttamente il decoratore at-tool. Questo decoratore fa una cosa fondamentale. Ispeziona la signature della tua funzione, estrae il nome della funzione, legge i type hint per ogni parametro e analizza la docstring. Prende tutti questi metadati e li raggruppa in un formato strutturato che il modello linguistico può effettivamente leggere.
Dato che il modello legge solo questo schema generato, la precisione nel tuo codice è fondamentale. Vediamo uno scenario. Supponiamo che tu scriva una funzione chiamata search database. Se le dai una docstring debole che dice solo, searches the database, e tralasci completamente i type hint, il modello linguistico naviga alla cieca. Non sa che tipo di database sia, e non sa quali argomenti fornire. Potrebbe provare a passare un'intera frase colloquiale come query di ricerca, facendo crashare la tua funzione Python durante l'esecuzione.
Ecco il punto chiave. Quando usi il decoratore at-tool, devi scrivere le tue docstring per il modello linguistico, non per lo sviluppatore umano. Invece di una descrizione vaga, scrivi un'istruzione chiara, come, cerca nel database clienti tramite indirizzo email per recuperare lo storico delle fatturazioni.
Poi, applichi dei type hint rigorosi ai tuoi parametri di input. Specifichi che l'argomento email deve essere una string. Potresti persino aggiungere una descrizione all'argomento stesso. Ogni informazione di tipo che aggiungi dà al modello linguistico un limite più preciso su cosa gli è permesso generare.
Quando passi questo tool appena decorato a un agente, l'agente legge lo schema dettagliato prima di fare qualsiasi altra cosa. Quando un utente chiede di un rimborso cliente, l'agente scansiona i tool disponibili e riconosce che il tool search database è esattamente quello giusto, basandosi sulla tua docstring precisa. Grazie al tuo type hint rigoroso, sa esattamente come formattare l'argomento. Estrae la string dell'email dal prompt dell'utente, ferma la generazione del testo e produce un tool call.
LangChain intercetta quel tool call. Prende la string dell'email generata dal modello, la passa alla tua funzione Python sottostante ed esegue il codice. La tua funzione parla col database, recupera lo storico delle fatturazioni e restituisce i dati grezzi direttamente a LangChain. LangChain quindi passa quei dati di nuovo all'agente come observation. L'agente riprende il suo processo di pensiero, ma ora ha i dati reali che gli hai appena fornito.
La capacità di agire del modello linguistico è completamente vincolata alla qualità della signature della tua funzione. Tratta le tue docstring e i tuoi type hint come rigorosi vincoli ingegneristici, perché per il modello linguistico sono le uniche istruzioni che esistono. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
6
Iniettare il Contesto nei Tool
3m 47s
Approfondiamo come passare informazioni di runtime direttamente ai tuoi tool senza esporle all'LLM. Imparerai a utilizzare il parametro ToolRuntime per configurazioni sicure tramite dependency injection.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 6 di 20. Se ti affidi a un language model per passare correttamente un token di autenticazione o una user identity a un tool di database, ti stai esponendo a una grave violazione della sicurezza. Il modello non sa chi sia l'utente corrente e non dovresti certo fidarti a farglielo indovinare. Hai bisogno di un modo per passare dati sensibili del backend direttamente ai tuoi tool, bypassando completamente il modello. Questo è esattamente ciò che risolve l'Injecting Tool Context.
Quando crei un tool, alcuni argomenti devono essere generati dal modello, come una search string o un intervallo di date. Altri argomenti sono strettamente per la tua infrastruttura di backend. È qui che entra in gioco l'oggetto ToolRuntime. Ti permette di iniettare una configurazione statica in un tool esattamente al momento della sua esecuzione.
Potresti pensare di poter semplicemente passare un dictionary di configurazione come un normale argomento del tool e dire al prompt di ignorarlo. Non farlo. Quando definisci un parametro chiamato config o runtime nella funzione del tuo tool, LangChain li tratta come keyword riservate. Li nasconde intenzionalmente dallo schema del tool che viene inviato al language model. Il modello non li vede mai. Vede solo gli argomenti che è tenuto a fornire. Questo significa che il modello non può allucinare una configurazione falsa o tentare di aggirare i tuoi limiti di sicurezza.
Considera uno scenario concreto. Stai creando un tool get account info per un'applicazione bancaria. Il tool richiede uno user ID per recuperare i record corretti dal database. Se il modello fornisce questo ID, una prompt injection astuta potrebbe ingannare il modello e fargli richiedere dati per un cliente completamente diverso. Invece, progetti la funzione del tuo tool in modo che accetti due argomenti. Il primo è l'account type, che verrà fornito dal modello. Il secondo è un argomento chiamato runtime.
All'interno del codice principale della tua applicazione, prima che il tool venga invocato, popoli questo oggetto runtime. Nello specifico, usi la proprietà runtime punto context. Inserisci lo user ID effettivo e autenticato della persona che effettua la richiesta direttamente in questo context. Potresti anche inserirci una connessione al database attiva o l'indirizzo di un endpoint regionale.
Il modello valuta la richiesta dell'utente e decide di chiamare il tool get account info. Analizza lo schema, vede che deve fornire un account type e restituisce la parola savings. Non restituisce nient'altro. LangChain intercetta questa chiamata di esecuzione. Prende l'account type dal modello, lo combina in modo trasparente con il runtime context del tuo backend ed esegue la funzione Python. All'interno della funzione, estrai lo user ID dal context ed esegui la tua query al database in modo sicuro.
Questo meccanismo ti offre una dependency injection sicura. Puoi iniettare qualsiasi cosa serva al tuo tool per funzionare e di cui il modello non deve sapere nulla. API key per servizi di fatturazione di terze parti, percorsi del file system o identificatori di tenant in un'architettura multi-tenant appartengono tutti al runtime context.
Ecco il punto chiave. Nascondere gli argomenti di configurazione dietro il runtime context garantisce che il tuo modello agisca esclusivamente come logic router, mentre il codice della tua applicazione mantiene il controllo assoluto e senza compromessi sull'accesso ai dati e sulla sicurezza dell'esecuzione.
Grazie per aver trascorso qualche minuto con me. Alla prossima, stammi bene.
7
Persistenza a Livello di Thread
3m 57s
Affrontiamo il tema della memoria a breve termine e di come mantenere la cronologia delle conversazioni. Imparerai come collegare i checkpointers al tuo agente per consentire alle conversazioni di essere messe in pausa, riprese e ricordate.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 7 di 20. Senza memoria, ogni interazione con il tuo agente IA sembra una scena di 50 volte il primo bacio. Il modello parte completamente vuoto, dimenticando tutto quello di cui hai discusso pochi secondi prima. La soluzione è la persistenza a livello di thread.
I Large Language Model sono completamente stateless. Elaborano testo e restituiscono testo, senza conservare assolutamente nulla tra una richiesta e l'altra. Per sostenere una conversazione, un agente ha bisogno di un modo per memorizzare e recuperare le interazioni passate. Nel contesto di una singola sessione attiva, gestiamo questo aspetto tramite la memoria a breve termine, che viene gestita come parte dello state dell'agente e resa persistente tramite checkpointer.
Spesso si pensa che la memoria nell'IA sia una sorta di capacità interna del modello, per cui la rete neurale si ricorda magicamente di te. Non è così. La memoria è semplicemente la message history. La persistenza a livello di thread significa semplicemente prendere la lista continua di messaggi, salvarla in un database dopo ogni step, e inserirla nuovamente nel prompt prima che il modello veda l'input successivo. Il checkpointer gestisce tutto questo automaticamente, così non devi scrivere manualmente la logica di storage e recupero.
In LangGraph, lo state viene salvato per ogni thread. Un thread rappresenta una sessione continua. Per abilitare questa funzionalità, hai bisogno di un checkpointer. Per lo sviluppo e il testing, puoi usare l'In Memory Saver. Quando compili il graph del tuo agente, passi questo oggetto saver come argomento del checkpointer. Questa integrazione dice all'agente che, alla fine dell'esecuzione di ogni node, deve fare uno snapshot del suo state corrente e passarlo al saver. Lo state include tutto ciò che hai definito nel tuo graph, che in genere è una lista continua di messaggi.
Vediamo uno scenario concreto. Compili il tuo agente con un In Memory Saver. Ora, vuoi invocare l'agente. Invece di passare solo un messaggio utente, passi anche un oggetto di configurazione che contiene uno specifico thread ID. Usiamo il valore string conversation one. Invii il messaggio, il mio nome è Bob. L'agente lo riceve, genera un saluto cortese e termina. Dietro le quinte, il checkpointer salva lo state aggiornato, che ora contiene il messaggio che dice che il tuo nome è Bob, indicizzato sotto conversation one.
Più tardi, invochi l'agente una seconda volta. Invii un nuovo messaggio chiedendo, qual è il mio nome. Cosa fondamentale, passi esattamente lo stesso oggetto di configurazione con il thread ID conversation one.
Ecco il punto chiave. Prima che l'agente passi la tua nuova domanda al modello, il checkpointer intercetta il processo. Cerca conversation one nell'In Memory Saver. Recupera lo snapshot dello state dal tuo turno precedente, carica la message history salvata e aggiunge la tua nuova domanda alla fine. Il language model riceve il contesto storico completo, vede il messaggio precedente in cui ti sei presentato e risponde correttamente che il tuo nome è Bob.
Se cambiassi il thread ID in conversation two e chiedessi il tuo nome, il checkpointer cercherebbe quel nuovo ID, non troverebbe nessuno state esistente e inizializzerebbe una message list nuova e vuota. L'agente non avrebbe idea di chi tu sia. Il thread ID è l'unica chiave che lega una sequenza di chiamate al modello isolate e stateless in una sessione coerente di memoria a breve termine.
Il checkpointer astrae il lavoro ripetitivo di gestione degli array di messaggi e delle query ai database, garantendo che il tuo agente possa riprendere il suo lavoro esattamente da dove lo aveva interrotto, a patto che tu fornisca il thread ID corretto.
Grazie per aver ascoltato, ci sentiamo alla prossima.
8
Comprimere il Contesto con i Middleware
3m 32s
Esploriamo come evitare che le lunghe conversazioni mandino in crash il tuo modello. Imparerai a utilizzare il SummarizationMiddleware per comprimere automaticamente i vecchi messaggi e risparmiare token.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 8 di 20. Più una conversazione si protrae, più un Large Language Model viene distratto da informazioni obsolete. Perdi precisione, mentre paghi costi in token più alti per ogni singolo turno. Comprimere il context tramite middleware risolve proprio questo problema.
Man mano che la chat history cresce, raggiungi inevitabilmente il limite della context window del tuo modello. Anche prima di raggiungere quell'hard limit, dare in pasto migliaia di token di vecchie conversazioni degrada le prestazioni. La soluzione è il SummarizationMiddleware in LangChain. Invece di tagliare semplicemente i vecchi messaggi, li comprime in un singolo blocco di summary. Questo preserva il significato semantico della conversazione senza l'enorme overhead di token.
C'è un equivoco comune su come funzioni. Spesso si pensa che il primary agent debba eseguire la summarization da solo. Non è così, e non dovrebbe assolutamente farlo. Vuoi che il tuo primary agent giri sul tuo modello più intelligente e capace per gestire la logica complessa. La summarization è un task molto più semplice. Assegni un modello più piccolo ed economico al SummarizationMiddleware esclusivamente per questo task.
Configurare il middleware richiede di definire due parametri principali. Il primo è il trigger. Il trigger dice al middleware quando intervenire. Potresti impostare il trigger per attivarsi ogni volta che il token count totale della conversazione raggiunge i 4000 token. Il secondo parametro è la keep condition. Questa dice al middleware quanto context recente lasciare completamente intatto. Potresti impostare il keep value a 20, il che significa che i 20 messaggi più recenti rimangono intatti.
Ecco il logic flow in pratica. Il tuo utente sta chattando con il main agent. La conversazione cresce. Al turno successivo, la message history totale supera la soglia dei 4000 token. Prima ancora che il primary agent veda il nuovo user input, il SummarizationMiddleware intercetta la request. Scansiona la history e identifica tutto ciò che è più vecchio dei 20 messaggi più recenti. Prende quel chunk più vecchio della conversazione e lo passa al tuo modello più piccolo designato. Diciamo che hai configurato il middleware per usare gpt-4.1-mini.
Quel modello più piccolo legge i vecchi messaggi e genera un paragrafo conciso che riassume la discussione. Il middleware quindi riscrive l'array della history. Sostituisce tutti quei vecchi messaggi individuali con un singolo system message contenente il nuovo summary. Se c'era già un summary più vecchio da un precedente ciclo di compressione, il middleware lo include nel prompt in modo che il nuovo summary aggiorni la narrazione in corso.
Il pacchetto finale inviato al tuo primary agent è altamente ottimizzato. Contiene il nuovo summary message, seguito dai 20 messaggi recenti non compressi, seguiti dall'ultimo user input.
Ecco il punto chiave. Il primary agent non si accorge mai che la history è stata compressa dietro le quinte. Riceve semplicemente una context window pulita e altamente rilevante. Preservi il significato semantico a lungo termine della chat, mantieni il modello concentrato e abbassi drasticamente i costi in token a ogni turno successivo.
Se trovi utili questi episodi e vuoi supportare lo show, puoi cercare DevStoriesEU su Patreon. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
9
Formati Dati Garantiti
3m 24s
Discutiamo di come forzare i modelli linguistici a restituire strutture dati rigorose e prevedibili. Scoprirai la differenza tra ProviderStrategy e ToolStrategy per la generazione di modelli Pydantic.
Ciao, sono Alex di DEV STORIES DOT EU. Framework di orchestrazione LangChain v1.0, episodio 9 di 20. Sviluppare software che si basa sul parsing di risposte in linguaggio naturale tramite espressioni regolari è una bomba a orologeria. Chiedi a un language model un semplice data object, e lui ti restituisce dati perfetti, tranne per il fatto che aggiunge un saluto di cortesia all'inizio e racchiude il tutto nella formattazione markdown. Il tuo parser va in crash all'istante. I Guaranteed Data Formats sono il modo in cui risolvi questo problema in modo permanente.
Lo structured output forza il language model a restituire le informazioni esattamente nel modo in cui la tua applicazione se le aspetta. Trasforma la generazione di testo imprevedibile in software object affidabili. Prendi come esempio un sistema che elabora i messaggi di customer support in entrata. Un utente invia un paragrafo disordinato e non strutturato lamentandosi di un problema di login, ma nascondendo nome, indirizzo email e numero di telefono da qualche parte nel testo. Hai bisogno di questi tre dati per triggerare una lookup sul database.
Invece di scrivere un prompt complesso implorando il modello di formattare correttamente la sua risposta, definisci un modello Pydantic standard. Crei una classe chiamata ContactInfo e definisci name, email e phone come campi obbligatori. Poi, passi semplicemente questo schema Pydantic al parametro response format della configurazione del tuo language model. Non hai bisogno di fornire esempi o scrivere script di validazione custom.
Questa è la parte che conta. Quando fornisci quello schema Pydantic, LangChain determina automaticamente il modo più affidabile per applicarlo. Lo fa scegliendo silenziosamente tra due diversi percorsi di esecuzione.
Per prima cosa, verifica se il language model che hai scelto ha una feature ufficiale di structured output integrata nella sua API. Se ce l'ha, LangChain seleziona in automatico la Provider Strategy. Questa strategia invia il tuo schema direttamente al provider, sfruttando i loro vincoli nativi lato server per garantire il formato di output.
Ma l'hardware cambia e i modelli vengono swappati. Se decidi di usare un modello diverso che non ha lo structured output nativo, LangChain rileva questa mancanza. Fa automaticamente un fallback sulla Tool Strategy. Dietro le quinte, traduce il tuo schema ContactInfo in una function signature. Comunica al modello l'esistenza di un fake tool che richiede esattamente un name, un'email e un phone number per girare. Il modello tenta di chiamare questo tool e, così facendo, genera gli argomenti strutturati esatti di cui hai bisogno. Il codice della tua applicazione non deve mai cambiare per adattarsi allo swap.
Quando l'operazione è completata, gli sviluppatori spesso cercano i loro dati nel posto sbagliato. Potresti dare per scontato che l'output venga restituito come raw text che devi ancora parsare. Non è raw text. LangChain intercetta il payload e istanzia l'oggetto Pydantic per te. Inserisce questo oggetto Python completamente validato direttamente nel tuo application state. Lo troverai catturato nella chiave structured response del tuo state dictionary. Ti basta fare riferimento a quella chiave, e hai immediatamente il tuo oggetto ContactInfo, con campi type-safe pronti per essere passati al resto della tua applicazione.
Spostando il peso della schema validation dalla logica di parsing custom al livello del framework, le integrazioni del tuo language model diventano prevedibili come una chiamata API standard.
Grazie per aver ascoltato — ci sentiamo alla prossima.
10
Intercettare il Ciclo dell'Agente
3m 17s
Introduciamo il paradigma dei middleware, che ti offre un controllo chirurgico sull'esecuzione del tuo agente. Imparerai a utilizzare gli hook wrap-style e node-style per intercettare le chiamate al modello.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 10 di 20. Se il tuo agent fallisce silenziosamente in produzione, spesso è perché non stai monitorando cosa succede tra le fasi del suo reasoning loop. Il modello va in crash, il loop si interrompe e ti ritrovi a fissare una run incompleta. Intercettare il loop dell'agent con un middleware custom è il modo per riprendere il controllo.
Quando un agent esegue un ciclo ReAct, cede continuamente il controllo al language model. Il middleware fornisce degli hook per eseguire la tua logica esattamente quando ne hai bisogno durante questo scambio. Ci sono due tipi principali di hook che utilizzerai: i node-style hook e i wrap-style hook. Un errore comune è trattarli in modo intercambiabile. I node-style hook vengono eseguiti in sequenza. I wrap-style hook racchiudono l'esecuzione e possono intercettare le eccezioni.
I node-style hook usano decorator chiamati before model e after model. Quando associ un hook before model a una funzione, il framework esegue completamente la tua logica, e solo dopo chiama l'API del language model. Quando il modello risponde, viene eseguito un hook after model. Questi hook sono ottimi per loggare il prompt esatto inviato all'API, iniettare contesto o rimuovere caratteri non validi dall'output di testo finale. Ma dato che vengono eseguiti rigorosamente in sequenza, non offrono alcuna protezione contro i fallimenti. Se l'API del language model va in timeout, il tuo hook after model non viene mai eseguito. L'errore si propaga e manda in crash l'intero loop dell'agent.
Questa è la parte importante. Se devi gestire l'instabilità, usi un wrap-style hook. Il decorator per questo è wrap model call. Un wrap hook si posiziona completamente attorno all'esecuzione del modello. La tua funzione viene eseguita, fa un po' di setup, e poi fa uno yield esplicito del controllo al modello. Dato che il tuo codice custom fa il wrap della vera e propria chiamata di rete, puoi inserire quell'esecuzione all'interno di strutture standard di error handling.
Immagina di creare un middleware wrap model call per gestire gli API rate limit con un retry loop in exponential backoff. Scrivi una funzione con il decorator wrap model call. All'interno di questa funzione, crei un retry loop. Inserisci il comando che cede il controllo al modello all'interno di un blocco try. Se il modello ha successo, prendi la response, la restituisci e il loop termina. Se il modello lancia un errore, il tuo blocco catch lo intercetta. Invece di far fallire l'agent, il tuo blocco catch fa scattare una pausa. Calcoli un breve delay, aspetti, e poi lasci che il loop tenti di nuovo la chiamata, raddoppiando il delay ogni volta.
L'orchestrator dell'agent non vede mai i fallimenti. Il middleware intercetta le eccezioni, gestisce la retry logic in isolamento, e restituisce senza problemi una response di successo al loop ReAct principale quando finalmente va a buon fine.
I node-style hook preparano gli input e formattano gli output, ma i wrap-style hook proteggono l'esecuzione. Per questo episodio è tutto. Alla prossima!
11
Context Engineering Dinamico
4m 03s
Ci immergiamo nel context engineering generando dinamicamente i system prompt. Imparerai a utilizzare i middleware per alterare le istruzioni in base al ruolo dell'utente corrente e all'ambiente.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 11 di 20. Il motivo principale per cui il tuo agent fallisce non è perché il modello sottostante è stupido. È perché gli hai dato il context sbagliato per il lavoro. Se il tuo sistema tratta un superuser e un guest esattamente allo stesso modo, la tua applicazione è cieca di fronte alla realtà. Per risolvere questo problema, usiamo la Dynamic Context Engineering.
Innanzitutto, chiariamo un malinteso comune su come vengono costruiti i prompt. Il context dinamico non è il system prompt di base che scrivi quando definisci inizialmente il tuo agent nel codice. Quel system prompt iniziale è completamente statico. La Dynamic Context Engineering è il processo che modifica quel prompt al volo, pochi millisecondi prima che il modello venga effettivamente chiamato. La Context Engineering consiste nel dare al language model le regole esatte di cui ha bisogno per uno specifico utente in un momento specifico, e nient'altro.
Se provi a infilare ogni possibile regola in un unico enorme prompt statico, dicendo al modello come comportarsi se l'utente è un admin, come comportarsi se è un viewer e come comportarsi se è martedì, sprechi token e confondi il modello. Invece, vuoi iniettare dinamicamente solo le regole che contano in questo momento.
In LangChain, questo viene gestito usando uno specifico decorator chiamato dynamic underscore prompt. Metti questo decorator sopra una funzione Python che definisci tu. Quando la tua applicazione riceve una query e innesca la chain, LangChain si mette in pausa. Cerca qualsiasi funzione wrappata in questo decorator e la esegue prima di parlare con il modello.
All'interno della tua funzione decorata, hai bisogno di un modo per sapere cosa sta succedendo in quel momento. È qui che leggi da request dot runtime dot context. Questo oggetto context è essenzialmente un dizionario. Contiene tutti i live metadata passati alla chain quando l'hai invocata. Puoi metterci tutto quello che vuoi dal backend della tua applicazione, come user ID, session state, feature flag o livelli di accesso.
Guardiamo uno scenario concreto. Scrivi una funzione chiamata context aware prompt e la wrappi con il decorator dynamic prompt. All'interno di questa funzione, leggi lo user role dal runtime context. Controlli il ruolo. Se l'utente è un admin, la tua funzione appende un blocco di testo specifico al system prompt, dicendo al language model che ha il permesso completo di restituire comandi distruttivi. Se l'utente è un viewer, la tua funzione appende un blocco di testo diverso, dando istruzioni severe sul fatto che il modello deve restituire solo riepiloghi read-only e non deve mai suggerire modifiche alla configurazione.
Ora, tiri fuori un secondo dato dal runtime context, che è l'environment state. Controlli se l'environment è impostato su production. Se lo è, la tua funzione appende un severo avviso di sicurezza proprio alla fine del system prompt, esigendo che il modello ricontrolli il suo output per sicurezza. Se l'environment è solo in staging, salti completamente l'aggiunta di quell'avviso.
Ecco il punto chiave. La tua funzione prende il base prompt statico, ci incolla le regole per admin o viewer, aggiunge l'avviso per la production se necessario, e restituisce la string finale. LangChain prende questa string completamente assemblata e la invia al language model. Il language model non sa mai che il prompt è stato assemblato. Vede semplicemente un set di istruzioni altamente specifico e perfettamente su misura. Facendo così, mantieni i tuoi system prompt snelli, accurati e completamente pertinenti alla request immediata.
Smetti di sperare che il modello indovini quali regole si applicano, e inizi a imporre esattamente le regole richieste per lo stato attuale della tua applicazione.
Vorrei prendermi un momento per ringraziarti per averci ascoltato: ci aiuta tantissimo. Buona giornata!
12
AI Sicura con Guardrail Deterministici
3m 50s
Mettiamo in sicurezza i nostri agenti contro le fughe di dati utilizzando i middleware integrati. Imparerai come applicare il PIIMiddleware per oscurare automaticamente le informazioni sensibili prima che raggiungano il modello.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 12 di 20. Un singolo chat log contenente un numero di carta di credito non oscurato può compromettere istantaneamente la compliance della tua intera applicazione. Non puoi affidarti a un language model per ignorare educatamente i dati sensibili, e chiedere al modello di autocensurarsi è lento e imprevedibile. È qui che entra in gioco la Safe AI con i guardrail deterministici.
I guardrail deterministici sono controlli hardcoded, basati su regole. Si basano su pattern e logiche prevedibili, come le regular expression o algoritmi fissi, invece di chiedere a un altro language model di valutare il testo. Poiché bypassano la chiamata di rete a un'AI, vengono eseguiti in millisecondi e hanno un costo praticamente nullo. Se sviluppi per la produzione, questo layer deterministico è obbligatorio per la sicurezza.
Nel framework, implementi tutto questo usando il PII Middleware. Un errore frequente che fanno gli sviluppatori è cercare di filtrare le informazioni sensibili a posteriori, scansionando l'output del modello. Ma per proteggere la privacy degli utenti, il PII Middleware è progettato per intercettare il messaggio raw non appena l'utente preme invio. Elabora il testo prima ancora che la chiamata al modello venga iniziata. Configuri esplicitamente questo comportamento impostando il parametro apply to input su true.
Vediamo uno scenario con un agente del servizio clienti. Un utente stressato invia un messaggio dicendo che il suo account è bloccato, includendo il suo indirizzo email personale, e poi incolla l'intero numero di carta di credito a sedici cifre per verificare l'acquisto. Se il tuo codice passa quella string raw a un provider AI di terze parti, hai violato la compliance di base dei dati. Hai bisogno di una strategia per neutralizzare il testo, e il middleware ti offre tre azioni integrate: block, redact e mask.
Se usi la strategia block, il middleware agisce come un muro invalicabile. Nel momento in cui rileva il formato della carta di credito, lancia un errore e interrompe completamente la chain. La richiesta viene respinta in toto.
Se scegli la strategia redact, il middleware rimuove chirurgicamente i dati specifici e inserisce un placeholder pulito. L'indirizzo email personale viene completamente eliminato dalla string e sostituito con la parola email tra parentesi. Il language model legge comunque una frase coerente e capisce che è stata fornita un'email, ma i dati effettivi sono spariti.
La terza strategia è mask. Il masking conserva una porzione sicura dei dati originali. Il middleware sostituisce le prime dodici cifre della carta di credito con degli asterischi, lasciando esposti solo gli ultimi quattro numeri. Questo è molto efficace quando il tuo sistema di backend deve verificare un account senza esporre l'intero record finanziario.
Implementare questo richiede la configurazione del middleware prima che la tua chain venga eseguita. Crei un'istanza del PII Middleware e gli fornisci una lista di entità target. In questo caso, specifichi email e carta di credito. Assegni quindi le tue strategie scelte a quelle entità, magari scegliendo redact per l'email e mask per la carta. Infine, colleghi questo componente middleware alla tua chain principale, assicurandoti di impostare il parametro apply to input. Nel momento in cui l'utente invia il suo messaggio, le regole deterministiche ripuliscono il testo, e l'AI riceve solo un prompt sanificato.
Ecco il punto chiave. Il modo più sicuro per gestire le informazioni personali sensibili in qualsiasi architettura di AI generativa è garantire che il language model non le veda mai fin dall'inizio. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
13
In Pausa per l'Approvazione Umana
4m 08s
Esploriamo l'esecuzione di tool ad alto rischio aggiungendo un essere umano al ciclo. Imparerai come interrompere l'esecuzione di un agente per approvare, modificare o rifiutare azioni sensibili.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 13 di 20. Un agent autonomo è incredibilmente potente, almeno fino al momento in cui invia autonomamente una bozza dei tuoi dati finanziari al cliente sbagliato. Alcune azioni sono semplicemente troppo rischiose per essere eseguite senza un paio di occhi umani. È proprio per questo che usiamo la pausa per l'approvazione umana.
Gli agent eseguono automaticamente i tool in base ai prompt dell'utente. Questo comportamento è ideale per leggere i dati, ma è pericoloso per azioni distruttive o irreversibili. Abbiamo bisogno di un modo per mettere in pausa l'esecuzione, chiedere a un umano se un'azione è sicura, e poi riprenderla o annullarla.
Prima di parlare dei meccanismi, dobbiamo chiarire un punto di errore comune. A volte gli sviluppatori configurano gli interrupt e poi si chiedono perché l'agent crasha o si riavvia. Devi avere un checkpointer abilitato. Non puoi mettere in pausa un agent se non riesce a ricordare dove si era interrotto. L'intera memoria dell'agent e il suo progresso attuale devono essere salvati nel persistence layer mentre aspetta che un umano risponda. Senza checkpointer, niente pausa.
Con la persistence attiva, puoi gestire l'esecuzione dei tool in modo sicuro usando il middleware Human In The Loop. Immagina un setup in cui il tuo agent ha due tool: un tool di ricerca e un tool per eliminare il database. Vuoi che l'agent cerchi liberamente, ma non vuoi assolutamente che esegua il drop delle tabelle senza permesso.
Quando configuri questo middleware, imposti un argomento chiamato interrupt on. Gli passi i nomi specifici dei tool che richiedono supervisione. Nel nostro scenario, configuri interrupt on per monitorare solo il tool di eliminazione del database. Il tool di ricerca viene ignorato dal middleware e viene eseguito immediatamente ogni volta che l'agent lo chiama. Tuttavia, quando l'agent decide di dover usare il tool di eliminazione del database, il middleware intercetta la richiesta. Mette in pausa il graph, salva lo stato corrente nel tuo checkpointer e ferma completamente l'esecuzione.
Il graph è ora sospeso nel persistence layer, in attesa dell'intervento umano. L'operatore umano esamina la tool call in sospeso e ha tre modi per rispondere al middleware.
Il primo tipo di decisione è approve. L'umano guarda i parametri generati dall'agent, concorda che siano corretti e invia un comando di approvazione. Il graph si risveglia ed esegue l'eliminazione esattamente come l'agent aveva originariamente pianificato.
Il secondo tipo di decisione è reject. L'operatore vede che l'agent sta cercando di eliminare il target sbagliato e invia un reject. Il tool non viene eseguito. Invece, l'agent riceve un'osservazione che indica che l'azione è stata bloccata da un umano. L'agent quindi elabora questo feedback e può provare un approccio diverso o chiedere chiarimenti all'utente.
Ecco il punto chiave. La terza opzione è edit. A volte l'agent fa quasi tutto giusto ma commette un piccolo errore, come puntare all'ambiente di produzione invece che all'ambiente di staging. Invece di rifiutare completamente l'azione e costringere l'agent a ragionare di nuovo sul problema, l'operatore può modificare direttamente i parametri di input del tool. L'umano cambia l'ambiente di destinazione in staging e invia la call corretta. L'agent riprende ed esegue l'azione usando i parametri modificati, procedendo senza intoppi.
Usando questo middleware, proteggi il tuo sistema da errori pericolosi. Mettere in pausa per l'approvazione umana non previene solo le catastrofi, ma trasforma il tuo agent da un'entità imprevedibile a un collaboratore supervisionato in grado di gestire in sicurezza operazioni ad alto rischio.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
14
Feedback dell'Agente in Tempo Reale
3m 41s
Ci immergiamo nello streaming per migliorare drasticamente l'esperienza utente. Imparerai a interpretare le stream modes per visualizzare i token dell'LLM dal vivo insieme agli aggiornamenti personalizzati sull'esecuzione dei tool.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 14 di 20. Agli utenti non dispiace aspettare dieci secondi per una risposta complessa, a patto che tu gli mostri cosa sta facendo il cervello durante quei dieci secondi. Una schermata vuota dà l'impressione di un'applicazione rotta. La soluzione alla latenza percepita è il feedback in tempo reale dell'agent.
Per risolvere il problema della schermata vuota, LangChain espone un parametro chiamato stream mode quando esegui il tuo agent o graph. Controlla esattamente che tipo di dati l'agent rimanda indietro sulla connessione mentre è in esecuzione. La prima modalità che devi conoscere è la messages mode. Questa gestisce il classico effetto typing. Manda in stream i token grezzi dal language model man mano che vengono generati. Se il modello sta scrivendo un paragrafo, la tua applicazione riceve i chunk di testo uno alla volta, permettendo alla tua user interface di aggiornarsi in modo fluido invece di aspettare l'intero blocco di testo.
Spesso le persone confondono lo streaming dei token della risposta finale con lo streaming del ragionamento intermedio. Sono due cose completamente diverse. Se il tuo agent decide di chiamare un search tool, la generazione dei token si ferma. Il language model sta aspettando che il tool finisca. Se quel tool ci mette cinque secondi a girare, la tua user interface si blocca per cinque secondi. La messages mode da sola non dice all'utente cosa sta effettivamente facendo l'agent in background. Mostra solo quello che il language model sta dicendo.
Per risolvere il problema del tool silenzioso, usi la custom mode. La custom mode permette ai tuoi tool e ai node interni di emettere i propri aggiornamenti di stato in tempo reale direttamente nello stream. Per implementare questo, usi una utility di LangChain chiamata get stream writer. Chiami questa funzione all'interno del codice del tuo tool. Ti restituisce un oggetto writer, che puoi usare per emettere custom event verso il client in qualsiasi momento durante l'esecuzione del tool.
Pensa a un tool di controllo meteo lento. Il tuo agent riceve un prompt che chiede le previsioni e decide di chiamare il weather tool. All'interno della funzione Python per quel tool, recuperi lo stream writer. Mentre il tool inizia a interrogare una API remota lenta, usi il writer per emettere un custom event con uno stato tipo Acquired data. Il tuo frontend riceve immediatamente questo custom event e mostra un loading spinner con quel testo. L'utente sa che l'agent sta lavorando. Una volta che la API remota restituisce i dati, il tool finisce e il language model riprende il controllo. Prende i dati meteo grezzi, formula una risposta human-friendly, e il messages stream riparte, scrivendo le previsioni finali sullo schermo.
Ecco il punto chiave. Non devi scegliere per forza una sola modalità. Puoi passare una lista contenente sia messages che custom al parametro stream mode. LangChain intreccerà automaticamente i token del language model e i log del tuo custom tool in un unico feed continuo. Il tuo frontend deve solo controllare il tipo di evento quando arriva. Se è un custom event, aggiorni l'indicatore di stato. Se è un message event, aggiungi il token alla chat bubble. La latenza percepita scende a zero perché il sistema sta sempre parlando con l'utente.
Se vuoi aiutare a far continuare questi episodi, puoi supportare lo show cercando DevStoriesEU su Patreon. Grazie per l'ascolto, e happy coding a tutti!
15
Persistenza Cross-Session
3m 45s
Esploriamo la memoria a lungo termine per costruire agenti che conoscano veramente i loro utenti. Imparerai a utilizzare gli store di LangGraph per salvare documenti JSON attraverso conversazioni completamente diverse.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 15 di 20. Per creare un assistente veramente personalizzato, deve ricordarsi che preferisci risposte brevi, anche se glielo hai detto tre settimane fa in una chat completamente diversa. Se ti affidi esclusivamente alla memoria di conversazione standard, questa preferenza scompare nel momento in cui inizi un nuovo thread. Il meccanismo che impedisce questa amnesia è la Cross-Session Persistence tramite il paradigma Store.
Molti sviluppatori confondono il checkpointer con lo store. Ecco la differenza. Un checkpointer gestisce lo state a breve termine. Ricorda un singolo thread di conversazione. Quando l'utente crea una nuova chat, il checkpointer riparte da zero. Lo store supera i confini di questi thread. Permette ai tuoi agent di persistere e recuperare informazioni a livello globale, in tutte le interazioni con uno specifico utente.
In sostanza, la memoria a lungo termine in LangChain è semplicemente un key-value store gerarchico. Persiste documenti JSON. La gerarchia si basa sui namespace. Un namespace è una sequenza di string che si comporta esattamente come il percorso di una cartella sul tuo computer. Se vuoi memorizzare i dati del profilo, potresti usare un namespace che contiene la string "users", seguita dall'identificativo dell'utente. All'interno di questo namespace, memorizzi degli elementi. Ogni elemento richiede una string key univoca e un dictionary che rappresenta il valore JSON.
È qui che la cosa si fa interessante. I tool interagiscono con questo store direttamente tramite il context di runtime. Non passi mai lo store manualmente attraverso il graph state.
Considera un custom tool chiamato save user info. Il suo compito è catturare una preferenza sulla lingua parlata. Durante il setup, inizializzi la tua applicazione con uno store di supporto, come un in-memory store per i test locali. All'interno della logica del tuo tool, accedi all'istanza dello store direttamente dalla configurazione di runtime iniettata. Estrai l'identificativo dell'utente dal context corrente. Poi, chiami il metodo put sullo store. Fornisci la tupla del namespace contenente la parola "users" e l'ID utente. Definisci una key, come "language preference", e infine passi il dictionary JSON contenente il valore, magari "Spanish".
Lo store persiste questo documento. Settimane dopo, l'utente inizia una conversazione completamente nuova. Lo state del thread è vuoto. Ma poiché l'agent ha accesso a un retrieval tool, può chiamare il metodo get sullo store di runtime usando esattamente lo stesso namespace e la stessa key. Recupera il documento JSON, legge la preferenza e risponde immediatamente in spagnolo.
Separare il context conversazionale a breve termine dalla memoria fattuale a lungo termine mantiene la tua applicazione leggera. Il checkpointer non si appesantisce con anni di cronologia dell'utente, e lo state rimane pulito. Lo store carica solo gli specifici documenti JSON che l'agent decide esplicitamente di recuperare.
Trattare context e persistenza come due sistemi completamente distinti è l'unico modo per scalare un agent in modo affidabile. Il checkpointer conserva il presente, mentre lo store conserva il passato.
Questo è tutto per oggi. Grazie per aver ascoltato — vai a creare qualcosa di fantastico.
16
Il Paradigma Multi-Agente
4m 06s
Spieghiamo perché i singoli agenti falliscono e introduciamo l'architettura Subagents. Imparerai come un agente supervisore principale coordina i subagents come context windows isolate per prevenire il sovraccarico di token.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 16 di 20. Quando il tuo singolo agente IA inizia a fallire a causa della sua enorme lista di tool e istruzioni in conflitto, dargli in pasto una context window più ampia non risolverà il problema. È ora di smettere di costruire uno script monolitico e iniziare ad assumere un team. Ed è proprio qui che entra in gioco il paradigma multi-agent.
Costruiamo sistemi multi-agent perché i singoli agenti si scontrano con un muro cognitivo. Dai a un agente trenta tool, cinque pagine di system prompt e una lunga history di conversazione, e perderà il focus. Chiamerà il tool sbagliato o dimenticherà i vincoli. L'approccio multi-agent scompone questo problema. Abilita lo sviluppo distribuito, in cui team diversi gestiscono agenti diversi. Permette l'esecuzione parallela. Ma soprattutto, impone un rigoroso isolamento del context.
Oggi ci concentriamo su un'architettura specifica chiamata pattern Subagents. Questa prevede un agente supervisor principale che delega i task a subagent specializzati. Spesso si confonde un supervisor con un semplice router. Un router è solo una funzione statica che esamina una query e la invia su un percorso fisso. Un supervisor è un agente attivo e pensante. Mantiene lo state della conversazione, decide quali subagent invocare nel corso di più turni e sintetizza le loro risposte.
Ecco il punto chiave. I subagent forniscono un perfetto isolamento del context. Quando il supervisor chiede a un subagent di fare qualcosa, il subagent si avvia con una context window completamente pulita. Ha solo le istruzioni e i tool specifici necessari per il suo esatto lavoro. Il subagent potrebbe commettere errori, chiamare i tool tre volte e riempire il proprio scratchpad mentre cerca di trovare la risposta. Il supervisor non vede mai questo caos. Riceve solo il risultato finale ripulito. Questo protegge il tuo main agent dal context bloat e previene le allucinazioni.
Per connettere il supervisor ai subagent, incapsuli i subagent come tool. Ci sono due modi per farlo in LangChain. Il primo metodo è tool-per-agent. Assegni al supervisor un tool specifico per ogni subagent. Se hai cinque subagent, il supervisor ha cinque tool. Il secondo metodo è un single-dispatch tool. Qui, il supervisor ottiene esattamente un tool chiamato qualcosa come delegate task. Questo tool richiede due input: il nome del target agent e la descrizione del task.
Considera uno scenario single-dispatch. Hai un main agent, un research agent e un writer agent. Un utente chiede un report di mercato complesso. Il main agent decide che prima gli servono i dati. Chiama il single-dispatch tool, passando il research agent come target e la query di mercato come payload. Il research agent si avvia nel suo context isolato, cerca sul web, fa il parsing dei documenti e restituisce un paragrafo di riepilogo. Il main agent riceve questo testo. Successivamente, il main agent chiama di nuovo il dispatch tool, questa volta puntando al writer agent, passandogli il riepilogo della ricerca e le istruzioni di formattazione. Il writer agent redige il report finale e lo restituisce al main agent, che lo consegna all'utente.
Puoi eseguire questi subtask in modo diverso a seconda delle tue esigenze. Puoi eseguire i subagent in modo sincrono, dove il supervisor aspetta che il research agent finisca prima di intraprendere qualsiasi altra azione. Se hai task indipendenti, come fare ricerca su tre diversi competitor, puoi eseguire i subagent in modo asincrono. Il supervisor fa il dispatch di tutti e tre i task contemporaneamente, questi vengono eseguiti in parallelo, e il supervisor aspetta che tutti ritornino prima di andare avanti.
Raggruppare i task nei subagent non serve solo a organizzare il tuo codice, serve a controllare rigorosamente ciò che il language model è costretto a tenere in memoria in un dato momento.
Questo è tutto per questo episodio. Grazie per aver ascoltato, e continua a sviluppare!
17
Agenti State-Driven
3m 53s
Esploriamo come gli agenti possano alterare dinamicamente il loro comportamento. Imparerai il pattern Handoffs per trasferire il controllo e il pattern Skills per caricare prompt specializzati su richiesta.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 17 di 20. Non hai bisogno di caricare la mente del tuo agent con ogni possibile scenario fin dall'inizio. Infilare cinquanta pagine di istruzioni in un singolo system prompt rende solo il tuo modello confuso, lento e costoso. Devi solo insegnargli come chiedere il manuale giusto al momento opportuno. Questo è il meccanismo fondamentale alla base degli State-Driven Agent.
Gli State-Driven Agent funzionano secondo un principio semplice. Il comportamento dell'agent cambia dinamicamente in base allo state attuale dell'applicazione. Gestiamo questo aspetto utilizzando due pattern principali, che sono Skill e Handoff. Entrambi i pattern si basano sui tool per aggiornare le variabili di state, che a loro volta determinano cosa succede dopo nel workflow.
Diamo prima un'occhiata al pattern Skill. Questo pattern riguarda la progressive disclosure della conoscenza. Invece di dare a un agent tutte le sue istruzioni all'inizio, gli dai un tool. Quando l'agent decide di aver bisogno di più informazioni per risolvere un problema, chiama questo tool. Il tool viene eseguito, ma fa molto di più che restituire semplicemente una string al modello. Aggiorna una specifica variabile di state nella tua applicazione. Il tuo orchestration layer monitora questo state. Quando rileva il cambiamento, inietta dinamicamente un nuovo set di istruzioni o capability nel system prompt dell'agent per il turno successivo.
Prendi un agent di customer support standard. All'inizio, il suo unico compito è capire cosa vuole il cliente. Un utente fa una domanda su un prodotto rotto. L'agent chiama un tool per raccogliere un warranty ID. L'esecuzione di questo tool aggiorna una variabile di state per indicare che una richiesta di garanzia è attiva. L'applicazione legge questo nuovo state e carica dinamicamente una skill specializzata per i rimborsi nel prompt. Questa skill potrebbe includere le regole specifiche per elaborare i resi e l'accesso a un database di inventario sicuro. Le capability dell'agent si sono evolute a metà conversazione, guidate interamente da un aggiornamento dello state.
Ora, cosa succede se il task richiesto è troppo complesso da gestire per l'agent iniziale, anche con nuove skill? È qui che entra in gioco il pattern Handoff. Anche gli Handoff usano i tool per aggiornare lo state, ma invece di caricare nuove istruzioni nell'agent corrente, il cambio di state trasferisce il controllo a un agent completamente diverso. Torniamo al nostro scenario. L'agent di supporto raccoglie il warranty ID, ma invece di elaborare il rimborso da solo, chiama un tool di handoff. Questo tool aggiorna una variabile di routing nello state, cambiando l'agent attivo dal bot di triage a un agent specializzato, progettato esclusivamente per i resi di alto valore. L'orchestration layer vede questo cambio di state e indirizza lo step successivo del workflow allo specialista.
È in questo punto di transizione che spesso le cose si rompono. Durante l'handoff tra agent, il nuovo agent ha bisogno del context della conversazione. Molti sviluppatori cercano di ripulire la history passando semplicemente i messaggi raw dell'utente al nuovo agent. Non farlo. Durante l'handoff tra agent, devi includere il messaggio dell'AI che contiene l'effettiva tool call che ha avviato l'handoff, e il Tool message risultante che conferma l'avvenuto handoff. Se rimuovi la tool call e il tool message dal message array, la history della conversazione si rompe. Il nuovo modello perde la chain logica degli eventi. Non saprà come ci è arrivato, e probabilmente ripeterà domande a cui l'utente ha già risposto. Passa sempre la message history ininterrotta.
Ecco il punto chiave. Lo state non è solo un memory store passivo, ma il control plane che detta esattamente cosa il tuo sistema è in grado di fare in ogni singolo millisecondo.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
18
Workflow Personalizzati e Router
3m 44s
Usciamo dal ciclo standard dell'agente. Imparerai a utilizzare LangGraph per costruire architetture di routing personalizzate, mescolando logica deterministica con ragionamento agentico non deterministico.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 18 di 20. A volte non vuoi che un agent IA decida liberamente il prossimo passo. Vuoi semplicemente che esegua un flowchart rigoroso e deterministico. I workflow custom e i router ti danno esattamente questo livello di controllo.
Quando ti affidi esclusivamente a un agent loop standard, lasci che sia il language model a capire ogni step da solo. Potrebbe cercare in un database, rendersi conto di aver bisogno di più dati, cercare di nuovo e alla fine rispondere. È un approccio potente, ma imprevedibile e spesso lento. I workflow custom in LangGraph ti permettono di uscire da questo loop. Sei tu a disegnare la mappa. Puoi mixare in modo fluido la logica deterministica, come l'esecuzione di script esatti di data retrieval, con il ragionamento non deterministico dell'agent. Inserisci il language model all'interno di una sequenza rigorosa di eventi.
Prima di crearne uno, dobbiamo chiarire una confusione comune tra un router e un supervisor. Un supervisor orchestra attivamente una conversazione multi-turn. Osserva gli agent parlare, decide chi parla dopo e gestisce il dialogo nel tempo. Un router non fa questo. Un router è solo uno step di classificazione. Guarda l'input, decide quale percorso deve prendere il workflow, fa il routing dei dati e il suo lavoro finisce lì. Può essere stateless o stateful, ma non è un conversation manager.
Vediamo uno scenario concreto. Stai costruendo un tool per una knowledge base multi-source. Un utente fa una domanda, e la risposta potrebbe essere sepolta in delle pull request su GitHub, in dei thread su Slack, o in entrambi. Non vuoi che un singolo agent tiri a indovinare alla cieca su dove cercare. Vuoi un workflow strutturato.
Per prima cosa, crei un nodo di routing. Passi la query dell'utente a un language model e gli chiedi di restituire in output una semplice lista di destinazioni. Se la query riguarda un bug fix recente, il modello potrebbe dare in output le parole GitHub e Slack.
Questa è la parte che conta. Non devi scegliere un solo percorso. Puoi eseguire più agent contemporaneamente usando la Send API. In LangGraph, invece di restituire un singolo step successivo dalla tua logica condizionale, la tua funzione di routing restituisce una lista di comandi Send. Ogni comando associa un nodo di destinazione ai dati specifici di cui ha bisogno. Il graph vede più comandi Send ed esegue automaticamente tutti quei nodi target in parallelo. Questo si chiama fanning out.
Durante il fanning out, il workflow raggiunge i tuoi nodi agent. In un workflow custom, invocare un agent è semplice. Un agent è semplicemente un processo runnable eseguito all'interno di una funzione nodo standard. Il nodo Slack riceve la query, esegue uno Slack agent dedicato per cercare nei canali, estrae il context e lo restituisce allo state generale del graph. Il nodo GitHub fa la stessa cosa in simultanea per i code repository. Isolare questi agent all'interno di nodi specifici assicura che facciano solo il lavoro per cui sono stati creati.
Infine, tutti quei branch paralleli devono convergere. Fai fanning in. Crei un nodo synthesizer che aspetta che gli agent paralleli finiscano. Legge lo state generale del graph, prende il context raccolto da Slack e il context raccolto da GitHub, li passa entrambi a un language model finale, e genera una singola risposta pulita per l'utente.
Il vero potere dei workflow custom è racchiudere la natura imprevedibile dei large language model all'interno dell'affidabilità prevedibile del routing software standard.
Per questo episodio è tutto. Alla prossima!
19
Comunicazione Agent-to-Agent
4m 22s
Esploriamo l'endpoint LangSmith A2A. Imparerai come agenti distribuiti su server completamente diversi possano conversare nativamente utilizzando il protocollo A2A RPC di Google.
Ciao, sono Alex di DEV STORIES DOT EU. Framework di orchestrazione LangChain v1.0, episodio 19 di 20. Cosa succede quando un agent scritto in Python deve conversare nativamente con un agent sviluppato da un team completamente diverso, in esecuzione su un server completamente diverso? Se ti affidi a function call interne hardcoded, il tuo sistema si rompe nel momento in cui attraversa un confine di rete. La soluzione è la comunicazione Agent-to-Agent.
L'Agent-to-Agent, o A2A, è un protocollo di comunicazione che abilita sistemi multi-agent veramente distribuiti. Permette ad agent ospitati su server completamente diversi di mantenere una conversazione continua senza dover condividere la stessa codebase sottostante o lo stesso spazio di memoria locale. Invece di racchiudere tutto in un'unica enorme applicazione, instradi le request attraverso la rete.
La comunicazione si basa rigorosamente su un formato di endpoint ben definito: slash a2a slash, seguito dall'assistant ID. Ogni agent che partecipa a questa rete distribuita espone esattamente questo path dell'endpoint. Quando un agent ha bisogno di aiuto da un altro, invia lì una request HTTP POST. Il payload inviato a questo endpoint è strutturato come un messaggio JSON-RPC standard.
Per mantenere la conversazione coerente attraverso vari hop di rete e server diversi, il protocollo utilizza due identificatori distinti nel suo payload. A volte i developer li confondono, quindi definiremo i loro confini. Il primo è il Context ID. Il Context ID è responsabile della continuità generale del thread. Rappresenta l'intera history della conversazione generale, dal primo prompt all'output finale. Il secondo è il Task ID. Il Task ID identifica la request o lo step specifico all'interno di quel singolo turno. Il Context ID copre l'intera sessione. Il Task ID cambia ogni volta che un agent chiede all'altro di eseguire una nuova azione.
Considera uno scenario pratico in cui l'Agent A è in esecuzione su un server in ascolto sulla porta 2024, e l'Agent B è in esecuzione su un server diverso sulla porta 2025. L'Agent A si rende conto di aver bisogno dell'Agent B per gestire un subtask specifico, magari per controllare un inventario esterno. L'Agent A prepara un messaggio JSON-RPC. All'interno di questo messaggio, include il Context ID esistente, in modo che l'Agent B sappia a quale conversazione in corso appartiene. L'Agent A genera anche un Task ID nuovo di zecca per questa specifica request di inventario.
L'Agent A invia questo payload all'endpoint A2A sulla porta 2025, inserendo lo specifico assistant ID dell'Agent B direttamente nel path dell'URL. L'Agent B riceve la request. Legge il Context ID per recuperare qualsiasi state di background necessario, elabora il task richiesto nei parametri JSON-RPC e calcola il risultato. L'Agent B costruisce quindi una response JSON-RPC. Questa response include esplicitamente l'esatto Task ID che l'Agent A aveva originariamente fornito. L'Agent B rimanda questa response all'Agent A sulla porta 2024. L'Agent A riceve il risultato, fa il match tra il Task ID e la sua request in sospeso, e continua la propria esecuzione interna.
Ecco il punto chiave. Poiché il protocollo impone lo standard JSON-RPC e isola il tracciamento dello state in identificatori Context e Task specifici, nessun agent ha bisogno di sapere come opera internamente l'altro. Non mantengono una connessione socket costantemente aperta. Semplicemente si scambiano a turno messaggi strutturati avanti e indietro attraverso confini HTTP standard. Un server fa una domanda, l'altro risponde e il task generale procede.
Quando separi il thread di conversazione a lungo termine dall'esecuzione del singolo task a breve termine, puoi scalare reti multi-agent su server e framework diversi all'infinito. Se trovi utili questi episodi e vuoi supportare il podcast, puoi cercare DevStoriesEU su Patreon. Questo è tutto per questo episodio. Grazie per l'ascolto e continua a sviluppare!
20
Il Futuro è MCP
4m 44s
Guardiamo al futuro con il Model Context Protocol, che standardizza il modo in cui gli agenti accedono ai tool esterni. Imparerai come connettere server MCP remoti al tuo agente utilizzando i transport standard.
Ciao, sono Alex di DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, episodio 20 di 20. Ogni volta che vuoi che il tuo agent parli con un nuovo database o un'API, finisci per scrivere un wrapper custom. La tua codebase si riempie di integrazioni fragili che si rompono ogni volta che un'API esterna cambia. Questo limita la velocità con cui puoi scalare le tue applicazioni. La soluzione a questo collo di bottiglia dell'integrazione è il Model Context Protocol, o MCP.
Pensa a MCP come all'USB-C per gli agent AI. Standardizza il modo in cui i tool e il context vengono esposti ai Large Language Model. Prima di questo protocollo, se volevi che il tuo agent interrogasse un database e controllasse un servizio meteo, dovevi scrivere funzioni Python specifiche per entrambi, definire manualmente i loro input schema e fare il bind al tuo modello. Con MCP, è il servizio esterno stesso a fornire un'interfaccia standardizzata. Il tuo agent ci si collega semplicemente e capisce all'istante quali tool sono disponibili, quali argomenti richiedono e come eseguirli.
Un malinteso comune è che usare un server MCP remoto significhi che la logica del tuo agent si sposti sulla rete. Ecco il punto chiave. Il tuo agent rimane completamente locale. Il server remoto non esegue il tuo agent e non controlla il suo ragionamento. Si limita a esporre una lista di JSON schema standardizzati che rappresentano i tool che supporta. Il tuo agent locale legge quegli schema, decide quale tool usare in base al prompt dell'utente e invia una richiesta di esecuzione al server. L'esecuzione avviene lì, e il risultato raw viene restituito al tuo agent locale.
In LangChain, gestisci queste connessioni usando il MultiServerMCPClient. Questo componente funge da hub centrale. Permette a un singolo agent di connettersi simultaneamente a diversi server MCP, raccogliendo i tool da tutti quanti. Il client gestisce la comunicazione sottostante usando diversi transport layer. I due transport principali che configurerai sono lo standard input e output, chiamati stdio, e l'HTTP.
Vediamo uno scenario concreto. Stai costruendo un agent che deve eseguire calcoli complessi usando uno script Python locale, e allo stesso tempo fare il fetch di dati meteo in tempo reale da un servizio remoto. Invece di scrivere tool wrapper custom per questi task, configuri il MultiServerMCPClient per gestirli entrambi.
Per prima cosa, definisci il tuo server matematico locale usando il transport stdio. Configuri il client con il comando da eseguire, come l'eseguibile Python di sistema, e il path del tuo script matematico. Quando il client si inizializza, avvia questo script come processo in background locale. Il client LangChain e lo script si scambiano messaggi direttamente attraverso gli stream di standard input e standard output.
Successivamente, definisci il server meteo usando il transport HTTP. Per questo, ti basta fornire l'URL dell'endpoint del servizio meteo remoto. Questo setup di solito si basa sui Server-Sent Events per mantenere una connessione persistente, permettendo all'agent di richiedere azioni e ricevere le risposte in stream via web.
Una volta definiti entrambi i transport, inizializzi il MultiServerMCPClient. Il client si connette immediatamente al processo matematico locale tramite stdio e all'URL del meteo remoto tramite HTTP. Chiede a entrambi i server di fornire le definizioni dei loro tool. Raccoglie gli schema, li unisce in un'unica lista continua e li fornisce al tuo agent LangChain. Dal punto di vista dell'agent, vede semplicemente una lista unificata di tool disponibili. È completamente ignaro del fatto che un tool venga eseguito in un processo binario locale e l'altro faccia partire una richiesta HTTP a un server dall'altra parte del mondo.
Il passaggio a protocolli standardizzati significa che puoi dedicare il tuo tempo a costruire una logica dell'agent migliore, invece di mantenere infiniti API wrapper. Dato che questo è l'ultimo episodio della serie, ti incoraggio vivamente a leggere la documentazione ufficiale di LangChain e a provare a configurare un server MCP locale hands-on. Se hai suggerimenti per argomenti che vorresti vedere nella nostra prossima serie, visita devstories dot eu e mandaci un messaggio. La vera potenza di un agent non sta in ciò che sa, ma in ciò a cui può connettersi in modo trasparente.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
Tap to start playing
Browsers block autoplay
Share this episode
Episode
—
Copy this episode in another language:
Questo sito non utilizza cookie. Il nostro fornitore di hosting potrebbe registrare il tuo indirizzo IP a fini statistici. Scopri di più.