Creare spazi di lavoro condivisi per persone e agenti
Come i Progetti di Perplexity garantiscono persistenza, concorrenza e tracciabilità al lavoro di lunga durata.
Abbiamo lanciato di recente Progetti, dove persone e agenti collaborano ad attività di lunga durata in Perplexity Computer. Ogni progetto poggia su uno spazio di lavoro condiviso con un filesystem che accumula contesto tra sessioni, agenti e utenti. Una collaborazione multiutente che si estende per mesi richiede persistenza, concorrenza e tracciabilità:
- Persistenza: il lavoro deve durare oltre qualsiasi singola sessione o sandbox di un agente, in modo che possa essere proseguito dallo stesso utente o agente e ampliato da qualsiasi collaboratore.
- Concorrenza: più utenti nello stesso progetto possono avere ciascuno più agenti che apportano modifiche in parallelo, facendo avanzare uno stato condiviso anziché sovrascriversi a vicenda.
- Tracciabilità: sia gli utenti sia gli agenti devono poter consultare la cronologia, per verificare chi ha modificato cosa dall’ultima sessione senza rileggere l’intero progetto e per annullare le modifiche quando necessario.
Queste sfide sono familiari agli ingegneri del software. Le forge Git sono nate decenni fa proprio per rispondere a queste esigenze: un servizio ospitato che affianca al controllo di versione funzionalità collaborative, in modo che molti contributori possano convergere su un’unica fonte di verità. Il filesystem alla base di Progetti è una forge Git di questo tipo, creata per la collaborazione tra persone e agenti e tra agenti.
Architettura
Git gestisce già persistenza, concorrenza e tracciabilità. Identifica ogni file in base al suo contenuto, quindi i file invariati vengono archiviati una sola volta e le copie salvate non diventano mai obsolete. Ogni commit salva in un’unica operazione tutti i file aggiornati, così i collaboratori non vedono mai uno stato lasciato a metà. Quando due autori entrano in conflitto, quello che ha perso può riapplicare le proprie modifiche sulla nuova versione e riprovare. La catena dei commit mostra chi ha modificato cosa e semplifica il ripristino delle versioni precedenti. Ciò di cui gli agenti non hanno bisogno è tutto il resto di una forge pensata per le persone, come le schermate di revisione, la gestione dei branch e le notifiche.
La nostra architettura esegue l’intero processo nel cloud e supporta ogni forma di lavoro intellettuale, ben oltre la programmazione. Ogni progetto di Computer si basa su un repository Git servito da 5 componenti:
- La CLI mantiene i checkout locali, sincronizza gli aggiornamenti e invia le modifiche dell’agente in ciascuna sandbox.
- Il piano di controllo individua il repository del progetto e rilascia credenziali di breve durata per accedervi.
- Il servizio Git invia i dati dei repository alle sandbox, ne riceve gli invii e decide quale invio diventa l’ultimo commit accettato.
- Lo storage basato su AWS S3 archivia in modo persistente i dati dei repository.
- L’elaborazione a valle estrae testo e altre informazioni utili dai documenti salvati e li rende disponibili quando gli agenti caricano o aggiornano il progetto.
Ogni agente ha la propria sandbox isolata. All’interno di questa sandbox lavora con una copia locale del repository, gestita da una piccola CLI. La CLI chiede al piano di controllo di individuare il repository, quindi recupera e invia le modifiche tramite il servizio Git. Un proxy degli agenti verifica l’accesso per le richieste delle sandbox prima che raggiungano il servizio Git. Il servizio Git legge e scrive i repository su un filesystem condiviso e decide se ciascun invio diventa l’ultimo commit accettato. Quel filesystem è fornito da AWS S3Files, che rende lo storage basato su S3 accessibile come normali file e directory. Lo storage è suddiviso in celle isolate, ciascuna con il proprio filesystem e le proprie repliche del servizio Git. Dopo che un commit è stato accettato, i worker in background estraggono testo e altre informazioni utili dai documenti modificati, archiviando i risultati separatamente dalla cronologia del repository e rendendoli disponibili quando gli agenti caricano o aggiornano il progetto.
Di seguito esaminiamo i componenti uno alla volta.
CLI: lavorare con i file locali nelle sandbox
Gli agenti vengono eseguiti in SPACE, la nostra piattaforma di sandbox interna. Ogni sandbox dispone di una piccola CLI che materializza il repository e lo mantiene sincronizzato. Per ogni unità di lavoro significativa svolta dall’agente, la CLI invia le modifiche come commit.
In genere gli agenti toccano solo una piccola parte dei file del progetto, quindi non è necessario materializzare in anticipo l’intero repository. Per questo la CLI materializza i file in modo differito: i file di grandi dimensioni e binari archiviati tramite Git Large File Storage (LFS) arrivano come piccoli file puntatore che riportano la dimensione reale dell’oggetto, così l’agente può basarsi su nome e dimensione per decidere se valga la pena scaricarli. Per documenti come i PDF, l’agente legge prima il testo estratto e scarica i file sorgente solo quando necessario.
Un’altra opzione naturale sarebbe usare un filesystem virtuale. Abbiamo testato un’implementazione basata su FUSE, ma sui carichi di lavoro con uso intensivo del filesystem era circa 400 volte più lenta rispetto ai file locali, poiché ogni richiesta comporta un roundtrip di rete. Inoltre, in genere richiede privilegi elevati sull’host, quindi ogni agente dovrebbe essere eseguito in una sandbox privilegiata.
Piano di controllo: individuare i repository e concedere l’accesso
Il piano di controllo individua dove è archiviato ciascun repository e ne concede l’accesso. Quando viene creato un repository, il piano di controllo lo assegna a una cella di storage, un’unità di archiviazione isolata con le proprie repliche del servizio Git. Quando un agente inizia a lavorare su un progetto, la CLI chiede al piano di controllo dove è archiviato il repository. Il piano di controllo restituisce la posizione e le credenziali temporanee per il servizio Git. Il piano di controllo non legge né scrive mai i dati del repository: è il servizio Git a decidere cosa entra in un repository.
Servizio Git: spostare i dati e coordinare gli aggiornamenti
Il servizio Git esegue le operazioni Git e trasferisce i contenuti e la cronologia delle versioni dei repository tra sandbox e storage. È un wrapper leggero attorno ai comandi di servizio nativi di Git. Supporta la ref discovery, per indicare al client dove si trova l’head del repository, upload-pack per clonazione e fetch, e receive-pack per ricevere nuovi oggetti e una richiesta di far avanzare l’head del repository. Gestisce anche l’API di Git LFS: per i file di grandi dimensioni e binari, rilascia link di breve durata in modo che le sandbox possano caricare e scaricare quei file direttamente da S3.
Siamo partiti da un server forge già pronto, così da poter prototipare le interfacce per agenti e utenti in parallelo allo sviluppo della nostra forge leggera, incentrata solo sulle operazioni Git di cui abbiamo bisogno.
Il servizio è costituito da un insieme di repliche, ciascuna delle quali è un’istanza in esecuzione dello stesso server. Una cella raggruppa lo storage condiviso con un insieme di repliche e i relativi servizi di supporto. Le repliche all’interno di una cella possono così accedere allo stesso filesystem condiviso, invece di mantenere copie indipendenti di ogni repository.
Questo storage condiviso consente alle repliche di restare stateless. Qualsiasi replica della cella può servire uno qualsiasi dei suoi repository, quindi sostituire o aggiungere repliche non richiede di spostare i dati dei repository tra server. Le richieste per un repository vengono normalmente indirizzate alla stessa replica per mantenerne utili le cache, ma il repository non dipende dalla disponibilità di quella specifica istanza.
La fase di accettazione verifica gli invarianti del repository per garantire che un commit accettato corrisponda a uno stato valido del repository. Definiamo un contratto esplicito per ogni repository, in modo che controlli automatici possano impedirne una crescita eccessiva. I file di grandi dimensioni e binari, come PDF e immagini, vengono archiviati tramite Git LFS anziché come blob Git non elaborati. La compattazione mantiene disponibile la cronologia recente, limitando al contempo le dimensioni del repository. Dopo un invio riuscito, la CLI chiede al servizio Git se il repository deve essere compattato. Se il numero di commit conservati supera una soglia, il servizio Git mantiene solo un insieme più ridotto dei commit più recenti. La cronologia meno recente viene sostituita da un unico snapshot iniziale e i commit recenti vengono riapplicati per aggiornarne gli identificatori.
Un semplice passaggio di sincronizzazione gestisce gli autori concorrenti. Tiene traccia dell’ultimo commit accettato, detto head. Quando riceve un invio, lo accetta solo se è stato costruito su quell’head. In caso contrario, restituisce una risposta strutturata di base obsoleta (stale-base); l’agente che ha perso deve quindi riapplicare la propria modifica sul nuovo head e ripetere l’invio. Questa soluzione garantisce che gli agenti concorrenti non si sovrascrivano a vicenda in modo silenzioso, senza causare rallentamenti significativi. Nei nostri flussi di lavoro in produzione, meno del 2% degli invii viene rifiutato perché obsoleto. Complessivamente, la latenza mediana di invio è inferiore a 1,7 secondi e la latenza p99 è inferiore a 8 secondi.
Il servizio Git registra inoltre ogni modifica accettata. Per ogni scrittura accettata, aggiunge una voce a un outbox, un log che elenca il repository, il nuovo commit, l’utente che ha apportato la modifica e i percorsi modificati. I servizi a valle, come il parser, leggono questo log per individuare nuovo lavoro.
Insieme, questi elementi formano un livello di gestione dei repository, senza le parti di cui gli agenti non hanno bisogno. Le pull request non sono necessarie, perché nessuna persona revisiona ogni singola modifica. Al contrario, il servizio Git verifica il contratto al momento dell’invio, l’agente che arriva secondo riapplica la propria modifica e la cronologia dei commit registra chi ha modificato cosa. I controlli deterministici mantengono ogni repository entro i limiti del suo contratto, anziché affidare a un operatore umano la gestione della crescita.
Storage: rendere il lavoro persistente
Il livello di storage salva in modo persistente i dati dei repository, indipendentemente dalle sandbox e dalle repliche del servizio Git. I repository risiedono su AWS S3Files, che espone lo storage basato su S3 tramite un’interfaccia di filesystem utilizzabile da Git standard senza modifiche. Ciascuno è un repository Git bare sul filesystem condiviso, che contiene gli oggetti e i riferimenti del repository anziché una copia di lavoro.
Disaccoppiare storage e calcolo consente alle sandbox di restare effimere. Ogni agente ha la propria sandbox e molti agenti possono lavorare sullo stesso progetto senza condividere una macchina. Se una sandbox si arresta in modo anomalo, è a rischio solo il lavoro non ancora inviato.
Potremmo invece assegnare a ogni progetto una sandbox di lunga durata condivisa da tutti i suoi agenti, in modo che i file del progetto risiedano sul disco di quella macchina. Tuttavia, questo legherebbe le risorse di calcolo degli agenti al luogo in cui viene eseguita la macchina e richiederebbe di dimensionarla per i periodi di maggiore carico. Inoltre, la macchina dovrebbe restare integra per mesi, con backup e ripristino gestiti come parte del sistema di storage del progetto.
Elaborazione a valle: rendere i documenti leggibili per gli agenti
Il principale componente a valle è una pipeline di parsing che estrae testo e metadati dai documenti appena aggiunti o aggiornati, per rendere i file del progetto facilmente leggibili dagli agenti. Un worker di parsing consuma gli aggiornamenti dalla coda del flusso di modifiche, ricava i file modificati dai metadati del commit e recupera i byte grezzi tramite l’hash del contenuto. Quindi analizza il documento per produrre il testo estratto e i relativi metadati.
Gli output del parsing risiedono al di fuori del repository, in un archivio indicizzato in base all’hash del documento sorgente. Questi artifact non vengono mai sottoposti a commit nel repository, perché ciò inquinerebbe inutilmente la cronologia e aumenterebbe il numero di scritture concorrenti. Gli output del parsing raggiungono invece una sandbox tramite checkout e sincronizzazione. Ogni checkout include una directory riservata che la CLI usa per materializzare gli artifact. Il parsing avviene in modo asincrono, quindi un worker di parsing in background non blocca i checkout.
Come gli agenti usano lo spazio di lavoro
Gli agenti esplorano la versione del repository caricata nella sandbox usando gli strumenti standard del filesystem. Invece di seguire una pipeline fissa di ricerca e poi lettura, elencano le cartelle, cercano nei contenuti dei file con grep, leggono i passaggi pertinenti e usano ciò che trovano per decidere dove cercare dopo.
Analogamente a Computer, Search adotta lo stesso approccio tramite i propri strumenti standard per i file. Un agente di esplorazione separato cerca nel progetto con un budget più limitato e restituisce i percorsi dei file pertinenti e gli estratti a supporto. Il modello che risponde legge quindi i file selezionati e genera la risposta. Riutilizzare una sandbox di progetto esistente riduce i tempi di configurazione: collegarsi a un checkout a caldo richiede circa 2,9 secondi, contro circa 8 secondi per un avvio a freddo.
Il testo estratto rende ricercabili con gli stessi strumenti anche i documenti più grandi, come PDF e file Office. L’agente controlla prima un manifest, un elenco che indica per quali documenti è disponibile il testo estratto, quindi cerca e legge quel testo come normali file. Scarica il documento originale solo quando il testo non basta, ad esempio per esaminare figure, layout o dati incorporati.
Abbiamo confrontato questo approccio con la ricerca semantica su un indice, utilizzando 150 domande finanziarie a documento singolo sullo stesso corpus. L’agente di esplorazione ha ottenuto 0,867 nel recupero del documento corretto e 0,627 nelle risposte corrette, contro circa 0,39 e 0,37 della ricerca semantica: circa 1,7 volte migliore nelle risposte e 2 volte migliore nel recupero, con una latenza inferiore di circa il 25%. L’agente di esplorazione lavora principalmente con il testo estratto e scarica raramente i PDF originali.
Un’unica infrastruttura condivisa
La memoria persistente di Computer usa la stessa infrastruttura di filesystem. Perplexity Brain, la wiki della conoscenza di Computer, archivia la memoria in repository di conoscenza con cronologia e policy proprie. Mantenere la conoscenza separata dai file di progetto fa sì che gli aggiornamenti della memoria in background non entrino in competizione con le modifiche a quei file. Una sessione che ha bisogno di entrambi carica entrambi i repository.
Gli agenti in background leggono la conoscenza esistente, incorporano nuove informazioni e salvano le pagine aggiornate come commit. Altri agenti leggono quelle pagine con i normali strumenti per i file e anche le persone possono modificarle. Chi scrive condivide il proprio lavoro tramite il repository, invece di coordinarsi direttamente con ogni lettore. La cronologia dei commit registra chi ha modificato cosa, mentre l’outbox segnala gli aggiornamenti accettati ai servizi a valle. Persone e agenti possono costruire sul lavoro reciproco, con una traccia di come si è evoluta la conoscenza.
Conclusione
Quando persone e agenti condividono un progetto, lo spazio di lavoro non si limita ad archiviare file: offre un luogo comune in cui combinare i contributi e tenere traccia di ciò che è cambiato. Git fornisce già gran parte di queste fondamenta. Noi aggiungiamo coordinamento e controlli automatici, così gli agenti possono inviare il proprio lavoro senza che una persona debba approvare ogni aggiornamento. Il risultato è una forge ridotta all’essenziale, perché la collaborazione tra agenti e lo sviluppo software con più contributori sono, in fondo, lo stesso problema.
Gli agenti lavorano in sandbox indipendenti e temporanee, contribuendo al contempo a repository persistenti. I limiti dei repository mantengono la crescita sotto controllo, i download espliciti consentono agli agenti di scegliere cosa recuperare e i normali file permettono loro di esplorare con strumenti familiari. Aggiornamenti in background, modifiche interattive e attività pianificate possono costruire sul lavoro reciproco senza coordinarsi direttamente.
Man mano che sempre più agenti lavorano in autonomia all’interno dei Progetti, il loro spazio di lavoro condiviso deve restare affidabile e comprensibile per le persone. L’obiettivo è semplice: ogni modifica dovrebbe durare più a lungo dell’agente che l’ha prodotta, diventare disponibile per il collaboratore successivo e lasciare una traccia chiara di ciò che è cambiato.
Citazione
@online{perplexity2026BuildingSharedWorkspacesForPeopleAndAgents,
author = {{Perplexity} and Se Won Jang and Peter Hart and Kartik Kapur and Kevin Lau and Sidhant Rajadnya and Ishbir Singh and Thomas Wang and Jarrod Bryan and Claire Beamer and Jeremy Yang},
title = {{Building shared workspaces for people and agents}},
date = {2026-10-12},
url = {https://www.perplexity.ai/hub/blog/building-shared-workspaces-for-people-and-agents}
}