Construirea de spații de lucru partajate pentru oameni și agenți

Cum asigură proiectele din Perplexity persistența, concurența și trasabilitatea muncii de lungă durată.

AutoriPerplexity Engineering

Am lansat recent proiectele în Perplexity Computer, unde oamenii și agenții lucrează împreună la sarcini de lungă durată. Fiecare proiect se bazează pe un spațiu de lucru partajat, cu un sistem de fișiere care acumulează context de la o sesiune la alta, între agenți și utilizatori. Colaborarea cu mai mulți participanți, întinsă pe luni întregi, necesită persistență, concurență și trasabilitate:

  • Persistența: munca ar trebui să dureze dincolo de orice sesiune de agent sau sandbox individual, astfel încât să poată fi continuată ulterior de același utilizator sau agent și dezvoltată de orice colaborator.
  • Concurența: mai mulți utilizatori din același proiect pot avea fiecare mai mulți agenți care fac editări în paralel, avansând o stare comună în loc să se suprascrie reciproc.
  • Trasabilitatea: atât utilizatorii, cât și agenții ar trebui să poată vedea istoricul, pentru a verifica cine ce a modificat de la ultima lor sesiune fără a reciti întregul proiect și pentru a anula editările atunci când este nevoie.

Aceste provocări le sunt familiare inginerilor software. Platformele forge Git au apărut acum câteva decenii pentru a răspunde acestor cerințe: un serviciu găzduit care adaugă funcții de colaborare peste controlul versiunilor, astfel încât numeroși contribuitori să poată converge către o singură sursă de adevăr. Sistemul de fișiere care stă la baza proiectelor este o astfel de platformă forge Git, construită pentru colaborarea dintre oameni și agenți, precum și dintre agenți.

Un singur proiect: agenții interactivi, agenții programați și agenții altor utilizatori converg toți către același depozit.

Arhitectură

Git gestionează deja persistența, concurența și trasabilitatea. Identifică fiecare fișier după conținutul său, astfel încât fișierele nemodificate sunt stocate o singură dată, iar copiile salvate nu devin niciodată învechite. Fiecare commit salvează simultan toate fișierele actualizate, așa că colaboratorii nu văd niciodată o stare pe jumătate terminată. Când două procese de scriere intră în conflict, cel care a pierdut își poate reaplica modificările pe noua versiune și poate încerca din nou. Lanțul de commituri arată cine ce a modificat și facilitează restaurarea versiunilor anterioare. Agenții nu au nevoie însă de restul unei platforme forge construite pentru oameni, cum ar fi ecranele de revizuire, gestionarea ramurilor și notificările.

Arhitectura noastră rulează întregul proces în cloud și acceptă toate formele de muncă bazată pe cunoaștere, nu doar programarea. Fiecare proiect Computer are la bază un depozit Git deservit de 5 componente:

  • CLI-ul gestionează copiile de lucru locale, sincronizează actualizările și trimite modificările agentului din fiecare sandbox.
  • Planul de control localizează depozitul proiectului și emite credențiale de scurtă durată pentru a-l accesa.
  • Serviciul Git trimite datele depozitului către sandboxuri, primește trimiterile acestora și decide care trimitere devine cel mai recent commit acceptat.
  • Stocarea bazată pe AWS S3 păstrează în mod durabil datele depozitelor.
  • Procesarea din aval extrage text și alte informații utile din documentele salvate și le pune la dispoziție atunci când agenții încarcă sau reîmprospătează proiectul.

Fiecare agent are propriul sandbox izolat. În interiorul acestuia, lucrează cu o copie locală a depozitului, gestionată de un mic CLI. CLI-ul îi cere planului de control să localizeze depozitul, apoi preia și trimite modificări prin serviciul Git. Un proxy pentru agenți verifică accesul pentru cererile din sandbox înainte ca acestea să ajungă la serviciul Git. Serviciul Git citește și scrie depozite pe un sistem de fișiere partajat și decide dacă fiecare trimitere devine cel mai recent commit acceptat. Acest sistem de fișiere este furnizat de AWS S3Files, care face ca stocarea bazată pe S3 să fie accesibilă sub formă de fișiere și directoare obișnuite. Stocarea este împărțită în celule izolate, fiecare cu propriul sistem de fișiere și propriile replici ale serviciului Git. După ce un commit este acceptat, workerii din fundal extrag text și alte informații utile din documentele modificate, stochează rezultatele separat de istoricul depozitului și le pun la dispoziție atunci când agenții încarcă sau reîmprospătează proiectul.

În continuare, prezentăm componentele pe rând.

CLI-ul contactează planul de control pentru a-și localiza depozitul, apoi preia și trimite date prin serviciul Git, prin intermediul proxyului pentru agenți. Serviciul Git verifică trimiterile și actualizează headul acceptat și outboxul în DynamoDB. Replicile locale ale celulei folosesc stocarea S3Files, în timp ce workerii din aval extrag text pentru checkout și sincronizare.

