Tworzenie wspólnych przestrzeni roboczych dla ludzi i agentów
Jak Projekty w Perplexity zapewniają trwałość, współbieżność i identyfikowalność długotrwałej pracy.
Niedawno uruchomiliśmy Projekty, w których ludzie i agenci wspólnie pracują nad długotrwałymi zadaniami w Perplexity Computer. Każdy projekt opiera się na wspólnej przestrzeni roboczej z systemem plików, który gromadzi kontekst z kolejnych sesji, od różnych agentów i użytkowników. Wieloosobowa współpraca trwająca miesiącami wymaga trwałości, współbieżności i identyfikowalności:
- Trwałość: praca powinna przetrwać dłużej niż pojedyncza sesja agenta czy piaskownica, aby ten sam użytkownik lub agent mógł ją później kontynuować, a pozostali współpracownicy – rozwijać.
- Współbieżność: wielu użytkowników w tym samym projekcie może mieć po kilku agentów, którzy równolegle wprowadzają zmiany rozwijające wspólny stan, zamiast nawzajem się nadpisywać.
- Identyfikowalność: zarówno użytkownicy, jak i agenci powinni mieć wgląd w historię, aby sprawdzić, kto co zmienił od ich ostatniej sesji, bez ponownego czytania całego projektu, i w razie potrzeby wycofać zmiany.
Te wyzwania wyglądają znajomo dla inżynierów oprogramowania. Platformy typu Git forge pojawiły się dziesiątki lat temu właśnie po to, by spełnić te wymagania: to hostowane usługi, które łączą kontrolę wersji z funkcjami współpracy, aby wielu współtwórców mogło dojść do jednego źródła prawdy. System plików, na którym działają Projekty, jest właśnie taką platformą Git forge, zbudowaną z myślą o współpracy między ludźmi a agentami oraz między samymi agentami.
Architektura
Git już zapewnia trwałość, współbieżność i identyfikowalność. Identyfikuje każdy plik na podstawie jego zawartości, więc niezmienione pliki są przechowywane tylko raz, a zapisane kopie nigdy się nie dezaktualizują. Każdy commit zapisuje wszystkie zaktualizowane pliki naraz, więc współpracownicy nigdy nie widzą niedokończonego stanu. Gdy zmiany dwóch autorów kolidują ze sobą, ten, który przegrał, może ponownie nałożyć swoje zmiany na nową wersję i spróbować jeszcze raz. Łańcuch commitów pokazuje, kto co zmienił, i ułatwia przywracanie wcześniejszych wersji. Agenci nie potrzebują natomiast reszty platformy forge zbudowanej dla ludzi, takiej jak ekrany przeglądu, zarządzanie gałęziami i powiadomienia.
Nasza architektura realizuje cały proces w chmurze i obsługuje wszystkie rodzaje pracy opartej na wiedzy, nie tylko programowanie. Każdy projekt w Computer opiera się na repozytorium Git obsługiwanym przez 5 komponentów:
- CLI utrzymuje lokalne kopie robocze, synchronizuje aktualizacje i przesyła zmiany agenta w każdej piaskownicy.
- Płaszczyzna sterowania lokalizuje repozytorium projektu i wydaje krótkotrwałe poświadczenia umożliwiające dostęp do niego.
- Usługa Git wysyła dane repozytorium do piaskownic, odbiera przesyłane z nich zmiany i decyduje, które zgłoszenie staje się najnowszym zaakceptowanym commitem.
- Pamięć masowa oparta na AWS S3 trwale przechowuje dane repozytoriów.
- Przetwarzanie końcowe wyodrębnia tekst i inne przydatne informacje z zapisanych dokumentów i udostępnia je, gdy agenci wczytują lub odświeżają projekt.
Każdy agent ma własną, odizolowaną piaskownicę. W jej obrębie pracuje na lokalnej kopii repozytorium, zarządzanej przez niewielkie CLI. CLI prosi płaszczyznę sterowania o zlokalizowanie repozytorium, a następnie pobiera i przesyła zmiany przez usługę Git. Proxy agenta sprawdza uprawnienia dostępu dla żądań z piaskownicy, zanim dotrą one do usługi Git. Usługa Git odczytuje i zapisuje repozytoria we współdzielonym systemie plików oraz decyduje, czy dane zgłoszenie staje się najnowszym zaakceptowanym commitem. Ten system plików zapewnia AWS S3Files, które udostępnia pamięć masową opartą na S3 w postaci zwykłych plików i katalogów. Pamięć masowa jest podzielona na odizolowane komórki, z których każda ma własny system plików i repliki usługi Git. Po zaakceptowaniu commita procesy działające w tle wyodrębniają tekst i inne przydatne informacje ze zmienionych dokumentów, przechowują wyniki oddzielnie od historii repozytorium i udostępniają je, gdy agenci wczytują lub odświeżają projekt.
Poniżej omawiamy kolejno poszczególne komponenty.
CLI: praca z lokalnymi plikami w piaskownicach
Agenci działają w SPACE, naszej wewnętrznej platformie piaskownic. Każda piaskownica ma niewielkie CLI, które materializuje repozytorium i utrzymuje jego synchronizację. Po wykonaniu przez agenta każdej istotnej jednostki pracy CLI przesyła zmiany jako commit.
Agenci zazwyczaj korzystają tylko z niewielkiej części plików projektu, więc nie trzeba materializować całego repozytorium z góry. Dlatego CLI materializuje je leniwie: duże pliki i pliki binarne przechowywane za pomocą Git Large File Storage (LFS) docierają jako małe pliki wskaźnikowe zawierające rzeczywisty rozmiar obiektu, dzięki czemu agent może na podstawie nazwy i rozmiaru zdecydować, czy warto pobrać dany plik. W przypadku dokumentów takich jak PDF-y agent najpierw odczytuje sparsowany tekst, a pliki źródłowe pobiera tylko wtedy, gdy jest to konieczne.
Inną naturalną opcją byłoby użycie wirtualnego systemu plików. Przetestowaliśmy implementację opartą na FUSE, ale przy obciążeniach intensywnie korzystających z systemu plików była ona mniej więcej 400 razy wolniejsza od plików lokalnych, ponieważ każde żądanie wymaga komunikacji sieciowej w obie strony. Zazwyczaj wymaga ona też podwyższonych uprawnień na hoście, więc każdy agent musiałby działać w uprzywilejowanej piaskownicy.
Płaszczyzna sterowania: lokalizowanie repozytoriów i przyznawanie dostępu
Płaszczyzna sterowania ustala, gdzie przechowywane jest każde repozytorium, i przyznaje do niego dostęp. Gdy powstaje repozytorium, płaszczyzna sterowania przypisuje je do komórki pamięci masowej – wyizolowanej jednostki przechowywania danych z własnymi replikami usługi Git. Gdy agent rozpoczyna pracę nad projektem, CLI pyta płaszczyznę sterowania, gdzie przechowywane jest repozytorium. Płaszczyzna sterowania zwraca lokalizację oraz tymczasowe poświadczenia do usługi Git. Płaszczyzna sterowania nigdy nie odczytuje ani nie zapisuje danych repozytorium. To usługa Git decyduje, co trafia do repozytorium.
Usługa Git: przesyłanie danych i koordynowanie aktualizacji
Usługa Git wykonuje operacje Git i przesyła zawartość repozytoriów oraz historię wersji między piaskownicami a pamięcią masową. Jest cienką nakładką na natywne polecenia serwerowe Gita. Obsługuje wykrywanie referencji (ref discovery), które informuje klienta, gdzie znajduje się head repozytorium, upload-pack do klonowania i pobierania oraz receive-pack do odbierania nowych obiektów i żądań przesunięcia head repozytorium. Obsługuje również API Git LFS: w przypadku dużych plików i plików binarnych wydaje krótkotrwałe linki, dzięki którym piaskownice mogą przesyłać i pobierać te pliki bezpośrednio z S3.
Zaczęliśmy od gotowego serwera forge, dzięki czemu mogliśmy prototypować interfejsy dla agentów i użytkowników równolegle z budową własnej, lekkiej platformy forge, skoncentrowanej wyłącznie na potrzebnych nam operacjach Git.
Usługa składa się z floty replik, z których każda jest działającą instancją tego samego serwera. Komórka grupuje współdzieloną pamięć masową z zestawem replik i ich usługami pomocniczymi. Dzięki temu repliki w obrębie komórki mają dostęp do tego samego współdzielonego systemu plików i nie muszą utrzymywać niezależnych kopii każdego repozytorium.
Dzięki tej współdzielonej pamięci masowej repliki mogą pozostać bezstanowe. Każda replika w komórce może obsługiwać dowolne z jej repozytoriów, więc wymiana lub dodawanie replik nie wymaga przenoszenia danych repozytoriów między serwerami. Żądania dotyczące danego repozytorium zwykle trafiają do tej samej repliki, aby jej pamięć podręczna pozostawała przydatna, ale repozytorium nie zależy od dostępności tej konkretnej instancji.
Etap akceptacji sprawdza niezmienniki repozytorium, aby zagwarantować, że zaakceptowany commit reprezentuje prawidłowy stan repozytorium. Dla każdego repozytorium definiujemy jawny kontrakt, dzięki czemu mechaniczne kontrole mogą zapobiegać jego nadmiernemu rozrastaniu się. Duże pliki i pliki binarne, takie jak PDF-y i obrazy, są przechowywane za pośrednictwem Git LFS, a nie jako surowe obiekty blob Gita. Kompaktowanie zachowuje dostęp do najnowszej historii, a jednocześnie ogranicza rozmiar repozytorium. Po udanym przesłaniu zmian CLI pyta usługę Git, czy repozytorium wymaga kompaktowania. Jeśli liczba przechowywanych commitów przekroczy określony próg, usługa Git zachowuje tylko mniejszy zbiór najnowszych commitów. Starsza historia zostaje zastąpiona pojedynczą migawką początkową, a najnowsze commity są odtwarzane na nowo, co aktualizuje ich identyfikatory.
Prosty etap synchronizacji kontroluje współbieżne zapisy. Śledzi ostatni zaakceptowany commit, czyli head. Gdy otrzymuje zgłoszenie, akceptuje je tylko wtedy, gdy zostało ono zbudowane na tym head. W przeciwnym razie wysyła ustrukturyzowaną odpowiedź o nieaktualnej bazie (stale-base); przegrany musi wtedy odtworzyć swoją zmianę na nowym head i przesłać ją ponownie. Takie rozwiązanie gwarantuje, że współbieżnie działający agenci nie nadpisują po cichu nawzajem swoich zmian, a przy tym nie powoduje znaczących spowolnień. W naszych produkcyjnych przepływach pracy mniej niż 2% przesłań jest odrzucanych jako nieaktualne. Ogółem mediana opóźnienia przesłania wynosi poniżej 1,7 sekundy, a opóźnienie p99 – poniżej 8 sekund.
Usługa Git rejestruje również każdą zaakceptowaną zmianę. Dla każdego zaakceptowanego zapisu dodaje wpis do skrzynki nadawczej (outbox) – dziennika, w którym odnotowywane są repozytorium, nowy commit, użytkownik, który wprowadził zmianę, oraz zmienione ścieżki. Usługi podrzędne, takie jak parser, odczytują ten dziennik, aby znaleźć nowe zadania.
Razem te elementy tworzą warstwę zarządzania repozytoriami – bez tych części, których agenci nie potrzebują. Pull requesty są zbędne, ponieważ żaden człowiek nie przegląda poszczególnych zmian. Zamiast tego usługa Git sprawdza kontrakt w momencie przesłania, agent, który przegra wyścig, ponownie nakłada własną zmianę, a historia commitów rejestruje, kto co zmienił. Deterministyczne kontrole utrzymują każde repozytorium w granicach jego kontraktu, dzięki czemu nie trzeba polegać na człowieku-operatorze, który zarządzałby jego wzrostem.
Pamięć masowa: zapewnianie trwałości pracy
Warstwa pamięci masowej trwale zapisuje dane repozytoriów niezależnie od piaskownic i replik usługi Git. Repozytoria znajdują się w AWS S3Files, które udostępnia pamięć masową opartą na S3 przez interfejs systemu plików, z którego standardowy Git może korzystać bez żadnych modyfikacji. Każde z nich to repozytorium Git typu bare we współdzielonym systemie plików, zawierające obiekty i referencje repozytorium, a nie roboczą kopię plików.
Oddzielenie pamięci masowej od mocy obliczeniowej pozwala, by piaskownice pozostały efemeryczne. Każdy agent otrzymuje własną piaskownicę, a wielu agentów może pracować nad tym samym projektem bez współdzielenia maszyny. Jeśli piaskownica ulegnie awarii, zagrożona jest tylko praca, która nie została jeszcze przesłana.
Moglibyśmy zamiast tego dać każdemu projektowi długo działającą piaskownicę współdzieloną przez wszystkich jego agentów, tak aby pliki projektu znajdowały się na dysku tej maszyny. Powiązałoby to jednak moc obliczeniową agentów z miejscem, w którym działa maszyna, i wymagałoby zwymiarowania jej pod kątem okresów największego obciążenia. Musiałaby ona również pozostawać sprawna przez wiele miesięcy, a kopiami zapasowymi i odzyskiwaniem danych trzeba by było zarządzać w ramach systemu pamięci masowej projektu.
Przetwarzanie końcowe: udostępnianie dokumentów agentom w czytelnej formie
Głównym komponentem podrzędnym jest potok parsowania, który wyodrębnia tekst i metadane z nowo dodanych lub zaktualizowanych dokumentów, aby pliki projektu były łatwo czytelne dla agentów. Proces roboczy parsera pobiera aktualizacje z kolejki strumienia zmian, ustala zmienione pliki na podstawie metadanych commita i pobiera surowe bajty przy użyciu skrótu zawartości. Następnie parsuje dokument, uzyskując wyodrębniony tekst i metadane dokumentu.
Wyniki parsowania znajdują się poza repozytorium, w magazynie indeksowanym skrótem dokumentu źródłowego. Te artefakty nigdy nie są commitowane z powrotem do repozytorium, ponieważ niepotrzebnie zaśmiecałoby to historię i zwiększało liczbę współbieżnych zapisów. Zamiast tego wyniki parsowania trafiają do piaskownicy w ramach checkoutu i synchronizacji. Każda kopia robocza zawiera zarezerwowany katalog, którego CLI używa do materializacji artefaktów. Parsowanie odbywa się asynchronicznie, więc proces parsera działający w tle nie blokuje checkoutów.
Jak agenci korzystają z przestrzeni roboczej
Agenci eksplorują wersję repozytorium wczytaną do piaskownicy za pomocą standardowych narzędzi systemu plików. Zamiast podążać za sztywnym schematem „najpierw wyszukaj, potem przeczytaj”, wyświetlają zawartość folderów, przeszukują pliki za pomocą grep, czytają istotne fragmenty i na podstawie tego, co znajdą, decydują, gdzie szukać dalej.
Podobnie jak Computer, Search stosuje to samo podejście, korzystając ze standardowych narzędzi do obsługi plików. Osobny agent eksploracyjny przeszukuje projekt w ramach bardziej ograniczonego budżetu i zwraca ścieżki do istotnych plików wraz z potwierdzającymi fragmentami. Model generujący odpowiedź odczytuje następnie wybrane pliki i formułuje odpowiedź. Ponowne wykorzystanie istniejącej piaskownicy projektu skraca czas przygotowania: podłączenie do „ciepłej” kopii roboczej trwa około 2,9 sekundy, w porównaniu z mniej więcej 8 sekundami przy „zimnym” starcie.
Dzięki sparsowanemu tekstowi większe dokumenty, takie jak pliki PDF i pakietu Office, można przeszukiwać tymi samymi narzędziami. Agent najpierw sprawdza manifest – listę dokumentów, dla których dostępny jest wyodrębniony tekst – a następnie przeszukuje i odczytuje ten tekst jak zwykłe pliki. Oryginalny dokument pobiera tylko wtedy, gdy tekst nie wystarcza, na przykład aby przeanalizować rysunki, układ lub osadzone dane.
Porównaliśmy to podejście z wyszukiwaniem semantycznym w indeksie na podstawie 150 pytań finansowych dotyczących pojedynczych dokumentów z tego samego korpusu. Agent eksploracyjny uzyskał wynik 0,867 w zakresie wyszukiwania właściwego dokumentu i 0,627 w zakresie poprawnych odpowiedzi, wobec około 0,39 i 0,37 dla wyszukiwania semantycznego – czyli około 1,7 raza lepiej w przypadku odpowiedzi i 2 razy lepiej w przypadku wyszukiwania, przy opóźnieniu niższym o około 25%. Agent eksploracyjny pracuje głównie z wyodrębnionym tekstem i rzadko pobiera oryginalne pliki PDF.
Jedna wspólna infrastruktura
Trwała pamięć w Computer korzysta z tej samej infrastruktury systemu plików. Perplexity Brain, wiki wiedzy w Computer, przechowuje pamięć w repozytoriach wiedzy z własną historią i zasadami. Oddzielenie wiedzy od plików projektu sprawia, że aktualizacje pamięci w tle nie konkurują z edycjami tych plików. Sesja, która potrzebuje obu, wczytuje oba repozytoria.
Agenci działający w tle odczytują istniejącą wiedzę, uwzględniają nowe informacje i zapisują zaktualizowane strony jako commity. Inni agenci odczytują te strony za pomocą zwykłych narzędzi do obsługi plików, a ludzie również mogą je edytować. Autorzy udostępniają swoją pracę za pośrednictwem repozytorium, zamiast koordynować się bezpośrednio z każdym czytelnikiem. Historia commitów rejestruje, kto co zmienił, a outbox informuje usługi podrzędne o zaakceptowanych aktualizacjach. Ludzie i agenci mogą bazować na wzajemnej pracy, mając wgląd w to, jak ewoluowała wiedza.
Wnioski
Gdy ludzie i agenci współdzielą projekt, przestrzeń robocza nie tylko przechowuje pliki. Zapewnia wspólne miejsce do łączenia wkładu wszystkich uczestników i śledzenia zmian. Git już dostarcza znaczną część tych fundamentów. My dodajemy koordynację i automatyczne kontrole, aby agenci mogli przesyłać swoją pracę bez konieczności zatwierdzania każdej aktualizacji przez człowieka. W rezultacie powstaje platforma forge ograniczona do niezbędnego minimum, ponieważ współpraca między agentami i tworzenie oprogramowania przez wielu współtwórców to u podstaw ten sam problem.
Agenci pracują w niezależnych, tymczasowych piaskownicach, a jednocześnie współtworzą trwałe repozytoria. Limity repozytoriów pozwalają panować nad ich wzrostem, jawne pobieranie pozwala agentom wybierać, co ściągnąć, a zwykłe pliki umożliwiają eksplorację za pomocą znanych narzędzi. Aktualizacje w tle, interaktywne edycje i zaplanowane zadania mogą bazować na wzajemnej pracy bez bezpośredniej koordynacji.
W miarę jak coraz więcej agentów pracuje autonomicznie w Projektach, ich wspólna przestrzeń robocza musi pozostać niezawodna i zrozumiała dla ludzi. Cel jest prosty: każda zmiana powinna przetrwać dłużej niż agent, który ją wprowadził, stać się dostępna dla kolejnego współpracownika i pozostawić jasny zapis tego, co się zmieniło.
Cytowanie
@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}
}