Come aggiungere memoria a un agente IA: pattern di persistenza dello stato per la produzione
Gli agenti stateless — quelli che dimenticano tutto quando il Worker termina — vanno bene per compiti una tantum. Nel momento in cui un agente deve ricordare cosa è successo ieri, riconoscere un cliente abituale o costruire su output precedenti, hai bisogno di memoria. Esistono tre pattern: memoria di lavoro (contesto in volo, vive in KV per la durata di un'esecuzione), memoria episodica (cosa è successo e quando, un log interrogabile) e memoria semantica (cosa sai, recuperata tramite ricerca vettoriale o dati strutturati). Collega il pattern giusto al lavoro giusto.
Ogni mercoledì. 28.400+ operatori. Zero riempitivo.
✓ Controlla la tua casella — clicca sul link di conferma per completare l'iscrizione.
✓ Iscrizione completata!
✓ Sei già nella lista.
Indice
Aggiornato giugno 2026.
TL;DR: Gli agenti stateless — quelli che dimenticano tutto quando il Worker termina — vanno bene per compiti una tantum. Nel momento in cui un agente deve ricordare cosa è successo ieri, riconoscere un cliente abituale o costruire su output precedenti, hai bisogno di memoria. Esistono tre pattern: memoria di lavoro (contesto in volo, vive in KV per la durata di un’esecuzione), memoria episodica (cosa è successo e quando, un log interrogabile) e memoria semantica (cosa sai, recuperata tramite ricerca vettoriale o dati strutturati). Collega il pattern giusto al lavoro giusto.
[Lettura dell’operatore] Ho sbattuto contro il muro dell’agente stateless più di una volta. L’agente di risposta social che continuava a presentarsi a clienti con cui aveva parlato 20 volte. L’agente di briefing giornaliero che segnalava lo stesso problema per quattro giorni di fila perché non aveva memoria di averlo segnalato ieri. Aggiungere il tipo giusto di memoria ha risolto entrambi. Ecco cosa uso.
Perché gli agenti stateless continuano a fallire
Un agente stateless inizia ogni esecuzione solo con ciò che gli passi esplicitamente: il prompt di sistema, il messaggio utente e i dati che recuperi al momento dell’invocazione. Non ha consapevolezza delle esecuzioni precedenti, degli utenti precedenti o delle decisioni precedenti.
Per un compito di classificazione una tantum — leggere un commento, restituire una categoria — lo stateless è corretto. È veloce, economico e prevedibile.
La superficie di fallimento appare nel momento in cui hai bisogno di continuità:
- Un agente rivolto ai clienti che non riconosce la storia del cliente
- Un agente di contenuti che raccomanda un articolo che aveva già raccomandato la settimana scorsa
- Un agente di moderazione che continua a ri-escalare un caso risolto
- Un briefing giornaliero che mostra lo stesso avviso obsoleto indefinitamente
Tutti questi sono sintomi dello stesso problema: l’agente non ha modo di trasportare il contesto tra le esecuzioni.
Tre tipi di memoria
Il framework che trovo utile in produzione:
- Memoria di lavoro — ciò che l’agente sa adesso, durante una singola esecuzione. Tenuta in KV o in memoria per la vita dell’invocazione.
- Memoria episodica — cosa è successo e quando. Un log strutturato che l’agente legge all’inizio di ogni esecuzione per orientarsi.
- Memoria semantica — cosa sa del mondo, dei clienti o di una base di conoscenza. Recuperata tramite query strutturate o ricerca vettoriale quando rilevante.
Non hai sempre bisogno di tutte e tre. La maggior parte degli agenti che eseguo ha bisogno di working + episodica. La memoria semantica è la più difficile da costruire e guadagna il suo posto solo quando la base di conoscenza è troppo grande per entrare nella finestra di contesto.
Memoria di lavoro: contesto in volo
La memoria di lavoro è uno stato che vive per la durata di un’esecuzione dell’agente. La forma più semplice sono variabili nell’ambito della funzione. La forma più interessante è una chiave KV condivisa che le sotto-attività all’interno della stessa esecuzione leggono e scrivono.
Il mio agente di risposta social usa la memoria di lavoro per accumulare contesto mentre elabora un batch di commenti in un messaggio di coda. Legge la cronologia delle conversazioni recenti di ogni cliente da KV all’inizio, aggiunge nuovo contesto durante l’elaborazione e riscrive alla fine.
// workers/social-reply.ts
async function processComment(
comment: SocialCommentEvent,
env: Env
): Promise<void> {
// Caricare la cronologia recente di questo cliente da KV (memoria di lavoro)
const historyKey = `customer:${comment.userId}:history`;
const rawHistory = await env.AGENT_KV.get(historyKey);
const history: ConversationTurn[] = rawHistory
? JSON.parse(rawHistory)
: [];
// Costruire un prompt di sistema contestuale dalla cronologia
const systemPrompt = buildSystemPrompt(history);
const response = await anthropic.messages.create({
model: "claude-opus-4-8",
max_tokens: 512,
system: systemPrompt,
messages: [{ role: "user", content: comment.text }],
});
const reply =
response.content[0].type === "text" ? response.content[0].text : "";
// Aggiornare la cronologia — mantenere gli ultimi 10 turni, TTL 30 giorni
const updatedHistory: ConversationTurn[] = [
...history.slice(-9),
{ role: "assistant", content: reply, timestamp: comment.timestamp },
];
await env.AGENT_KV.put(historyKey, JSON.stringify(updatedHistory), {
expirationTtl: 60 * 60 * 24 * 30,
});
await postReply(comment, reply, env);
}Due cose da notare. La cronologia è limitata a 10 turni — inietta una finestra scorrevole, non lasciarla crescere senza limiti. E il TTL è di 30 giorni: se un cliente rimane in silenzio per un mese, la cronologia scade e l’agente ricomincia da capo. Entrambe sono intenzionali.
Memoria episodica: cosa è successo e quando
La memoria episodica è il log dell’agente. Un registro strutturato delle esecuzioni passate che l’agente legge all’inizio di ogni nuova esecuzione per evitare di ripetersi.
Il mio agente di briefing giornaliero mostrava gli stessi avvisi obsoleti ogni giorno perché ogni esecuzione non aveva consapevolezza di ciò che era già stato segnalato. La soluzione: un log strutturato di avvisi passati che l’agente legge prima di generare il briefing.
// workers/daily-brief.ts
interface AlertLogEntry {
id: string;
surfacedAt: string; // timestamp ISO
resolvedAt?: string;
summary: string;
}
async function buildDailyBrief(env: Env): Promise<void> {
const [emails, calendar, tasks] = await Promise.all([
fetchOvernightEmails(env),
fetchTodayCalendar(env),
fetchTopTasks(env),
]);
// Caricare la memoria episodica: cosa è già stato segnalato
const rawLog = await env.AGENT_KV.get("brief:alert-log");
const alertLog: AlertLogEntry[] = rawLog ? JSON.parse(rawLog) : [];
// Filtrare solo gli avvisi recenti e non risolti
const sevenDaysAgo = new Date(
Date.now() - 7 * 24 * 60 * 60 * 1000
).toISOString();
const recentAlerts = alertLog.filter(
(e) => e.surfacedAt > sevenDaysAgo && !e.resolvedAt
);
const brief = await synthesizeBrief(
{ emails, calendar, tasks, recentAlerts },
env
);
// Aggiornare il log con i nuovi avvisi segnalati in questa esecuzione
const newAlerts: AlertLogEntry[] = brief.newAlerts.map((a) => ({
id: crypto.randomUUID(),
surfacedAt: new Date().toISOString(),
summary: a,
}));
const updatedLog = [...alertLog, ...newAlerts].slice(-100); // mantenere gli ultimi 100
await env.AGENT_KV.put("brief:alert-log", JSON.stringify(updatedLog));
await writeToWorkspace(brief.content, env);
}L’agente ora sa cosa ha già detto. Gli avvisi duplicati rimangono fuori dal briefing finché il problema sottostante non cambia. Quando contrassegno un avviso come risolto, scompare dalla lista attiva.
Questo pattern si generalizza: qualsiasi agente che produce decisioni, segnalazioni o raccomandazioni beneficia di un log. Il log è economico (pochi KB in KV), il guadagno è alto (niente più output ridondanti).
Memoria semantica: cosa sai
La memoria semantica è la base di conoscenza. Risponde a “cosa sai su X?” al momento della query, invece di stipare tutto nel prompt di sistema in anticipo.
La forma più semplice è una ricerca strutturata in KV o in un database. Il mio agente di prenotazione di Pickleland consulta i profili dei clienti e le preferenze dei campi prima di redigere le conferme:
// workers/booking-agent.ts
interface CustomerProfile {
userId: string;
preferredCourts: string[];
experienceLevel: "beginner" | "intermediate" | "advanced";
specialNotes: string;
}
async function draftConfirmation(
booking: BookingEvent,
env: Env
): Promise<string> {
// Recuperare il profilo del cliente da KV (memoria semantica — conoscenza fattuale)
const profileKey = `customer:${booking.userId}:profile`;
const rawProfile = await env.AGENT_KV.get(profileKey);
const profile: CustomerProfile | null = rawProfile
? JSON.parse(rawProfile)
: null;
const systemPrompt = profile
? `Redigi conferme di prenotazione personalizzate. Questo cliente preferisce ${profile.preferredCourts.join(", ")}, è un giocatore ${profile.experienceLevel}. ${profile.specialNotes}`
: "Redigi conferme di prenotazione per un impianto di pickleball.";
const response = await anthropic.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 256,
system: systemPrompt,
messages: [
{
role: "user",
content: `Redigi una conferma per: ${JSON.stringify(booking)}`,
},
],
});
return response.content[0].type === "text" ? response.content[0].text : "";
}Per basi di conoscenza più grandi — documentazione di prodotto, una knowledge base di supporto, qualsiasi cosa troppo grande per entrare in una finestra di contesto — hai bisogno di un archivio vettoriale. Il flusso di lavoro è: incorporare la query, recuperare i k chunk più rilevanti, iniettarli nel contesto. Cloudflare Vectorize gestisce questo nativamente se sei già su Workers. Per indici più grandi ho usato Upstash Vector. La scelta dipende dalla scala, non dal principio.
La nota onesta sulla memoria semantica: è la più difficile delle tre da costruire e mantenere. L’indice deve rimanere aggiornato. La qualità del recupero varia. Inizia con ricerche strutturate — KV, una tabella in D1 — e passa alla ricerca vettoriale solo quando l’approccio strutturato non riesce a coprire la superficie di conoscenza di cui hai bisogno.
Il framework decisionale per la memoria
Prima di aggiungere qualsiasi memoria a un agente, rispondi a tre domande:
-
L’agente deve ricordare tra le esecuzioni? Se ogni invocazione è genuinamente indipendente — una traduzione, una classificazione, una generazione una tantum — salta la memoria. Stateless è più semplice e più economico.
-
L’agente si sta ripetendo o sta agendo cieco alla propria storia? Se sì, aggiungi prima la memoria episodica. È la correzione con il minor sforzo e copre la maggior parte dei reclami “l’agente continua a fare X”.
-
L’agente tratta ogni utente o entità in modo identico quando non dovrebbe? Se sì, aggiungi memoria di lavoro (cronologia del cliente, profilo utente) o memoria semantica (un sistema di ricerca o recupero).
L’errore che vedo più spesso: qualcuno aggiunge un’enorme base di conoscenza (memoria semantica) a un agente che in realtà stava fallendo perché non aveva memoria episodica — nessun log di ciò che aveva già fatto. La complessità non corrisponde al problema.
Cosa uso davvero in produzione
Su 30+ agenti:
- Tutti hanno almeno la memoria di lavoro — qualche forma di stato all’interno di un’esecuzione, anche se è solo la finestra di contesto stessa.
- Circa la metà ha memoria episodica — un log delle esecuzioni passate, decisioni o segnalazioni. Questo vale quasi sempre la pena aggiungere.
- Tre o quattro hanno vera memoria semantica supportata da un archivio vettoriale. Questi sono gli agenti che rispondono a domande su una grande base di conoscenza dinamica.
Cloudflare KV è il mio archivio predefinito per la memoria di lavoro ed episodica. È veloce, economico e integrato nativamente in Workers — nessun client extra, nessuna credenziale separata. Il limite: KV è eventualmente coerente e non ottimo per scritture ad alta frequenza. Per gli agenti che scrivono stato molte volte al secondo, uso Durable Objects o un database D1 invece.
Per la memoria semantica supportata da vettori, uso Cloudflare Vectorize per indici da piccoli a medi (meno di ~100K vettori) e Upstash Vector per tutto ciò che è più grande. Entrambi hanno client JavaScript di prima classe.
La conclusione dell’operatore
Aggiungi memoria a un agente solo quando il comportamento stateless sta causando problemi reali — output ripetuti, punti ciechi sulla storia del cliente, ignoranza delle decisioni passate. Poi scegli il livello giusto: memoria di lavoro per il contesto in esecuzione, episodica per ciò che è successo storicamente, semantica per ciò che sai. Inizia con l’episodica se non sei sicuro — corregge il modo di fallimento più comune con la minore complessità. Non ricorrere a un database vettoriale finché non hai esaurito le ricerche strutturate. Il miglior sistema di memoria è il più semplice che fa comportare correttamente l’agente.
Correlato: Lo stack di agenti che uso per gestire 30+ agenti in produzione · Agenti basati su eventi vs. pianificati · Come misuro se un agente IA sta davvero funzionando
Hai bisogno di aiuto per progettare la memoria degli agenti per il tuo caso d’uso? Contattami — progetto sistemi di agenti in produzione per team operativi.
Ogni mercoledì. 28.400+ operatori. Zero riempitivo.
✓ Controlla la tua casella — clicca sul link di conferma per completare l'iscrizione.
✓ Iscrizione completata!
✓ Sei già nella lista.
Articoli correlati
Come Costruire il Tuo Primo Server MCP: Guida Pratica
Aggiornato per il 2026. Il codice TypeScript esatto che uso per costruire e registrare server MCP — trasporto stdio, definizioni di strumenti e come testarli in Claude Desktop in meno di 30 minuti.
AI AgentsPrompt caching con la Claude API: riduci i costi di input senza cambiare modello
Come usare cache_control per ridurre fino al 90% i costi di input della Claude API sugli agenti con prompt grandi e stabili: l'invariante del prefix-match, cosa mettere in cache, gli invalidatori silenziosi e la matematica del punto di pareggio.
AI AgentsClaude Fable 5, prime impressioni: il punto di vista di un operatore
Aggiornato al 2026. Prime impressioni su Claude Fable 5 da chi gestisce oltre 30 agenti in produzione: cosa cambia davvero, l'insidia sui costi di cui nessuno ti avverte e se ti conviene passare.
Ricevi il manuale dell'IA nella tua casella di posta
Ogni mercoledì. 28.400+ operatori. Zero riempitivo.
Controlla la tua casella di posta.
Ti abbiamo inviato un'email di conferma — clicca sul link per completare l'iscrizione. Controlla lo spam se non la vedi entro un minuto.
Sei iscritto.
Benvenuto — la prossima edizione arriverà presto nella tua casella.
Sei già nella lista — cercala ogni mercoledì.