Torna al blog
Remi d'Almeida8 min di lettura

La modalità YOLO senza affidare il mio portatile a un agente IA

Perché, quando sviluppo Aitopus, avvio ogni sessione con un agente di programmazione in una Docker Sandbox e uso un kit di progetto riutilizzabile per rendere semplice e ripetibile una configurazione nativa complessa.

Zed mostra le modifiche al codice Rust di Aitopus accanto a una sessione con un agente di programmazione avviata in una Docker Sandbox
Una tipica sessione di sviluppo di Aitopus in Zed, con l’agente di programmazione al lavoro in una Docker Sandbox.
In questa pagina

Gli agenti di programmazione più capaci sono anche i più frustranti quando interrompono di continuo il lavoro per chiedere il permesso di eseguire un comando.

Installare questo pacchetto? Sì. Eseguire i test? Sì. Consentire a uno script di build di invocarne un altro? Sì.

Prima o poi, la tentazione è inevitabile: attivare la «modalità YOLO» e lasciare che l’agente lavori.

Sul mio portatile, però, questo equivale a prendere due decisioni ben distinte:

  1. Voglio che l’agente lavori senza dovermi aspettare.
  2. Sono disposto a mettergli a disposizione tutto ciò a cui può accedere il mio account utente.

Sono d’accordo con la prima. Non con la seconda.

Sviluppare Aitopus mi pone costantemente davanti a una domanda: dove viene eseguito un processo di IA e a quali risorse può accedere? Applico lo stesso criterio al mio ambiente di sviluppo.

Per questo, quando lavoro al progetto, avvio ogni sessione con un agente di programmazione in una Docker Sandbox. Aitopus ha un’ampia base di codice Rust e un ambiente di compilazione nativo complesso. L’agente deve quindi poter installare dipendenze, compilare il codice, eseguire test e avviare script senza poter agire liberamente sul mio portatile.

Il flusso di lavoro si fonda su quattro principi: isolare l’agente in una microVM, scegliere come condividere il repository, limitare l’accesso alla rete ed esaminare ciò che produce come se fosse codice non affidabile.

Perché non usare semplicemente un container?

Un normale container di sviluppo è utile per incapsulare le dipendenze, ma non costituisce automaticamente una solida barriera di sicurezza.

La scorciatoia più comune consiste nel montare il socket Docker dell’host, così che uno strumento all’interno del container possa creare e avviare altri container. Di fatto, questo gli conferisce il controllo del daemon Docker dell’host. Con un agente autonomo, si vanifica così buona parte dell’isolamento che si voleva ottenere.

Docker Sandboxes adotta un approccio diverso. Ogni sandbox viene eseguita all’interno di una microVM, con ambiente Linux, file system, rete e Docker Engine propri.

All’interno di questo ambiente, l’agente può:

  • installare pacchetti con sudo
  • creare immagini Docker
  • avviare container
  • eseguire Docker Compose
  • modificare il proprio ambiente di sviluppo

Può fare tutto questo senza avere accesso al daemon Docker dell’host né ai file esterni allo spazio di lavoro che ho scelto espressamente di condividere.

Questo non impedisce all’agente di causare danni. Significa, però, che la portata dei possibili danni è più limitata e più facile da comprendere.

Modalità diretta e modalità clone

Docker Sandboxes mette a disposizione due modalità utili per condividere un progetto.

Modalità diretta

Il progetto viene montato in lettura e scrittura. Le modifiche apportate dall’agente compaiono immediatamente nel mio checkout locale. Uso questa modalità per il normale lavoro di sviluppo, perché io e l’agente possiamo lavorare sugli stessi file.

Il compromesso è evidente: l’agente può ancora danneggiare il repository.

Modalità clone

La modalità clone offre un isolamento maggiore quando uso agenti che conosco poco, conduco esperimenti potenzialmente distruttivi o lavoro in parallelo. Il repository dell’host viene montato in sola lettura, mentre l’agente lavora su un clone privato all’interno della sandbox. Le modifiche arrivano nel checkout locale solo quando decido esplicitamente di importarle.

La modalità clone impedisce di modificare il repository, non di leggerlo. I file al suo interno, compresi quelli ignorati da Git, possono comunque rimanere visibili tramite il montaggio in sola lettura. I segreti devono quindi restare fuori dallo spazio di lavoro.

Il kit di progetto riutilizzabile

Una sandbox vuota risolve il problema dell’isolamento, ma non quello della configurazione.

Non volevo che ogni nuova sessione iniziasse con una lunga spiegazione delle librerie native richieste dal progetto, delle versioni degli strumenti necessarie per la build o di come configurare l’ambiente per i modelli locali.

Docker Sandboxes permette di definire configurazioni di progetto riutilizzabili chiamate kit. Il kit del mio progetto descrive gli strumenti e l’ambiente di cui l’agente ha bisogno, tra cui:

  • dipendenze native per la build
  • strumenti di sviluppo Rust
  • dipendenze per i test nel browser
  • variabili d’ambiente
  • accesso alla rete necessario durante la configurazione

I dettagli della configurazione contano meno del principio: le informazioni necessarie a preparare l’ambiente restano nel progetto, invece di dover essere ricostruite ogni volta a memoria.

Un agente IA può abbozzare uno spec.yaml specifico per il progetto esaminando il repository e ponendo domande su ciò che non può dedurre: pacchetti di sistema, comandi di build e test, servizi in background, accesso alla rete, porte e credenziali gestite dall’host.

Per un’applicazione web, il kit può includere Playwright e un browser headless da eseguire nella sandbox. L’agente può così effettuare il rendering delle pagine, eseguire test end-to-end e acquisire screenshot per una verifica visiva. Se l’agente e il modello scelti accettano immagini in input, l’agente può esaminare anche quegli screenshot. Il file generato deve comunque essere rivisto e validato con sbx kit validate.

