· 6 min · Ingegneria

Memoria persistente per Claude Code: come funziona davvero il contesto tra sessioni

Memoria persistente per Claude Code: come funziona davvero il contesto tra sessioni

Chiudi il portatile venerdì dopo una sessione di tre ore in cui Claude Code ha ristrutturato il tuo modulo di autenticazione, ha imparato che il tuo team usa un wrapper personalizzato Result<T> invece di generare eccezioni e ha finalmente capito perché UserService non può importare da billing/. Lunedì apri una nuova sessione e Claude, con sicurezza, racchiude una nuova funzione in un try/catch e importa il modulo vietato. Tutto ciò che aveva imparato è svanito.

Questo è il problema ergonomico distintivo degli strumenti di programmazione agentica: il modello non ha memoria episodica. Ogni sessione riparte da zero, con l'aggiunta di ciò che hai annotato manualmente. Cerchiamo una soluzione ingegneristica, con onestà, includendo anche le parti che non funzionano.

Il problema fondamentale: le sessioni sono prive di stato per progettazione

Una sessione di Claude Code è una conversazione. Quando termina, la trascrizione viene archiviata e il contesto di lavoro, ovvero la comprensione accumulata attraverso decine di chiamate agli strumenti, svanisce. La sessione successiva ricostruisce il contesto da tre fonti:

  • Il tuo CLAUDE.md files (project and user scope)
  • Qualsiasi file che Claude legge durante la sessione
  • Ciò che scrivi

Nessuna di queste fonti cattura la conoscenza derivata : i vicoli ciechi che hai già esplorato, il motivo per cui esiste una soluzione alternativa insolita, il fatto che hai provato l'approccio A e ha compromesso la CI. Ricostruire quella conoscenza costa token e tempo effettivo a ogni singola sessione.

L'istinto è costruire un livello di memoria: acquisire ciò che è successo, comprimerlo e reinserire la parte rilevante all'avvio. Il progetto open source claude-mem è un'implementazione di riferimento ben strutturata proprio di questo modello e merita di essere studiato, che tu lo adotti o meno.

Il modello architetturale alla base della memoria persistente di Claude Code

Ogni approccio serio alla memoria persistente di Claude Code segue lo stesso ciclo in tre fasi. Comprendere ciascuna fase separatamente ti permette di decidere se svilupparla, acquistarla o saltarla.

Fase 1: Acquisizione

Devi osservare ciò che è accaduto in una sessione. Claude Code espone hook del ciclo di vita hook — comandi shell che si attivano in risposta a eventi. Quelli rilevanti sono:

HookSi attiva quandoUtilizzo
SessionStartInizia una sessioneInserire la memoria
SessionEndTermina una sessioneAvviare l'acquisizione
PostToolUseDopo ogni chiamata a uno strumentoTrasmettere in streaming le attività dettagliate
StopL'agente termina la rispostaSalvare un punto di controllo

Un hook di acquisizione minimale in .claude/settings.json:

{
  "hooks": {
    "SessionEnd": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/mem/capture.sh"
          }
        ]
      }
    ]
  }
}

L'hook riceve su stdin un JSON che descrive l'evento. Per SessionEnd ricevi l'ID della sessione e il percorso della trascrizione, quindi capture.sh può leggere il registro completo della conversazione:

#!/usr/bin/env bash
INPUT=$(cat)
TRANSCRIPT=$(echo "$INPUT" | jq -r '.transcript_path')
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')

# Hand the raw transcript to the compression stage
python3 "$CLAUDE_PROJECT_DIR/.claude/mem/compress.py" \
  --transcript "$TRANSCRIPT" \
  --session "$SESSION_ID"

Un'insidia comune: gli hook hanno un timeout e una trascrizione di grandi dimensioni passata in modo sincrono a un LLM lo supererà. In pratica, l'acquisizione dovrebbe essere avviata senza attenderne il completamento: scrivi il percorso della trascrizione in una coda ed elaboralo in un worker in background, anziché direttamente nell'hook.

Fase 2: Compressione

