Memoria per agenti di coding: salvarla è la metà facile

Il post sull'Harness della settimana scorsa mostrava un briefing di sessione vero, e una riga lì dentro lavorava più di tutte le altre:

- **MCP Server** [PITFALL] (claude-code/vincent, 1 day ago): every new ID argument
  name must be added to idArgumentResolvers in authz.go, or the cross-org check
  silently skips it.

Un agente che legge quella riga si risparmia il pomeriggio che l'agente precedente ha perso. Bene. Adesso falla invecchiare di sei mesi. La stessa frase, con lo stesso tono sicuro, servita a un agente che lavora su un file che nel frattempo due persone hanno riscritto. Niente, nella riga, sembra diverso. L'agente non ha modo di accorgersene, e nemmeno tu.

Questo è il vero problema della memoria per gli agenti di coding, e non è la parte che costruiscono la maggior parte degli strumenti. Scrivere le cose è la metà facile.

Perché un mucchio di note non può rispondere alla domanda

Le forme comuni di memoria per agenti, oggi, sono un file markdown a cui l'agente accoda righe e un vector store in cui scrive. Entrambi salvano bene. Entrambi recuperano in modo ragionevole. Nessuno dei due può dirti che il terreno sotto una nota si è spostato, perché nessuno dei due sa di cosa parla la nota in senso strutturale. Un vector store sa che una nota è vicina alle parole "gateway" e "headers". Non sa che ApiGateway è un container del tuo sistema, che ha un percorso nei sorgenti, e che il codice a quel percorso ha smesso di corrispondere al modello documentato tre settimane fa.

Un modello di architettura sa tutte e tre le cose. È tutto qui l'argomento per mettere la memoria accanto a uno, ed è l'unica parte di questo post che un altro prodotto non potrebbe copiare in uno sprint.

La memoria adesso è dentro Archyl, su tutti i piani. Ecco cosa fa.

Una memoria è attaccata a un elemento, non a una conversazione

Una memoria è un fatto tipizzato come note, convention o pitfall, agganciato a un elemento C4 o al progetto nel suo insieme. Gli agenti le scrivono via MCP; le persone le scrivono nell'Agent Hub o nel pannello di dettaglio di qualunque elemento sul diagramma.

▶ remember(projectId: …, element: "ApiGateway", kind: "pitfall",
    content: "The gateway strips custom headers longer than 8KB — payloads must go in the body.")

C'è un quarto tipo, session_outcome, scritto automaticamente quando una sessione di lavoro finisce. Una sessione che teneva otto lease produce una memoria attaccata a otto elementi, non otto copie dello stesso paragrafo. La forma conta per il recupero: un agente che chiede di uno qualunque di quegli elementi riceve l'esito una volta sola, invece di rileggersi lo stesso riassunto otto volte solo perché la sessione ha toccato otto cose.

Contenuto e titoli delle memorie sono cifrati a riposo, come ogni altra colonna di contenuto sensibile del prodotto.

Il recall ordina per significato, non per sottostringhe in comune

recall mescola similarità semantica e sovrapposizione di termini, pesate 0.55 contro 0.45. Un agente che chiede di "rate limiting" si riprende la nota che qualcun altro ha scritto sul "throttling", il caso che una ricerca per parole si perde e che un collega non si perderebbe mai.

I vettori sono best-effort per scelta. Senza un provider AI configurato (compatibile OpenAI oppure Ollama) non ci sono vettori e lo scoring resta puramente lessicale, come si comportava prima. Degrada invece di rompersi, e questo conta se fai self-hosting senza provider. E le memorie scritte quando nessun provider esisteva non restano di serie B per sempre: un worker in background recupera i loro vettori appena ne configuri uno.

Scrivere due volte lo stesso fatto lo conferma

Ridire qualcosa che il progetto già sa non crea una seconda copia. Sopra una similarità coseno di 0.94, la scrittura conferma invece la memoria esistente, e la risposta dice deduplicated: true. Un agente che riafferma quello che ha imparato è una prova, non rumore.

Tra 0.82 e 0.94 sta la fascia interessante: vicino, ma non lo stesso fatto. Quelle vengono salvate, e le quasi-corrispondenze tornano in similarTo, così chi scrive può chiamare remember(supersedes: "Old title") di proposito invece di contraddire in silenzio una memoria che è ancora viva e ancora servita.