È anche un registro di problemi e soluzioni

La prima versione del kit era molto più essenziale. Da allora, l’ho ampliato ogni volta che i fatti hanno smentito una delle mie ipotesi.

In una versione, il contenuto di PATH veniva sostituito anziché esteso. Di conseguenza, scomparivano i percorsi aggiunti dal runtime della sandbox e l’agente di programmazione non riusciva ad avviarsi correttamente.

Un’altra versione impostava RUSTFLAGS a livello globale, sovrascrivendo per errore un flag specifico del progetto usato in CI per escludere i test che effettuano richieste reali ai provider di modelli.

Quei problemi avrebbero potuto rimanere nella cronologia della shell o in appunti personali. Ora, invece, le correzioni fanno parte della configurazione e ne documentano le ragioni.

È questo il vero valore del kit. Non si limita a installare software: rende le conoscenze sull’ambiente parte del codice del progetto, così da poterle esaminare, versionare e migliorare.

Il flusso di lavoro quotidiano

Per il normale lavoro di sviluppo, creo una sandbox a cui assegno un nome e che configuro con il kit del progetto:

# Tra gli altri agenti supportati ci sono claude, gemini e opencode.
sbx run codex \
  --name aitopus \
  --kit ./sandbox/aitopus/

Il comando usa il montaggio diretto del progetto, quindi le modifiche dell’agente compaiono nel mio albero di lavoro.

Quando serve un isolamento maggiore, posso invece creare una sandbox separata in modalità clone:

sbx run --clone --no-share-skills codex \
  --name aitopus-review \
  --kit ./sandbox/aitopus/

La configurazione iniziale può richiedere parecchio tempo, perché l’ambiente comprende toolchain native, binari dei browser e dipendenze per la build. Il vantaggio è che lo stato della sandbox e le cache di compilazione rimangono disponibili tra una sessione e l’altra.

Terminata la configurazione iniziale, posso ricollegarmi alla sandbox già creata anziché ricostruire da zero l’intero ambiente.

Definire con cura l’accesso alla rete

Un agente di programmazione ha comunque bisogno di internet. Potrebbe dover contattare il provider del modello, i registri dei pacchetti, i repository del codice sorgente e gli archivi delle release.

Per le sessioni più delicate, parto da regole di rete restrittive e consento l’accesso soltanto ai servizi necessari all’agente e al processo di build.

Il proxy per le credenziali fornito da Docker Sandboxes permette di lasciare sull’host le credenziali supportate e di associarle soltanto alle richieste approvate. In questo modo evito di copiare nella sandbox una chiave API di lunga durata e di dimenticare in seguito dove l’ho salvata.

Anche i controlli di rete hanno dei limiti. Un servizio autorizzato può ricevere le informazioni che l’agente gli invia. Limitare le destinazioni riduce l’esposizione, ma non significa che ogni richiesta in uscita sia opportuna.

Ciò che la sandbox non risolve

Una sandbox limita l’accesso, ma non garantisce che il codice sia corretto. Esamino il lavoro dell’agente come se arrivasse da una pull request di cui non mi fido.

  • Correttezza. L’agente può comunque introdurre una dipendenza vulnerabile, fraintendere un requisito o produrre codice che supera i test ma non rispetta le scelte progettuali.
  • Effetti sull’host. In modalità diretta, l’agente può modificare ben altro oltre ai normali file sorgente. Gli hook Git, i workflow di CI, le attività dell’IDE, gli script di build e le configurazioni dell’agente potrebbero eseguire codice sull’host in un secondo momento.
  • Modifiche al repository. La modalità clone impedisce di scrivere direttamente nel checkout dell’host, ma qualsiasi modifica importata nel progetto deve comunque essere esaminata.
  • Piattaforme di destinazione. Una sandbox Linux è un ambiente di lavoro più sicuro e coerente, non la prova che l’applicazione finita funzioni correttamente su ogni piattaforma di destinazione.

L’autonomia va definita nell’ambiente

Le richieste di autorizzazione sono utili quando non esiste un confine più solido. Non possono però sostituirne uno progettato con cura.

All’interno di una microVM dedicata, l’agente può lavorare con ampio margine d’azione. Può installare compilatori, modificare pacchetti, creare container e completare un intero ciclo di debug senza attendere un’autorizzazione dopo ogni comando.

Scelgo deliberatamente di dargli accesso al repository del progetto, ma non al daemon Docker dell’host né a file estranei al progetto. Il resto del computer rimane fuori dalla sua portata.

Questo approccio non è soltanto più sicuro: rende anche il lavoro più produttivo.

Dedico meno energie alle approvazioni di routine, passo meno tempo a riparare le toolchain locali e non devo dilungarmi nei prompt per spiegare l’ambiente di sviluppo. L’agente ha la libertà necessaria per lavorare; io mantengo un perimetro chiaro, che posso controllare.

Lo stesso principio vale per l’IA locale: scegliere dove avviene l’elaborazione, decidere quali informazioni possono attraversare il confine e mantenere tutto il resto sotto controllo locale.

Questa è la modalità YOLO con cui mi sento a mio agio:

non fidarsi ciecamente di un agente, ma sapere di aver deciso fin dove possono arrivare le conseguenze dei suoi errori.

Nota: i kit di Docker Sandboxes sono al momento sperimentali. Consulta la documentazione aggiornata prima di basare un flusso di lavoro di produzione su comandi o campi di configurazione specifici.

Informazioni sull’autore

Remi d'Almeida

Sviluppatore full stack e architetto di soluzioni con oltre dieci anni di esperienza nella progettazione e realizzazione di prodotti software curati e affidabili.