Le trascrizioni grezze sono inutili come memoria: sono enormi e piene di rumore (dump di file, messaggi ripetitivi degli strumenti, i tuoi errori di battitura). La fase di compressione usa un LLM per distillare la sessione in fatti durevoli. È qui che conviene spendere per una chiamata a Haiku 4.5, non a Opus: la sintesi è esattamente il tipo di attività ad alto volume e basso rischio per cui è pensato il prezzo di Haiku.

import anthropic

client = anthropic.Anthropic()

PROMPT = """You are a memory compressor. From this coding session
transcript, extract ONLY durable facts worth remembering next session:
- Architectural decisions and their rationale
- Conventions discovered (naming, error handling, imports)
- Dead ends already explored (so we don't repeat them)
- Unresolved TODOs

Output JSON: a list of {fact, category, files[], confidence}.
Omit anything transient. If nothing durable happened, output []."""

resp = client.messages.create(
    model="claude-haiku-4-5",
    max_tokens=1500,
    system=PROMPT,
    messages=[{"role": "user", "content": transcript_text}],
)
memories = resp.content[0].text

Nota il campo confidence e l'istruzione esplicita di produrre []. Entrambi servono a limitare i danni del tipo di errore che vedremo più avanti. Archivia l'output in un sistema interrogabile: SQLite con una colonna di embedding, oppure un archivio vettoriale indicizzato per progetto e percorsi dei file.

Fase 3: Inserimento

All'inizio della sessione, recuperi i ricordi rilevanti e li inserisci nel contesto. L'hook SessionStart può scrivere su stdout e quell'output viene aggiunto al contesto di Claude:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "*",
        "hooks": [
          { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/mem/inject.sh" }
        ]
      }
    ]
  }
}

La decisione tecnica cruciale è il filtro per rilevanza. Inserire tutta la memoria è una scelta ingenua e sbagliata: gonfia il contesto e sommerge i fatti utili. Meglio recuperare le informazioni in base al probabile argomento della sessione. Se non puoi ancora determinarlo, inserisci solo fatti ad alta affidabilità validi per l'intero progetto e rendi accessibile il resto tramite un server MCP così Claude può interrogare la memoria su richiesta:

# A tiny MCP tool the agent calls when it wants history
@mcp.tool()
def recall(query: str, files: list[str] = []) -> list[dict]:
    """Retrieve relevant memories about this codebase."""
    return memory_store.search(query, files=files, min_confidence=0.6)

In pratica, questo modello pull funziona meglio del modello push. Invece di indovinare cosa sia rilevante all'avvio, lasci che l'agente chieda «abbiamo già lavorato su questo codice di fatturazione?» proprio quando serve. L'hook fornisce un breve riepilogo sempre presente; il server MCP gestisce il recupero mirato.

Dove questo sistema fallisce — e fallisce davvero

Ho usato livelli di memoria abbastanza a lungo da essere scettico al riguardo. I problemi sono reali e si amplificano a vicenda.

La memoria compressa dall'AI produce allucinazioni. Il compressore è esso stesso un modello linguistico. Ogni tanto registrerà come «decisione» un'idea che in realtà è stata scartata, oppure capovolgerà la motivazione di una scelta. Ti ritrovi così con un ricordo falso dall'apparenza autorevole inserito all'avvio, e l'agente gli accorda più fiducia di quanto dovrebbe. È peggio che non avere memoria, perché presenta con sicurezza informazioni sbagliate. Il campo confidence e la revisione umana dell'archivio di memoria sono le uniche mitigazioni reali.

Il contesto obsoleto è un pericolo silenzioso. Esegui il refactoring di UserService martedì. La memoria di lunedì dice ancora «l'autenticazione si trova in UserService». Nulla la invalida. L'accuratezza dei ricordi si deteriora nel momento in cui il codice cambia e non esiste un segnale chiaro per farli scadere. Collega i ricordi agli hash dei file o agli SHA dei commit e considerali sospetti quando il file sottostante viene spostato.