CLI: lucrul cu fișiere locale în sandboxuri

Agenții rulează în SPACE, platforma noastră internă de sandboxuri. Fiecare sandbox are un mic CLI care materializează depozitul și îl menține sincronizat. Pentru fiecare unitate de lucru semnificativă efectuată de agent, CLI-ul trimite modificările sub formă de commit.

De obicei, agenții ating doar o mică parte din fișierele proiectului, așa că nu este necesar ca întregul depozit să fie materializat de la început. Prin urmare, CLI-ul materializează fișierele la cerere: fișierele mari și binare stocate prin Git Large File Storage (LFS) sosesc ca mici fișiere pointer care rețin dimensiunea reală a obiectului, astfel încât agentul poate folosi numele și dimensiunea pentru a decide dacă merită sau nu să le descarce. Pentru documente precum PDF-urile, agentul citește mai întâi textul parsat și descarcă fișierele sursă doar atunci când este necesar.

O altă opțiune firească ar fi folosirea unui sistem de fișiere virtual. Am testat o implementare bazată pe FUSE, dar era de aproximativ 400 de ori mai lentă decât fișierele locale la sarcinile de lucru care solicită intens sistemul de fișiere, deoarece fiecare cerere necesită un drum dus-întors prin rețea. De asemenea, de obicei necesită capabilități privilegiate din partea gazdei, așa că fiecare agent ar trebui să ruleze într-un sandbox privilegiat.

Dimensiunea pointerului și manifestul de parsare decid: citirea textului parsat, descărcarea sursei sau omiterea fișierului.

Planul de control: localizarea depozitelor și acordarea accesului

Planul de control identifică locul în care este stocat fiecare depozit și acordă acces la acesta. Când este creat un depozit, planul de control îl atribuie unei celule de stocare, o unitate de stocare izolată, cu propriile replici ale serviciului Git. Când un agent începe să lucreze la un proiect, CLI-ul întreabă planul de control unde este stocat depozitul. Planul de control returnează locația și credențiale temporare pentru serviciul Git. Planul de control nu citește și nu scrie niciodată datele depozitului. Serviciul Git decide ce intră într-un depozit.

Serviciul Git: transferul datelor și coordonarea actualizărilor

Serviciul Git execută operațiuni Git și transferă conținutul depozitelor și istoricul versiunilor între sandboxuri și stocare. Este un strat subțire peste comenzile de servire proprii ale Git. Acceptă descoperirea referințelor, pentru a-i indica clientului unde se află headul depozitului, upload-pack pentru clonare și preluare și receive-pack pentru primirea de obiecte noi și a unei cereri de avansare a headului depozitului. De asemenea, deservește API-ul Git LFS: pentru fișierele mari și binare, emite linkuri de scurtă durată, astfel încât sandboxurile să poată încărca și descărca acele fișiere direct din S3.

Am început cu un server forge standard, disponibil pe piață, ca să putem crea prototipuri ale interfețelor pentru agenți și utilizatori în paralel cu dezvoltarea propriei noastre platforme forge, ușoare și axate doar pe operațiunile Git de care avem nevoie.

Serviciul constă dintr-o flotă de replici, fiecare fiind o instanță în execuție a aceluiași server. O celulă grupează stocarea partajată cu un set de replici și serviciile lor auxiliare. Astfel, replicile dintr-o celulă pot accesa același sistem de fișiere partajat, în loc să mențină copii independente ale fiecărui depozit.

Această stocare partajată permite ca replicile să rămână fără stare. Orice replică din celulă poate deservi oricare dintre depozitele acesteia, așa că înlocuirea sau adăugarea de replici nu necesită mutarea datelor depozitelor între servere. În mod normal, cererile pentru un depozit ajung la aceeași replică, pentru ca memoria cache a acesteia să rămână utilă, dar depozitul nu depinde de disponibilitatea continuă a acelei instanțe anume.

Pasul de acceptare verifică invarianții depozitului pentru a se asigura că un commit acceptat reprezintă o stare validă a depozitului. Definim un contract explicit pentru fiecare depozit, astfel încât verificările mecanice să-l împiedice să crească prea mult. Fișierele mari și binare, cum ar fi PDF-urile și imaginile, sunt stocate prin Git LFS, nu ca bloburi Git brute. Compactarea păstrează disponibil istoricul recent, limitând în același timp dimensiunea depozitului. După o trimitere reușită, CLI-ul întreabă serviciul Git dacă depozitul trebuie compactat. Dacă numărul de commituri păstrate depășește un prag, serviciul Git păstrează doar un set mai mic, cu cele mai recente commituri. Istoricul mai vechi este înlocuit cu un singur instantaneu inițial, iar commiturile recente sunt reaplicate pentru a actualiza identificatorii commiturilor.

