Salta ai contenuti

Memoria e conoscenza

Senza la memoria, ogni conversazione con un agente riparte da zero: la stessa convenzione va spiegata di nuovo, la stessa decisione ridiscussa, lo stesso vicolo cieco riesplorato. La memoria è l’archivio a livello di spazio di lavoro che sopravvive alle esecuzioni ed esiste perché la conoscenza prodotta da un agente sia ritrovabile da un altro, più tardi.

Ha tre livelli, che rispondono a domande diverse:

  1. Fatti — ciò che è vero (una convenzione, un esito, una decisione).
  2. Policy — ciò che gli agenti devono fare in merito (una regola normativa).
  3. Memoria di lavoro — ciò che un singolo agente stava facendo in quel momento.

La distinzione conta perché questi livelli raggiungono l’agente per vie diverse. I fatti si cercano. Le policy vengono inviate. La memoria di lavoro è privata.

Un MemoryFact è un’unità di conoscenza con ambito limitato a uno spazio di lavoro e a un dominio.

Attributo Che cos’è
domain Il dominio di conoscenza (“conventions”, “decisions”, “codebase”)
topic Un’etichetta breve dell’argomento
content Il testo della conoscenza
confidence 0.0–1.0, inizializzata dalla provenienza e alzata dalle nuove menzioni
memoryType Il tipo di fatto — determina la sua curva di decadimento temporale
veracity Come è stato appreso — inizializza la confidenza e dimensiona ogni incremento per nuova menzione
sourceObservationIds Quali osservazioni hanno portato a esso
supersededBy Il fatto più recente che lo ha sostituito, se esiste
validUntil, recallCount, mentionCount Segnali di scadenza e di utilizzo usati in fase di richiamo

Le ultime due righe sono quelle che sfuggono e sono ciò che decide quale fatto emerge. memoryType porta con sé i parametri di decadimento di Weibull per tipo, quindi un impegno a scadenza svanisce in fretta mentre un fatto di profilo stabile no. veracity registra la provenienza — dichiarato da una persona (peso 1.0), inferito da un agente (0.7), prodotto da uno strumento (0.5), importato (0.6) — e quel peso inizializza la confidenza di partenza del fatto.

I fatti non vengono mai modificati sul posto quando vengono contraddetti. Scrivere un fatto esegue il rilevamento dei conflitti rispetto ai fatti dello stesso dominio e dello stesso argomento e sostituisce il perdente, registrando una riga di conflitto. La traccia di controllo è il punto: puoi sempre vedere che cosa si credeva prima e che cosa lo ha sostituito.

Una MemoryPolicy è una regola normativa derivata dai fatti, con ambito limitato a uno spazio di lavoro e a un dominio, con un flag di attivazione e un requiredRole opzionale.

Ogni policy attiva dello spazio di lavoro viene iniettata in ogni invio, senza filtri: nessun filtro per dominio, ruolo, attività o spazio. Vale la pena saperlo prima di scrivere la ventesima policy, perché le policy competono per la stessa finestra di contesto dell’attività. È anche il motivo per cui requiredRole su una policy è solo indicativo: descrive a chi è rivolta la regola, non impedisce che la regola raggiunga tutti gli altri.

Un MemoryDomain raggruppa fatti e policy all’interno di uno spazio di lavoro. I domini danno alla conoscenza una struttura organizzativa e sono l’unità su cui si scrivono le concessioni di accesso — ma leggi l’avvertenza qui sotto prima di trattare un dominio come un confine di riservatezza.

Un dominio è a livello di spazio di lavoro (architecture) oppure limitato a un repository (repo:<slug>/architecture). Lo stesso nome nei due ambiti indica due archivi indipendenti: un fatto vero per un codebase non sovrascrive quello a livello di spazio di lavoro. search_memory e il preambolo di invio danno la precedenza alla memoria limitata al repository quando l’agente lavora in quel repository; non escludono il resto. Passa repo a propose_fact / propose_policy / search_memory per scrivere o rafforzare quell’ambito.

Il controllo degli accessi è fail-open per le letture

Sezione intitolata “Il controllo degli accessi è fail-open per le letture”

MemoryAccessGrant mappa un ruolo di agente e un dominio su uno di tre livelli di permesso:

Permesso Significato
none Nessun accesso
read Può cercare e recuperare i fatti
write Richiesto da propose_policy. Le scritture di fatti (propose_fact, supersede_fact) non sono vincolate dalle concessioni