I costi dei token aumentano a ogni sessione. La memoria inserita è contesto che paghi a ogni turno, che venga usata o meno. Un livello di memoria che inserisce 4K token all'avvio aggiunge quella quantità al costo dell'input per l'intera sessione. Il modello MCP basato sul recupero su richiesta aiuta, ma acquisizione e compressione comportano a loro volta costi ricorrenti.

Ecco un confronto onesto:

ApproccioCosto di configurazioneToken ricorrentiRischio di obsolescenzaIdeale per
CLAUDE.md soltantoMinutiBassi, deterministiciSotto il tuo controlloLa maggior parte dei progetti
Strumenti MCP con ambito limitatoOreSolo su richiestaBassoStato attuale del sistema
Livello di memoria completoGiorniPiù elevati, per sessioneAltoLavoro lungo ed esplorativo

La verità scomoda: probabilmente non ti serve

Prima di sviluppare tutto questo, scrivi un buon CLAUDE.md. Un file curato manualmente che dice «usiamo Result<T>, non sollevare mai eccezioni; UserService non deve importare billing/; l'autenticazione è stata spostata in auth/ nel secondo trimestre» risolve il 80% del problema della memoria senza alcun rischio di allucinazioni e con un costo deterministico. È scritto da una persona, quindi è affidabile per costruzione.

I livelli di memoria giustificano il loro costo in un ambito più ristretto di quanto suggerisca il clamore: lavori esplorativi di lunga durata in cui la conoscenza derivata (vicoli ciechi, indagini lasciate a metà) non può davvero essere scritta in anticipo, perché non la possiedi ancora. Per lo sviluppo ordinario di funzionalità, CLAUDE.md insieme a un paio di server MCP con ambito limitato copre più esigenze di una pipeline di memoria automatizzata, e non ti mente mai.

Se decidi di sviluppare la pipeline, la fase di compressione è quella in cui l'attenzione ai costi conta di più: generare riepiloghi frequenti con Haiku costa poco, ma solo se il prezzo per token è ragionevole fin dall'inizio. È uno dei motivi per cui i team instradano questo tipo di lavoro in background ad alto volume attraverso fornitori come AI Prime Tech.

Indicazioni pratiche

  • Le sessioni non conservano lo stato. La conoscenza derivata — vicoli ciechi, motivazioni, convenzioni — è ciò che va effettivamente perso, ed è costoso ricostruirla.
  • Lo schema è acquisizione → compressione → inserimento. Collega acquisizione e inserimento tramite gli hook di SessionEnd/SessionStart ; esegui l'acquisizione in modo asincrono per evitare i timeout degli hook.
  • Preferisci il pull al push. Fornisci un riepilogo minimo all'avvio, poi esponi uno strumento recall MCP, così l'agente recupera la memoria solo quando è rilevante.
  • Comprimi con Haiku 4.5, contrassegna ogni ricordo con il livello di affidabilità e gli hash dei file sorgente, e considera la memoria sospetta quando i file cambiano.
  • La memoria automatizzata può mentire. Un contesto allucinato e obsoleto è peggio dell'assenza di contesto, perché appare autorevole. Mantieni una supervisione umana sull'archivio di memoria.
  • Prova CLAUDE.md prima. Per la maggior parte dei progetti, un file di contesto scritto a mano insieme a strumenti con ambito limitato supera un livello di memoria completo in termini di costi, affidabilità e manutenzione: ricorri alla persistenza solo quando il tuo lavoro è davvero lungo ed esplorativo.
A

AI Prime Tech pubblica questo blog. Gli articoli sono redatti con l'assistenza dell'AI; verifica nella documentazione ufficiale i dettagli specifici della versione, come gli ID dei modelli, i prezzi e i limiti, prima di farvi affidamento.

Ottieni accesso all'API Claude a un costo inferiore

Un'unica chiave API per Claude Opus 5.5, Sonnet 5, Haiku 4.5 e Fable 5.1, oltre a GPT-6 modelli. Pagamento a consumo, senza abbonamento.

Ottieni la tua chiave API →
AI Prime Tech è un gateway API indipendente di terze parti. Claude™ e Anthropic® sono marchi di Anthropic, PBC. Non si intende suggerire alcuna affiliazione o approvazione.