La memoria impara dall'uso

Ogni recall registra quali memorie ha servito a quale sessione. Quando la sessione finisce, usedMemories nomina quelle su cui si è davvero appoggiata.

Quei due segnali non sono pesati allo stesso modo, ed è voluto. Ricevere una memoria è indiziario. Dire che l'hai usata è una testimonianza. Quindi solo le citazioni alzano il rango di una memoria, in scala logaritmica e con un tetto a 1.8x, così che una memoria popolare non possa seppellire quella più nuova che la corregge. Una memoria servita a cinque sessioni senza una sola citazione riceve un moltiplicatore di 0.75 e viene trattata come rumore.

Trattata come, non cancellata. Niente, nella memoria, viene mai rimosso da un'euristica. Le memorie ignorate finiscono in una coda di revisione con il loro numero di impression, e decide una persona. Lo stesso principio attraversa tutta la funzionalità: corretto, mai cancellato.

Una memoria ha un ciclo di vita

La freschezza decade con un'emivita di 45 giorni dal momento in cui si è saputo per l'ultima volta che la memoria era vera, cioè la sua creazione o la sua conferma più recente. confirm_memory azzera quell'orologio e alza il contatore delle conferme. remember(supersedes: …) sostituisce un fatto che è cambiato: la vecchia versione esce dal recupero ma resta nella storia e nel grafo, così puoi ancora vedere cosa il progetto credeva l'anno scorso.

Sopra ci stanno i pesi per tipo, e hanno un'opinione: un pitfall vale 3.0, una convention 2.0, una semplice note 1.5, un session outcome 1.0. Per un agente che sta per cambiare del codice, "questo ti morderà" batte "ecco cos'è successo".

Quello che invalida davvero una memoria è il drift

Tutto quanto sopra è contabilità decente. Questa sezione è il motivo per cui la memoria appartiene a uno strumento di architettura.

Il tempo è una misura debole della verità. Una convention scritta due anni fa su come funzionano i confini dei tuoi servizi probabilmente è ancora giusta. Una nota scritta il mese scorso su un file che da allora è stato riscritto probabilmente è sbagliata. Il decadimento le tratta allo stesso modo, perché un orologio è tutto quello che ha.

Quello che rende davvero sospetta una memoria è il cambiamento del codice dietro al suo elemento. Archyl lo calcola già, in modo deterministico: il drift score confronta il modello documentato con il repository e nomina gli elementi che non corrispondono più. Lancialo dalla UI, dall'API, oppure a ogni push con la GitHub Action drift-score. La memoria adesso è collegata a quello.

Quando il drift trova un elemento fuori sincrono, ogni memoria attaccata a quell'elemento viene timbrata con il momento in cui è successo. Una memoria confermata l'ultima volta prima di quel timbro descrive qualcosa che nel frattempo si è mosso sotto di lei. Da qui seguono tre cose:

  • Viene declassata nel ranking, con un moltiplicatore di 0.6. Declassata, non nascosta: potrebbe essere l'unica cosa che qualcuno abbia mai scritto su quell'elemento, e nasconderla sarebbe peggio che servirla con un avviso.
  • Compare nella coda di revisione per una persona.
  • L'agente legge un avviso, nel briefing, a parole invece che in metadati:
- **ApiGateway** [PITFALL] [VERIFY — the element drifted since this was written]
  (claude-code/sarah, 96 days ago): the gateway strips custom headers longer than 8KB.

Riconfermare la memoria toglie il flag, perché una conferma risponde direttamente alla domanda del drift: qualcuno ha guardato, e la cosa regge ancora.

Le due metà di quel meccanismo vivono nello stesso prodotto. La conoscenza è qui, e c'è anche il confronto modello-contro-codice che può metterla in discussione. Uno strato di memoria imbullonato su un client di chat ha la prima metà e nessun modo di procurarsi la seconda.

Le memorie si collegano tra loro

Dai un titolo a una memoria e diventa indirizzabile. Qualunque altra memoria può poi referenziarla con [[Title]] nel suo contenuto, alla Obsidian. La stessa sintassi risolve verso gli elementi C4 per nome ([[ApiGateway]]) e verso le decisioni ([[ADR-17]]), e un link a un titolo che ancora non esiste resta in sospeso e si attacca da solo nel momento in cui qualcuno scrive quella memoria.

