
La maggior parte dei framework per agenti oggi presuppone un ambiente desktop. Un utente, una macchina, un processo. L'agente viene eseguito finché il portatile è aperto, scrive su un file system locale, conserva le chiavi API in variabili d'ambiente e muore quando il terminale viene chiuso. Quando qualcosa si rompe, l'utente riprova. Quando l'agente ha bisogno di un pacchetto, pip install lo inserisce nel Python dell'utente. Stato, segreti e ciclo di vita risiedono tutti all'interno di un unico confine fidato.
L'infrastruttura cloud per agenti non ha nessuno di questi lussi.
L'agente viene eseguito su un sandbox che si avvia da zero, su hardware condiviso con estranei, attivato da chiamanti che l'utente non incontra mai: un programma, una richiesta HTTP, un altro agente. L'utente di solito dorme quando avviene l'esecuzione. Il codice all'interno del sandbox potrebbe essere ostile. Il file system deve sopravvivere ai deployment. Le credenziali non possono risiedere dove vive l'agente. Ogni garanzia che il desktop ti offre gratuitamente — persistenza, identità, fiducia di rete, ripetizione — deve essere ricostruita come un sistema esplicito.
Negli ultimi mesi abbiamo passato il tempo a stringere quel layer in CREAO. Ne sono emerse due lezioni. Se hai mai messo in produzione un agente desktop e ti sei chiesto cosa cambia quando si sposta nel cloud, ecco cosa cambia.
Lezione 1: Separa ciò che cambia lentamente da ciò che cambia velocemente