Compactarea păstrează cele mai recente commituri, condensează istoricul mai vechi într-o singură rădăcină-instantaneu și reaplică commiturile recente cu identificatori noi; noul head conține aceleași fișiere.

Un simplu pas de sincronizare gestionează scrierile concurente. Acesta urmărește cel mai recent commit acceptat, numit head. Când primește o trimitere, o acceptă doar dacă a fost construită pe baza acelui head. În caz contrar, transmite un răspuns structurat de tip „bază învechită”; agentul care a pierdut trebuie apoi să-și reaplice modificarea peste noul head și să o retrimită. Acest design garantează că agenții concurenți nu își suprascriu tacit munca unii altora, fără a provoca încetiniri semnificative. În fluxurile noastre de lucru din producție, mai puțin de 2% dintre trimiteri sunt respinse ca învechite. În ansamblu, latența mediană a trimiterii este sub 1,7 secunde, iar latența p99 este sub 8 secunde.

Doi agenți trimit simultan; unul este acceptat, iar celălalt primește un răspuns de tip „bază învechită”, își reaplică modificarea peste noul head și o retrimite.

De asemenea, serviciul Git înregistrează fiecare modificare acceptată. Pentru fiecare scriere acceptată, adaugă o intrare într-un outbox, un jurnal care include depozitul, noul commit, utilizatorul care a făcut modificarea și căile care s-au schimbat. Serviciile din aval, cum ar fi parserul, citesc acest jurnal pentru a găsi sarcini noi.

Împreună, aceste componente formează un strat de gestionare a depozitelor, fără părțile de care agenții nu au nevoie. Pull request-urile nu sunt necesare, deoarece niciun om nu revizuiește fiecare modificare. În schimb, serviciul Git verifică contractul în momentul trimiterii, agentul care pierde o cursă își reaplică propria modificare, iar istoricul commiturilor înregistrează cine ce a modificat. Verificările deterministe mențin fiecare depozit în limitele contractului său, în loc să depindă de un operator uman care să gestioneze creșterea.

Stocarea: păstrarea durabilă a muncii

Stratul de stocare salvează în mod durabil datele depozitelor, independent de sandboxuri și de replicile serviciului Git. Depozitele se află pe AWS S3Files, care expune stocarea bazată pe S3 printr-o interfață de sistem de fișiere pe care versiunea standard a Git o poate folosi fără modificări. Fiecare este un depozit Git bare pe sistemul de fișiere partajat, care conține obiectele și referințele depozitului, nu o copie de lucru.

Decuplarea stocării de resursele de calcul permite ca sandboxurile să rămână efemere. Fiecare agent primește propriul sandbox, iar mulți agenți pot lucra la același proiect fără să partajeze o mașină. Dacă un sandbox se închide neașteptat, este în pericol doar munca încă netrimisă.

Am putea, în schimb, să oferim fiecărui proiect un sandbox de lungă durată, partajat de toți agenții săi, astfel încât fișierele proiectului să se afle pe discul acelei mașini. Totuși, acest lucru ar lega resursele de calcul ale agenților de locul în care rulează mașina și ar impune dimensionarea ei pentru perioadele cele mai aglomerate. De asemenea, mașina ar trebui să rămână funcțională luni întregi, cu copiile de rezervă și recuperarea gestionate ca parte a sistemului de stocare al proiectului.

Un singur sandbox de lungă durată, partajat de agenții unui proiect, comparat cu sandboxuri de scurtă durată, câte unul pentru fiecare agent, care accesează stocarea partajată durabilă prin replici fără stare ale serviciului Git.

Procesarea din aval: documente ușor de citit pentru agenți

Principala componentă din aval este un pipeline de parsare care extrage textul și metadatele din documentele nou adăugate sau actualizate, pentru ca fișierele proiectului să poată fi citite ușor de agenți. Un worker de parsare preia actualizările din coada fluxului de modificări, determină fișierele modificate pe baza metadatelor commitului și obține octeții bruți folosind hashul conținutului. Apoi parsează documentul pentru a produce textul extras și metadatele documentului.

Rezultatele parsării se află în afara depozitului, într-un spațiu de stocare indexat după hashul documentului sursă. Aceste artefacte nu sunt niciodată adăugate înapoi în depozit prin commit, deoarece acest lucru ar polua inutil istoricul și ar crește numărul de scrieri concurente. În schimb, rezultatele parsării ajung într-un sandbox prin checkout și sincronizare. Fiecare checkout conține un director rezervat, pe care CLI-ul îl folosește pentru materializarea artefactelor. Parsarea are loc asincron, astfel încât un worker de parsare din fundal nu blochează checkouturile.

