Xiaomi ha rilasciato MiMo Code, un agente di programmazione che gira nel terminale e che — spoiler — è progettato per non perdere il filo anche dopo centinaia di passi di esecuzione. Sì, centinaia. Non è il solito wrapper attorno a un LLM che ti genera una funzione e poi saluta. È un sistema pensato per sessioni lunghe, progetti reali, task che si estendono su giorni. E la licenza? MIT. Quindi sì, fateci quello che volete.
Il progetto nasce da un’osservazione semplice: gli agenti di coding funzionano benissimo finché il task dura meno di 10 turni. Passata quella soglia, iniziano i problemi. Il primo è banale: il context window si riempie. Non importa quanto sia grande — 128K, 200K, un milione di token — se ogni turno aggiunge log di errori, snippet di codice e output di tool, prima o poi finisce lo spazio. A quel punto devi comprimere. E la compressione classica — riassumere tutto e buttare via il resto — ti condanna a un destino simile a quello di Mamba: hai uno stato, ma non puoi più tornare indietro a guardare. Quello che serve non è comprimere meglio. È ricordare meglio.
Il secondo problema è più subdolo: anche se il context è abbastanza grande, la capacità del modello di seguire le istruzioni degrada con l’aumentare della lunghezza. Le intenzioni si diluiscono, gli obiettivi si perdono tra montagne di output di tool, e il modello fatica a capire cosa dovrebbe fare dopo.
Tre assi: calcolo, memoria, evoluzione
Il team di Xiaomi ha diviso il problema su tre scale temporali. Primo: la qualità della singola decisione, limitata dalla computazione. Secondo: la continuità su più turni dentro la stessa sessione, limitata dalla gestione dello stato. Terzo: il miglioramento tra sessioni diverse, limitato dal meccanismo di distillazione dell’esperienza. MiMo Code è costruito attorno a queste tre leve.
Computazione: spendere token dove conta
Quando un task arriva a cento passi, ogni errore si moltiplica. E spesso l’agente non ha nessun segnale esterno che lo corregge. La risposta è semplice: spendi più compute. Max Mode genera cinque candidati in parallelo per ogni turno. Ognuno ragiona e pianifica indipendentemente, ma nessuno esegue. Poi lo stesso modello fa da giudice, confronta i cinque piani e sceglie il migliore. Costa 4-5 volte i token, ma su SWE-Bench Pro porta un +10-20% di performance. Temperatura a 1, quindi i cinque sample quasi mai convergono. Se convergono, è un segnale forte. Se divergono, meglio avere un giudice a bassa temperatura che sceglie il piano più robusto.
Poi c’è Goal, che risolve un problema diverso: l’agente che dichiara di aver finito quando non ha finito. Classico. Vede qualche progresso, si convince che il lavoro sia fatto, e chiede conferma. Pericoloso in esecuzione automatica, perché non c’è nessuno lì a dirgli ‘no, manca questo’. Goal è un verificatore indipendente: tu definisci in linguaggio naturale la condizione di stop — tipo ‘tutti i test passano e il codice è committato’ — e ogni volta che l’agente tenta di terminare, parte una chiamata separata che controlla se la condizione è davvero soddisfatta. Se no, feedback e si continua. Se il task è impossibile, viene marcato come tale. Falsi positivi sotto lo 0,5%, che è accettabile.
Max Mode è parallelo: stesso passo, N volte il compute. Goal è seriale: stesso task, più tempo speso in auto-verifica. Puoi attivarli entrambi.
Memoria: sessioni infinite, finestre finite
Qui diventa interessante. Una sessione è una sequenza di turni che si accumulano da sinistra a destra. La finestra ha un limite. Prima o poi si riempie. MiMo Code interviene prima che accada, in punti fissi chiamati checkpoint. A ogni checkpoint, il runtime lancia un writer subagent indipendente: legge la conversazione fino a quel punto e scrive un file strutturato su disco. L’agente principale continua a lavorare, il writer gira in parallelo. Non si disturbano.
Quando la finestra si avvicina al limite vero, il runtime fa un rebuild: taglia la finestra corrente, ne apre una nuova, e ricostruisce il contesto usando i file persistiti come seed. L’agente si sveglia nella nuova finestra con lo stato già pronto davanti, e continua. Dal punto di vista del modello, la conversazione non si è mai interrotta. Dal punto di vista del runtime, è iniziata una nuova finestra fisica. Una sequenza che finisce con un rebuild è un cycle. I cycle non hanno limite superiore. La sessione logica è una catena di cycle, e quella catena non ha lunghezza massima.
Perché estrarre presto? Intuizione sbagliata comune: aspettare che la finestra sia quasi piena. Il team ha scoperto che è esattamente il contrario. Primo: la capacità del modello degrada quando il context è quasi pieno. ‘Lost in the middle’ — l’attenzione al centro crolla, l’affidabilità dell’estrazione strutturata pure. Chiedere al modello di fare la compressione più critica proprio quando la sua capacità di comprimere è al minimo è un pessimo trade-off. Secondo: l’estrazione richiede spazio. Il writer deve leggere, interpretare, e produrre output strutturato — tutto dentro la stessa finestra. Al 95% di utilizzo non c’è spazio per pensare. Al 30% ce n’è in abbondanza.
Quindi i checkpoint scattano molto prima del limite — circa al 20%, 45%, 70% del budget. Ogni trigger è un aggiornamento incrementale del precedente. Il rebuild finale non è una compressione frettolosa, ma il momento in cui i record strutturati accumulati diventano contesto di lavoro.
Il writer: un estrattore separato
Reazione naturale: fai mantenere le note all’agente principale. Non funziona. Chiedere a un modello che sta debuggando un problema complesso di mantenere anche un log strutturato lo fa lavorare peggio su entrambi i fronti. Soluzione: l’agente principale non mantiene la propria memoria. L’estrazione è completamente fuori dal loop principale, triggherata dal runtime ed eseguita da un writer subagent indipendente — che non condivide né l’attenzione né il budget di token dell’agente principale.
Il writer scrive un file di checkpoint con struttura fissa — 11 campi: intent corrente, azione successiva, vincoli di lavoro, albero dei task, lavoro corrente, file coinvolti, scoperte cross-task, errori e fix, stato del runtime, decisioni di design, note varie. E quando serve, aggiorna la memoria a livello di progetto. Per ogni file strutturato, esattamente un attore ha i permessi di scrittura. Single-writer è l’invariante più semplice per prevenire stati inconsistenti da scritture concorrenti.
Quattro layer di memoria
Il writer non scrive un solo file. Mantiene un sistema di memoria stratificato, con lifecycle diversi:
Session memory (checkpoint.md): vive solo dentro la sessione logica corrente. Stato completo della sessione.
Project memory (MEMORY.md): conoscenza persistente a livello di progetto — decisioni architetturali, regole utente, fatti tecnici verificati ripetutamente. Quando un’osservazione si stabilizza su più checkpoint di sessione, il writer la promuove da session a project.
Global memory: preferenze utente che valgono cross-progetto.
History: trace SQLite completo di ogni sessione — testo grezzo di ogni messaggio, ogni chiamata a tool, senza indicizzazione. Quando un dettaglio non si trova nella memoria strutturata, l’agente usa il tool history per risalire al record originale.
Le relazioni: i layer superiori sono più raffinati, più persistenti, più piccoli. I layer inferiori sono più completi, più grandi, più lenti. Il writer distilla verso l’alto, la history fa da fallback verso il basso.
L’agente principale ha accesso read-only ai file strutturati, con un’eccezione: notes.md, uno scratchpad free-form a livello di sessione. L’agente può appendere scoperte sparse in qualsiasi momento; a ogni checkpoint, il writer legge, smista il contenuto nei campi strutturati appropriati, e poi svuota. È l’unico canale di scrittura disponibile all’agente principale.
Rebuild injection
Quando il runtime fa un rebuild, assembla i file persistiti in un prompt stratificato e li inietta nella nuova finestra, con un limite di token indipendente per ogni sezione. Ordine approssimativo: task list (l’agente deve prima sapere cosa deve fare) → checkpoint di sessione → slice letterali dei messaggi utente recenti (per evitare che la riscrittura del writer drifti via dall’intent originale) → project memory → global memory → notes → indice dei path dei file di memoria leggibili on-demand → reminder finale che dice all’agente cosa fare dopo.
Anche se ogni sezione raggiunge il limite, il contenuto totale iniettato resta sotto i 65K token circa — ben dentro il budget di lavoro di qualsiasi context window ragionevole. Dopo aver recuperato lo stato da queste informazioni, l’agente continua direttamente, senza dover riconfermare l’obiettivo o rileggere file già processati.
Evoluzione: imparare tra sessioni
Le due sezioni precedenti risolvono come lavorare bene dentro un singolo turno e una singola sessione. Ma in sviluppo reale, un utente può interagire con lo stesso progetto decine o centinaia di volte. Se tutta l’esperienza si perde alla fine di ogni sessione, l’agente non può mai accumulare dal lavoro passato. Deve riscoprire gli stessi vincoli di progetto e ripetere gli stessi errori ogni volta.
MiMo Code mantiene un file di memoria a livello di progetto (in Markdown), che persiste conoscenza cross-sessione: background del progetto, regole specificate esplicitamente dall’utente, decisioni architetturali e razionale, fatti tecnici verificati ripetutamente.
Perché file invece di un pure vector database? Reviewability. Una volta che la memoria influenza il comportamento successivo dell’agente, l’utente deve poter vedere cosa il sistema ha ricordato, cancellare entry sbagliate, modificare conoscenza obsoleta. I file possono essere manipolati direttamente con tool standard di lettura/scrittura senza richiedere un’interfaccia dedicata per ogni operazione di manutenzione. Un indice full-text fornisce retrieval veloce sopra i file.
Dream e Distill
Il file di memoria di progetto cresce nel tempo. Senza manutenzione, entry obsolete, record duplicati, riferimenti a file invalidi si accumulano, abbassando il rapporto segnale/rumore.
Dream viene triggherato automaticamente ogni 7 giorni. Un agente indipendente legge le conversazioni storiche delle sessioni e il file di memoria esistente, poi esegue merging, deduplicazione, verifica di validità dei path, compressione — convergendo memorie sparse in una rappresentazione compatta dello stato corrente e aggiornando la global memory.
Distill viene triggherato automaticamente ogni 30 giorni. Anche questo eseguito da un agente indipendente che legge le sessioni storiche, ma il focus non è la conoscenza — è il processo. Identifica pattern di lavoro ricorrenti e li solidifica in skill riusabili, comandi CLI, agenti custom, documenti SOP, e artefatti simili.
Valutazione: benchmark e A/B reali
Sui tre benchmark mainstream (SWE-Bench Pro incluso), MiMo Code + MiMo-V2.5-Pro batte Claude Code + Claude Sonnet 4.6. Ma — e questo è importante — questi benchmark misurano ancora capacità one-shot di problem-solving su singoli issue a livello repository. La maggior parte degli obiettivi di design di MiMo Code — memoria multi-turno, mantenimento di stato in background, verifica di completamento, evoluzione cross-sessione — mostra il suo valore principalmente in scenari di sviluppo reale che continuano per decine di turni. Questi vantaggi si riflettono pienamente solo nell’uso effettivo.
Per questo hanno costruito un A/B test double-blind human-in-the-loop: nei progetti reali degli sviluppatori, due agenti anonimi vengono lanciati in parallelo per lo stesso task. Dopo che completano indipendentemente, lo sviluppatore assegna punteggi, con scoring automatico della traiettoria e quantificazione del diff usati per triangolazione. Beta interna su 576 sviluppatori, 474 repository privati reali, 1.213 coppie A/B con giudizi win/loss chiari.
Risultato: il vantaggio di MiMo Code cresce con la complessità del task. Quando il numero di step di esecuzione è entro 200, i win rate dei due sistemi sono vicini al 50%. Quando gli step superano i 200 (inclusa interazione multi-turno con l’utente), il win rate di MiMo Code sale oltre il 65%. Che tradotto significa: più il task è lungo, più MiMo Code tiene il passo meglio di Claude Code.
Usarlo
Installazione one-line, o via npm. Al primo avvio, MiMo Code ti guida nella scelta del metodo di accesso al modello: MiMo Auto (gratis per un periodo limitato di un mese, basato su MiMo-V2.5 e con supporto per context da 1 milione di token), login alla piattaforma Xiaomi MiMo, import dalla configurazione di Claude Code, o modello custom.
Il codice è su GitHub, MIT license. Il paper tecnico è denso — vale la pena leggerlo se vi interessa capire come si costruisce un agente che può davvero continuare per giorni senza dimenticare dove aveva messo le chiavi.