L’asimmetria — morbida sulle letture, rigida sulle scritture di policy — è un compromesso deliberato. La memoria è più utile quando circola, e un diniego di lettura produce un agente che sa silenziosamente di meno, non un agente che segnala un problema. Un diniego di scrittura di policy, al contrario, è rumoroso e correggibile, ed è lì che si colloca l’applicazione. Un dominio appena creato inizializza write per ogni ruolo; restringerlo in seguito è una modifica solo RPC, perché non esiste un’interfaccia per le concessioni.

Ogni agente ha una AgentWorkingMemory: un blocco di appunti a testo libero con chiave (spazio di lavoro, agente). Persiste tra le esecuzioni, è privata per quell’agente e viene iniettata nel suo prompt a ogni invio. È dove vive il «ero a metà del refactoring di auth»: lo stato che vale la pena portare all’esecuzione successiva ma non promuovere a fatto durevole.

Al momento dell’invio, il preambolo della memoria è composto da esattamente tre cose:

  • Ogni policy attiva dello spazio di lavoro, come righe - [domain] rule.
  • La memoria di lavoro dell’agente stesso, alla lettera.
  • Un elenco ristretto di fatti corrispondenti per parola chiave per questa attività: al massimo cinque, entro un budget di ~1.200 caratteri e solo quando la descrizione dell’attività è lunga almeno 20 caratteri. Le attività più brevi non ricevono alcun fatto.

L’elenco ristretto si basa solo su FTS/parole chiave ed è limitato di proposito. Calcolare l’embedding di una query è lento e il percorso di invio è l’unico punto in cui la latenza è immediatamente visibile, quindi il percorso semantico lento ne è tenuto deliberatamente fuori. Il preambolo si chiude dicendo all’agente di verificare gli elementi portanti con search_memory, dove risiede il modello di richiamo completo.

Su questo percorso non viene consultata alcuna concessione di accesso. Ciò che l’elenco ristretto trova è ciò che l’agente vede.

Lo strumento search_memory esposto agli agenti ha tre modalità, e sono ricerche davvero diverse:

  • keyword — solo FTS5.
  • semantic — risultati BM25 e vettoriali fusi tramite reciprocal rank fusion.
  • hybrid (il valore predefinito) — richiamo polifonico: quattro voci classificate fuse insieme, poi diversificate.

Le quattro voci sono lessicale (FTS), semantica (KNN vettoriale), temporale (fatti attivi recenti) e grafo — un percorso a due salti sugli archi episodici a partire dai semi lessicali e semantici più forti. La voce del grafo è il motivo per cui gli archi episodici esistono: fa emergere il fatto che è collegato alla tua risposta senza corrispondere a nessuna delle tue parole. Le voci sono ponderate in base a un intento di query classificato (il semantico pesa di più per impostazione predefinita, poi grafo e lessicale, poi la recentezza), il punteggio di ogni candidato è scalato dal suo decadimento di Weibull e l’insieme dei risultati è diversificato con MMR, così cinque riformulazioni di un unico fatto non soffocano quattro fatti diversi.

La ricerca in memoria del desktop e del web è un percorso separato e più semplice: l’operazione RPC memory_fact.search è solo FTS5, perché un client leggero non può inviare l’embedding di una query e il percorso ibrido resta interno all’host. Quindi la classifica che vedi nell’esploratore della memoria non è quella che un agente ottiene da search_memory. È previsto, non è un bug, ma significa comunque che «ho cercato e non l’ho trovato» nell’interfaccia non è una prova che l’agente non lo troverà.

L’esploratore della memoria si trova in Impostazioni → Spazio di lavoro → Memoria (/workspaces/<id>/settings/memory), con le schede Fatti, Politiche e Grafo della conoscenza.

C’è un’asimmetria che sorprende: puoi modificare ed eliminare la memoria, ma non puoi crearla. Né la scheda Fatti né la scheda Politiche offrono un comando per aggiungere. La scrittura avviene dal lato agente, tramite propose_fact e propose_policy (supersede_fact / supersede_policy per sostituirli). remember scrive un elemento del livello hot limitato alla sessione, che consolidate_memory può in seguito promuovere a fatto; record_observation e update_my_notes scrivono il blocco di appunti privato iniettato all’invio. L’esploratore è una superficie di revisione e correzione, non di scrittura: quindi, se vuoi un fatto in memoria, il modo per inserirlo è dirlo a un agente.

Due operazioni di manutenzione sono anch’esse invocate dagli agenti invece che pianificate: consolidate_memory unisce e sfronda i fatti accumulati e harmonize_memory riconcilia le convinzioni divergenti tra agenti. list_memory_conflicts mostra ciò che il rilevamento dei conflitti ha già registrato. Nessun timer le esegue al posto tuo. Le decisioni delle riunioni confluiscono nel dominio decisions quando un passaggio di persistenza di una riunione le registra; non si tratta di un timer sulle esecuzioni concluse degli agenti.