Su un desktop, l'ambiente dell'utente e il runtime dell'agente sono la stessa cosa, aggiornati con la stessa cadenza, dalla stessa persona. Nel cloud non lo sono.
Un'applicazione agente accumula stato dal lato della piattaforma. Un analista azionario installa matplotlib, scarica dati di mercato, scrive script per creare grafici. Quell'ambiente è la memoria muscolare dell'agente. Lo congeliamo in uno snapshot del sandbox nel momento in cui l'utente è soddisfatto, e manteniamo quello snapshot congelato finché l'utente non modifica di nuovo l'ambiente. Ogni esecuzione parte dalla stessa immagine. Stessi pacchetti, stessi file, stesse versioni. L'esecuzione del lunedì si comporta come quella del venerdì, perché nulla è cambiato sotto.
Questa è la proprietà che i framework desktop non possono darti gratuitamente. Un pip install di sei mesi fa si risolve in versioni diverse oggi. Uno snapshot cloud si risolve negli stessi byte per sempre. La riproducibilità è qualcosa che la piattaforma deve all'utente, e uno snapshot congelato è il modo più economico per fornirla.
Poi emerge il problema dell'accoppiamento.
La stessa immagine che congela l'ambiente dell'utente contiene anche il codice del runner — la piccola libreria di supporto sviluppata da noi che gestisce l'agente in ogni esecuzione. L'utente vuole che il suo ambiente rimanga fermo. Noi vogliamo che il nostro runner possa essere distribuito molte volte al giorno. Un unico artefatto, due requisiti opposti.
La nostra prima soluzione è stata brutale. All'avvio, verifica se il runner all'interno dello snapshot corrisponde alla versione che abbiamo appena distribuito. Se non corrisponde, butta via lo snapshot e avvia da un template pulito. Funzionava, e nessuno si è lamentato. Il danno colpiva solo la prima esecuzione dopo un deployment.
Le esecuzioni non presidiate hanno eliminato quella copertura. Un cron job alle 9 di lunedì mattina non dovrebbe perdere il suo ambiente solo perché abbiamo distribuito alle 8:55. Il contratto che stavamo silenziosamente violando — "il tuo ambiente è congelato finché non lo modifichi" — è stato esposto.
La soluzione ci ha richiesto più tempo di quanto avrebbe dovuto per essere vista. L'ambiente dell'utente e il codice del runner cambiano a velocità completamente diverse. L'utente modifica il suo agente quando lo decide. Noi distribuiamo la piattaforma molte volte al giorno. Trattarli come un unico artefatto imponeva una scelta in ogni deployment: tenere codice runner obsoleto, o distruggere l'ambiente congelato che l'utente ci aveva esplicitamente chiesto di preservare.
Il modello su cui ci siamo assestati prende in prestito da come i sistemi operativi gestiscono gli aggiornamenti. Il kernel cambia. La tua home directory no. Non cancelli il disco per installare una patch di sicurezza.
Abbiamo tracciato lo stesso confine. Il sandbox si avvia dallo snapshot congelato dell'utente, intatto. Poi sostituiamo a caldo solo il runner. La sequenza:
- Posiziona il nuovo runner in una directory temporanea all'interno del sandbox.
- Validalo con node --check in modo che qualsiasi errore di sintassi venga catturato prima di toccare qualcosa di attivo.
- Sostituiscilo atomicamente: sblocca il flag immutabile sul vecchio runner, copia il nuovo sopra, ri-blocca con chattr +i, poi nascondi il binario chattr stesso in modo che il codice del sandbox non possa invertire il blocco.
- Pulisci la cache di compilazione V8 (/home/user/.cache/v8-compile-cache/*) in modo che il nuovo file venga effettivamente caricato invece di eseguire bytecode obsoleto.
- Se un qualsiasi passo fallisce, uccidi il sandbox e riprova con uno nuovo. Nessuno stato parzialmente aggiornato esegue mai un agente.
L'intera sostituzione richiede circa 300 millisecondi. Rieseguiamo lo snapshot dopo un'esecuzione riuscita solo quando il codice del runner è stato sostituito, incorporando il codice aggiornato nell'immagine dell'utente in modo che la prossima esecuzione salti del tutto la sostituzione. I deployment della piattaforma non scartano mai lo stato dell'utente; ci incorporano il nuovo runner. I pacchetti, i file e le personalizzazioni dell'utente vengono portati avanti invariati.
Se c'è una cosa da portare via da questa lezione, è la domanda diagnostica. Per qualsiasi cosa persista in una piattaforma cloud, chiediti: chi controlla la cadenza di cambiamento su questo artefatto? Se l'utente e la piattaforma lo possiedono entrambi, alla fine pagherai per l'accoppiamento. Suddividi l'artefatto lungo il confine di proprietà e lascia che ogni lato si aggiorni con la propria tempistica.
Lezione 2: Tieni i segreti fuori dal confine di esecuzione

Questa è la lezione che separa l'infrastruttura cloud per agenti da tutto il resto.
Un agente desktop viene eseguito come l'utente. Usa le chiavi dell'utente, sulla macchina dell'utente, contro la rete dell'utente. Un agente cloud viene eseguito come nessuno, su hardware condiviso, contro l'internet aperto, eseguendo codice che un LLM ha scritto da un prompt che potrebbe essere stato ostile. Il modello di sicurezza deve presumere che il codice all'interno del sandbox sia già compromesso, non sperare il contrario.
La regola che seguiamo è semplice. Nessuna credenziale a lunga durata vive mai all'interno del sandbox.
Quando un agente ha bisogno di chiamare un servizio autenticato — Slack, GitHub, l'API dell'utente stesso — non detiene il token. Invece invia una richiesta HTTP locale a un ponte API che viene eseguito fuori dal sandbox. Il ponte allega il token OAuth dal lato host e inoltra la chiamata. La risposta torna indietro senza che il token entri mai nella memoria o nell'ambiente del sandbox.
La parte interessante è come il ponte sa che al sandbox è permesso chiedere. Due controlli, stratificati di proposito.
Primo, whitelist IP. Il ponte accetta solo connessioni dall'intervallo di rete interna su cui risiedono i nostri host sandbox. Una chiamata da qualsiasi altra parte — un portatile di uno sviluppatore, un URL trapelato, l'internet pubblico — viene scartata a livello di rete prima che qualsiasi codice applicativo venga eseguito. Questo vincola il ponte a una singola infrastruttura fisica e lo rende inutile per chiunque sia al di fuori.
Secondo, un JWT a breve durata coniato per ogni esecuzione. Quando un sandbox si avvia, la piattaforma firma un token con ambito limitato a quella specifica esecuzione: quale utente, quale app, quale sessione, con una scadenza che copre la finestra di esecuzione e niente di più. Il sandbox lo presenta in ogni chiamata al ponte. Il ponte verifica la firma, controlla la scadenza, e solo allora risolve le credenziali memorizzate dell'utente e le allega lato server. Se un sandbox viene dirottato, l'attaccante eredita un token che muore con l'esecuzione e autorizza solo chiamate con ambito limitato a quella singola sessione. Non esiste una credenziale master da rubare.
Lo stesso ponte trasporta fuori detrazioni di fatturazione, log e metriche, quindi è l'unica interfaccia che attraversa il confine del sandbox in entrambe le direzioni. Tutto il resto all'interno del sandbox è trattato come compromesso per default.
Se un'iniezione di prompt convince un agente a scaricare process.env in un webhook domani, l'attaccante ottiene un JWT a breve durata che funziona solo dall'interno della nostra rete e scade con l'esecuzione. Questa proprietà è ciò che ci permette di eseguire codice utente non fidato su infrastruttura condivisa senza perdere il sonno.
Il pattern sottostante
L'infrastruttura cloud per agenti affidabile e sicura non è un sistema nuovo. Sono alcune proprietà mantenute senza eccezioni:
- Lo stato vive nel sandbox, congelato finché l'utente non lo modifica.
- Il codice è sostituibile a caldo, indipendentemente dallo stato.
- Le credenziali vivono lato host, mai all'interno dell'agente.
- Una singola pipeline di esecuzione serve ogni chiamante, che il trigger sia un umano, un programmatore, o un altro pezzo di software.
Quest'ultima proprietà è il punto chiave dell'intero design. Una singola funzione executeAgent gestisce i click dell'interfaccia utente, le esecuzioni programmate e le chiamate API. Il sistema di fatturazione, i log di detrazione dei crediti, i segnali di osservabilità — tutti identici indipendentemente dal fatto che un umano abbia cliccato Esegui, un cron sia scattato, o uno script abbia chiamato l'API. Aggiungere una nuova superficie di trigger è un cambiamento di routing, non un cambiamento architetturale. L'agente stesso non sa e non si cura di chi ha tirato il grilletto.
Questo è ciò che i framework desktop non possono darti, e ciò che rende la versione cloud degna di essere costruita. Un agente su un laptop è legato al laptop. Un agente nel cloud è una funzione che il resto del tuo stack può chiamare. L'utente lo scrive una volta. La piattaforma lo fa sopravvivere ai deployment, funzionare in sicurezza su hardware condiviso, e accettare chiamanti che l'utente non aveva mai previsto.
Un agente è una funzione con un'interfaccia in linguaggio naturale. La sua implementazione appartiene all'utente. La sua superficie di trigger, il suo runtime, il suo confine di sicurezza appartengono alla piattaforma. La disciplina è costruire i layer in modo che ognuno si evolva con la propria tempistica, e dedicare il tempo a trovare le crepe tra i sistemi prima che qualcun altro lo faccia.
Questo è ciò che rende la prossima superficie economica da rilasciare, e sicura da rilasciare.