I link non servono solo alla lettura. recall li segue: le corrispondenze migliori si tirano dietro le vicine collegate, marcate via così vedi cosa le ha portate. Un pitfall sul gateway che punta all'ADR che spiega perché quel confine esiste arriva con il ragionamento attaccato.

Il knowledge map, e il grafo che abbiamo buttato

La prima versione del pannello memoria era un grafo a nodi e archi. Renderizzava, faceva cluster, sembrava proprio il genere di cosa di cui fai lo screenshot. Rispondeva a "quale memoria è collegata a quale memoria", e quella non è una domanda che stesse facendo qualcuno.

Quello che le persone hanno bisogno di sapere è quali parti della loro architettura il progetto capisce e su quali parti nessuno ha scritto una parola. Così l'abbiamo sostituito. Il pannello adesso mostra una cella per elemento C4: cosa se ne sa, quanto è fresca quella conoscenza, quanti pitfall ci stanno sopra, e, per gli elementi senza niente del tutto, un buco visibile. Produce un titolo che nessuna dashboard ti dava prima:

3 of 19 elements documented

Quella frase è scomoda in un modo utile. Il grafo non lo era.

Cosa non fa

Il recall semantico ha bisogno di un provider AI. Nessun endpoint compatibile OpenAI e nessun Ollama significa nessun vettore, e il ranking ricade sulla sovrapposizione di termini. Tutto il resto di questa pagina funziona comunque.

L'abbinamento degli elementi è ancora lessicale. La memoria adesso ordina per significato. Il passo prima, find_relevant_context che sceglie di quali elementi parla il tuo task, continua a dare punteggi per sovrapposizione di parole su nomi, descrizioni, tag e percorsi. Un task su "checkout" continuerà a non far emergere un component chiamato OrderProcessor. L'avevamo segnalato come limite in molti agenti, una sola architettura ed è ancora vero.

Il segnale di utilità esiste solo se gli agenti citano quello che hanno usato. Lo skill archyl-harness insegna all'agente a passare il suo sessionId a recall e a nominare usedMemories quando finisce. Niente lo obbliga. Un agente collegato senza lo skill produce impression e nessuna citazione, e questo si legge esattamente come una memoria che nessuno ha trovato utile.

La memoria ha come ambito il progetto. Una convention valida per tutta l'organizzazione va scritta dentro ogni progetto che ne ha bisogno. È la prossima cosa che stiamo sistemando.

E l'avvertenza onesta d'insieme: la memoria è appena uscita. Non abbiamo numeri di adozione, nessun benchmark, e nessun cliente che ti dica che gli ha fatto risparmiare qualcosa. Quello che c'è sopra è quello che fa il codice, e puoi verificarne ogni pezzo sul tuo progetto.

Da dove partire

Se fai già girare l'Harness, la memoria è già accesa. remember, recall e confirm_memory sono tre dei sedici tool del profilo coding. La versione 0.8.0 del plugin di Claude Code è il pezzo che insegna a un agente le due abitudini da cui dipende il ranking: passare il proprio sessionId a recall, e nominare quello che ha usato quando finisce.

La prima cosa che vale la pena fare non è scrivere memorie. È aprire il knowledge map e leggere la riga di copertura. Qualunque frazione mostri, quella è la frazione della tua architettura che sopravvive alla persona che la capisce quando va in ferie. Indovina il numero prima di guardare, poi guarda.

Poi prendi l'unico elemento con più traffico e meno scritto, e scrivi la trappola che racconteresti a una persona nuova il suo primo giorno. Quella è la memoria che serve al prossimo agente, e finché qualcuno non la digita, nessuna quantità di recupero la troverà.


La memoria fa parte dell'Archyl Harness: le sessioni di lavoro, il preflight gate, l'hook Guard e la Fleet console. Il plugin, gli skill e l'hook Guard e le GitHub Actions sono open source, e il riferimento completo è nella guida all'Harness. Letture correlate: le sessioni di lavoro, molti agenti, una sola architettura, e perché i tuoi agenti hanno un file di regole e non un modello.