Un Coding Agent risparmia token ricordando le vecchie modifiche? Dentro Singularity
Ieri hai chiesto a un Coding Agent di aggiungere una scorciatoia da tastiera a un repository. Oggi gli chiedi una modifica simile. Potrebbe ricominciare cercando gli stessi file, rileggendo gli stessi test e inciampando negli stessi problemi. È normale che la prima esplorazione abbia un costo. Ma perché pagarlo di nuovo?
Ho scoperto Singularity attraverso un post su Show HN. Il progetto open source prova a trasformare modifiche già completate in workflow riutilizzabili: dove intervenire, come verificare il risultato e quali problemi evitare. Quando arriva un nuovo compito, recupera i passaggi che potrebbero essere utili e li propone all’agente.
L’idea mi interessa, ma la domanda che volevo approfondire era un’altra: quando un ricordo viene recuperato, cosa dimostra che sia ancora adatto al compito e al repository di oggi?
Ho esaminato Singularity al commit 9d241f2 e ho eseguito un piccolo test sintetico senza chiamate a modelli. Prima di tutto il limite: non ho installato né eseguito la CLI di Singularity in un test end-to-end e non ho confrontato i costi reali dei token in Claude Code o Codex. Ho ricostruito in modo indipendente alcune regole di corrispondenza viste nel sorgente, per capire in quali situazioni possano recuperare un ricordo sbagliato.
Non ricorda tutta la chat, ma il percorso del lavoro
Secondo il README del commit fissato, Singularity raccoglie esperienza dopo modifiche riuscite e usa un modello per sintetizzare esperienze ricorrenti in workflow. Un workflow potrebbe indicare quali file si modificano di solito per una certa funzionalità, quali comandi di test servono e dove i tentativi precedenti erano falliti.
Non equivale a salvare per intero la cronologia di una conversazione. Una chat contiene tanti tentativi utili soltanto in quel momento; il workflow cerca di conservare i passaggi che vale la pena ripetere. Qui analizzo il riuso dei passaggi e dei loro indizi testuali, non tutti gli eventuali sistemi di cache presenti nel progetto. Anche una posizione di file corretta in passato va ricontrollata dopo una modifica della struttura del repository.
Inoltre ci sono due voci di costo distinte. Imparare un workflow può richiedere chiamate a un modello. Selezionare passaggi usando indizi già generati può invece non richiederne. Il percorso workflows-cues rappresenta quest’ultimo caso.
Questo non significa che Singularity funzioni sempre senza costi di modello. Nel codice di valutazione fissato, StepSelector.ts chiama un modello per decidere quali passaggi siano applicabili. Memory.ts, invece, descrive workflows-cues come selezione tramite indizi, senza modello. Uno dei percorsi chiede a un modello di scegliere i passaggi; l’altro confronta frasi preparate in anticipo. Le strutture di costo sono diverse, ma non ho confrontato tempi o token dei due percorsi su attività reali.
Che cosa controlla davvero la ricerca senza modello
Ho seguito il codice di apps/cli/src/workflows/Cues.ts.
Il meccanismo di base è semplice: normalizza il testo del compito rispetto a maiuscole e minuscole, cerca di rimuovere clausole negative con parole come not, never e without, poi controlla se il testo rimasto contiene espressioni-indizio generate in precedenza per un workflow. Il workflow viene selezionato quando corrisponde un indizio positivo e non scatta un indizio di esclusione. Anche i singoli passaggi possono essere filtrati tramite indizi.
Il modulo non chiede a un modello «questi due compiti hanno un significato simile?». È più simile a una tabella ben organizzata di regole sulle stringhe. Questo lo rende economico, veloce e ripetibile. Il rovescio della medaglia è che parole uguali non significano intenzioni uguali.
Immaginiamo che il trigger sia keyboard shortcut. La richiesta «Add a keyboard shortcut» dovrebbe corrispondere. Anche «Review keyboard shortcuts in documentation only» contiene le stesse parole, ma chiede soltanto di controllare una documentazione, non di modificare una funzionalità.
Il sorgente gestisce alcune negazioni esplicite. Non significa però che sappia comprendere ogni negazione complessa, vincolo implicito o intenzione distribuita su più frasi. Il matcher individua ricordi candidati; da solo non dimostra che seguire i loro passaggi sia corretto.
Cinque input sintetici per verificare il limite
Partendo dal Cues.ts fissato, ho riscritto manualmente e in modo indipendente la parte centrale della normalizzazione del testo, del filtro sulle clausole negative e delle corrispondenze positive e negative. Il test usa soltanto la libreria standard di Node.js. Non è la suite ufficiale del progetto e non garantisce la copertura di tutti i casi limite del codice originale. Non ho installato Singularity, collegato modelli o operato su un repository reale.
Lo script e i risultati leggibili da macchina sono conservati in registrazioni di ricerca private; non ne è disponibile una copia pubblica da scaricare. La tabella mostra tutti e cinque i risultati. Si tratta di una riproduzione sintetica delle regole ispirate al sorgente, non di un test completo della CLI.
| Input artificiale | Risultato | Che cosa mostra |
|---|---|---|
| Aggiungere una scorciatoia da tastiera | Corrisponde | Recupero pertinente previsto |
| Correggere una connessione al database | Non corrisponde | Compito estraneo escluso |
| Dire esplicitamente di non aggiungere una scorciatoia | Non corrisponde | Negazione semplice gestita |
| Controllare solo le descrizioni delle scorciatoie nella documentazione | Corrisponde | Le parole comuni provocano falsi richiami |
| Aggiungere una scorciatoia, ma il vecchio file ricordato è stato eliminato | Corrisponde | Il matcher non verifica se il file esiste |
Avevo stabilito gli esiti attesi prima di eseguire il test, in base alle regole semplificate: i compiti pertinenti dovrebbero corrispondere, quelli estranei e quelli esplicitamente negati no. Una richiesta che menziona solo la documentazione dovrebbe comunque corrispondere se contiene la frase trigger. Anche il file eliminato non dovrebbe cambiare il risultato, perché il controllo del testo non consulta il file system.
Tutte e cinque le asserzioni hanno prodotto l’esito previsto. È essenziale notare che gli ultimi due casi sono risultati indesiderabili progettati apposta. «5/5 superati» non è una misura di accuratezza e non prova che cinque compiti reali siano stati svolti correttamente. Conferma solo le previsioni fatte per questo matcher sintetico.
Il caso del file obsoleto è il più importante. Il confronto testuale di cueChoice non può sapere se un file sia stato spostato, eliminato o ristrutturato. Un agente che esegue i passaggi dopo il recupero potrebbe verificare il repository e accorgersi del problema. Ma la strada vecchia potrebbe già essergli stata suggerita. Un ricordo trovato è un suggerimento, non una prova dello stato attuale del codice.
Come leggere i risparmi di token dichiarati nel README
L’autore ha pubblicato un confronto su compiti in Excalidraw. In un’attività lunga particolarmente adatta alla memoria appresa, i token dichiarati scendono da circa 1,90 milioni a 423.000, il costo da circa 0,81 a 0,30 dollari e la mediana dei turni da 28,5 a 9,5. Tuttavia ogni condizione conta solo tre o quattro esecuzioni circa e le prove riguardano pochi repository.
I numeri meritano attenzione, ma restano risultati dichiarati dall’autore per attività specifiche. Un tipo di modifica mai incontrato o una correzione minuscola e irripetibile potrebbe beneficiarne pochissimo. Anche imparare i workflow comporta un costo.
Risparmiare token nella lettura dei file non equivale necessariamente a ridurre il costo totale del lavoro. Se viene richiamato un percorso sbagliato, l’agente potrebbe dover indagare di più. Dopo un refactoring importante, una memoria vecchia può persino rallentare la soluzione.
Non ho ripetuto il confronto tra modelli pubblicato dall’autore e non ho misurato token o dollari reali. Per questo non propongo una percentuale di risparmio verificata indipendentemente. Servirebbero gli stessi compiti reali eseguiti con e senza memoria, includendo le chiamate necessarie ad apprendere, le correzioni dei falsi richiami e il costo fino al completamento finale. Il mio test non contiene quei dati.
Come la userei io
In repository con operazioni ripetitive, struttura relativamente stabile e comandi di verifica chiari, proverei un sistema di memoria dei workflow. Tratterei però ogni memoria come un indice da controllare, non come un ordine che l’agente debba eseguire alla cieca.
Ogni workflow potrebbe avere il commit di provenienza, i percorsi coinvolti, la data dell’ultima verifica e le condizioni in cui è applicabile. Prima di usarlo, verificherei che i file esistano ancora e che i test funzionino. Se più recuperi consecutivi richiedessero correzioni manuali, farei riapprendere o disattiverei quel workflow. Sono precauzioni che suggerisco, non funzionalità di scadenza automatica che ho verificato nell’attuale Singularity.
La scelta di installare un sistema simile dovrebbe dipendere dalla ripetitività delle attività, non da una percentuale di risparmio pubblicitaria. Se ogni volta lavori su repository, linguaggi e problemi differenti, mantenere le memorie potrebbe costare più di quanto immagini.
Vorrei vedere un confronto pubblico sugli stessi compiti reali con richiami utili, falsi richiami, memorie obsolete, costo di apprendimento e costo finale complessivo nella stessa tabella. Solo allora si potrà capire se la memoria elimina davvero lavoro ripetitivo o sposta una parte del costo dall’esplorazione alla manutenzione dei ricordi.
Riferimenti: repository Singularity · codice fissato del matching delle piste · valutazione e limiti dichiarati dall’autore