Cum folosesc agenții spațiul de lucru

Agenții explorează versiunea depozitului încărcată în sandbox folosind instrumente standard pentru sistemul de fișiere. În loc să urmeze un flux fix de tip „caută, apoi citește”, aceștia listează folderele, caută în conținutul fișierelor cu grep, citesc pasajele relevante și folosesc ceea ce găsesc pentru a decide unde să caute în continuare.

La fel ca în Computer, Search folosește aceeași abordare prin instrumentele sale standard pentru fișiere. Un agent de explorare separat caută în proiect cu un buget mai limitat și returnează căile fișierelor relevante și fragmente justificative. Modelul care formulează răspunsul citește apoi fișierele selectate și generează răspunsul. Reutilizarea unui sandbox de proiect existent reduce timpul de configurare: atașarea la un checkout deja pregătit durează aproximativ 2,9 secunde, față de circa 8 secunde la o pornire la rece.

Sandboxurile din Computer, subagentul de explorare din Ask, procesele de fundal care actualizează cunoștințele și workerii de parsare citesc și scriu toți în același depozit și în același outbox.

Textul parsat face ca documentele mai mari, precum PDF-urile și fișierele Office, să poată fi căutate cu aceleași instrumente. Agentul verifică mai întâi un manifest, o listă care arată pentru ce documente este disponibil textul extras, apoi caută în acel text și îl citește ca pe niște fișiere obișnuite. Descarcă documentul original doar atunci când textul nu este suficient, de exemplu pentru a examina figuri, aspectul paginii sau date încorporate.

Am comparat această abordare cu căutarea semantică într-un index, pe 150 de întrebări financiare bazate pe un singur document, din același corpus. Agentul de explorare a obținut 0,867 la identificarea documentului corect și 0,627 la răspunsurile corecte, față de aproximativ 0,39 și 0,37 pentru căutarea semantică, adică rezultate de circa 1,7 ori mai bune la răspunsuri și de 2 ori mai bune la regăsire, cu o latență cu aproximativ 25% mai mică. Agentul de explorare lucrează în principal cu textul extras și descarcă rareori PDF-urile originale.

Explorarea comparativ cu căutarea semantică în fișiere, pe benchmarkul intern.

O infrastructură comună

Memoria persistentă din Computer folosește aceeași infrastructură de sistem de fișiere. Perplexity Brain, wikiul de cunoștințe din Computer, stochează memoria în depozite de cunoștințe cu propriul istoric și propriile politici. Păstrarea cunoștințelor separat de fișierele proiectului înseamnă că actualizările memoriei din fundal nu concurează cu editările acelor fișiere. O sesiune care are nevoie de ambele încarcă ambele depozite.

Agenții din fundal citesc cunoștințele existente, încorporează informații noi și salvează paginile actualizate sub formă de commituri. Alți agenți citesc acele pagini cu instrumente obișnuite pentru fișiere, iar oamenii le pot edita și ei. Autorii își partajează munca prin depozit, în loc să se coordoneze direct cu fiecare cititor. Istoricul commiturilor înregistrează cine ce a modificat, în timp ce outboxul raportează actualizările acceptate către serviciile din aval. Oamenii și agenții pot construi pornind de la munca celorlalți, păstrând o evidență a modului în care au evoluat cunoștințele.

Concluzie

Când oamenii și agenții partajează un proiect, spațiul de lucru face mai mult decât să stocheze fișiere. Oferă un loc comun pentru combinarea contribuțiilor și urmărirea modificărilor. Git oferă deja o mare parte din această fundație. Noi adăugăm coordonare și verificări automate, astfel încât agenții să-și poată trimite munca fără ca o persoană să aprobe fiecare actualizare. Rezultatul este o platformă forge redusă la esențial, deoarece colaborarea dintre agenți și dezvoltarea software cu mai mulți contribuitori sunt, în fond, aceeași problemă.

Agenții lucrează în sandboxuri independente și temporare, contribuind în același timp la depozite durabile. Limitele depozitelor mențin creșterea sub control, descărcările explicite le permit agenților să aleagă ce preiau, iar fișierele obișnuite îi lasă să exploreze cu instrumente familiare. Actualizările din fundal, editările interactive și sarcinile programate se pot baza unele pe munca celorlalte, fără o coordonare directă.

Pe măsură ce tot mai mulți agenți lucrează autonom în cadrul proiectelor, spațiul lor de lucru comun trebuie să rămână fiabil și ușor de înțeles pentru oameni. Obiectivul este simplu: fiecare modificare ar trebui să fie mai durabilă decât agentul care a produs-o, să devină disponibilă pentru următorul colaborator și să lase o evidență clară a ceea ce s-a schimbat.

Citare

BibTeX
@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}
}