Criar espaços de trabalho partilhados para pessoas e agentes
Como os projetos do Perplexity mantêm o trabalho de longa duração persistente, concorrente e rastreável.
Lançámos recentemente os projetos no Perplexity Computer, onde pessoas e agentes trabalham em conjunto em tarefas de longa duração. Cada projeto assenta num espaço de trabalho partilhado com um sistema de ficheiros que acumula contexto entre sessões, agentes e utilizadores. Uma colaboração entre vários utilizadores que se prolonga por meses exige persistência, concorrência e rastreabilidade:
- Persistência: o trabalho deve perdurar para além de qualquer sessão ou sandbox de um agente individual, para que o mesmo utilizador ou agente lhe possa dar continuidade no futuro e qualquer colaborador possa partir dele.
- Concorrência: vários utilizadores no mesmo projeto podem ter, cada um, vários agentes a fazer edições em paralelo que fazem avançar um estado partilhado, em vez de se sobreporem uns aos outros.
- Rastreabilidade: tanto os utilizadores como os agentes devem conseguir ver o histórico, para verificarem quem alterou o quê desde a última sessão sem voltarem a ler todo o projeto, e reverterem edições quando necessário.
Estes desafios são familiares para os engenheiros de software. As forjas Git surgiram há décadas para responder a estes requisitos: um serviço alojado que envolve o controlo de versões com funcionalidades colaborativas, para que muitos contribuidores possam convergir numa única fonte de verdade. O sistema de ficheiros que suporta os projetos é uma dessas forjas Git, criada para colaborações entre humanos e agentes e entre agentes.
Arquitetura
O Git já trata da persistência, da concorrência e da rastreabilidade. Identifica cada ficheiro pelo seu conteúdo, pelo que os ficheiros inalterados são armazenados uma única vez e as cópias guardadas nunca ficam desatualizadas. Cada commit guarda todos os ficheiros atualizados de uma só vez, para que os colaboradores nunca vejam um estado a meio. Quando dois escritores colidem, o que perdeu pode voltar a aplicar as suas alterações sobre a nova versão e tentar novamente. A cadeia de commits mostra quem alterou o quê e facilita o restauro de versões anteriores. Aquilo de que os agentes não precisam é o resto de uma forja criada para humanos, como ecrãs de revisão, gestão de ramos e notificações.
A nossa arquitetura executa todo o processo na nuvem e suporta todas as formas de trabalho de conhecimento para além da programação. Cada projeto do Computer é suportado por um repositório Git servido por 5 componentes:
- A CLI mantém checkouts locais, sincroniza atualizações e submete as alterações do agente em cada sandbox.
- O plano de controlo localiza o repositório do projeto e emite credenciais de curta duração para lhe aceder.
- O serviço Git envia os dados do repositório para as sandboxes, recebe as suas submissões e decide que submissão se torna o commit aceite mais recente.
- O armazenamento baseado no AWS S3 guarda os dados dos repositórios de forma duradoura.
- O processamento a jusante extrai texto e outras informações úteis dos documentos guardados e disponibiliza-os quando os agentes carregam ou atualizam o projeto.
Cada agente tem a sua própria sandbox isolada. Dentro dessa sandbox, trabalha com uma cópia local do repositório, gerida por uma pequena CLI. A CLI pede ao plano de controlo que localize o repositório e, em seguida, obtém e submete alterações através do serviço Git. Um proxy de agentes verifica o acesso dos pedidos das sandboxes antes de chegarem ao serviço Git. O serviço Git lê e escreve repositórios num sistema de ficheiros partilhado e decide se cada submissão se torna o commit aceite mais recente. Esse sistema de ficheiros é fornecido pelo AWS S3Files, que torna o armazenamento baseado no S3 acessível como ficheiros e diretórios comuns. O armazenamento está dividido em células isoladas, cada uma com o seu próprio sistema de ficheiros e réplicas do serviço Git. Depois de um commit ser aceite, workers em segundo plano extraem texto e outras informações úteis dos documentos alterados, armazenando os resultados separadamente do histórico do repositório e disponibilizando-os quando os agentes carregam ou atualizam o projeto.
De seguida, analisamos os componentes um a um.
CLI: trabalhar com ficheiros locais em sandboxes
Os agentes são executados no SPACE, a nossa plataforma interna de sandboxes. Cada sandbox tem uma pequena CLI que materializa o repositório e o mantém sincronizado. Por cada unidade de trabalho significativo realizado pelo agente, a CLI submete as alterações como um commit.
Normalmente, os agentes só mexem numa pequena fração dos ficheiros do projeto, pelo que não é necessário materializar todo o repositório à partida. Por isso, a CLI materializa de forma diferida: os ficheiros grandes e binários armazenados através do Git Large File Storage (LFS) chegam como pequenos ficheiros ponteiro que guardam o tamanho real do objeto, para que o agente possa usar o nome e o tamanho para decidir se vale ou não a pena descarregá-los. No caso de documentos como PDF, o agente lê primeiro o texto processado e só descarrega os ficheiros de origem quando necessário.
Outra opção natural seria utilizar um sistema de ficheiros virtual. Testámos uma implementação baseada em FUSE, mas era cerca de 400 vezes mais lenta do que os ficheiros locais em cargas de trabalho intensivas em sistema de ficheiros, uma vez que cada pedido exige uma ida e volta pela rede. Normalmente, também exige capacidades privilegiadas do anfitrião, pelo que cada agente teria de ser executado numa sandbox privilegiada.
Plano de controlo: localizar repositórios e conceder acesso
O plano de controlo localiza onde cada repositório está armazenado e concede acesso ao mesmo. Quando um repositório é criado, o plano de controlo atribui-o a uma célula de armazenamento, uma unidade de armazenamento isolada com as suas próprias réplicas do serviço Git. Quando um agente começa a trabalhar num projeto, a CLI pergunta ao plano de controlo onde está armazenado o repositório. O plano de controlo devolve a localização e credenciais temporárias para o serviço Git. O plano de controlo nunca lê nem escreve dados do repositório. É o serviço Git que decide o que entra num repositório.
Serviço Git: mover dados e coordenar atualizações
O serviço Git executa operações Git e transfere o conteúdo e o histórico de versões dos repositórios entre as sandboxes e o armazenamento. É uma camada fina sobre os próprios comandos de serviço do Git. Suporta a descoberta de refs, para indicar ao cliente onde está o head do repositório, o upload-pack para clonar e obter, e o receive-pack para receber novos objetos e um pedido para fazer avançar o head do repositório. Também serve a API do Git LFS: para ficheiros grandes e binários, emite ligações de curta duração para que as sandboxes possam carregar e descarregar esses ficheiros diretamente a partir do S3.
Começámos com um servidor de forja pronto a usar, para podermos prototipar as interfaces do agente e do utilizador em paralelo com o desenvolvimento da nossa própria forja leve, focada apenas nas operações Git de que precisamos.
O serviço é composto por uma frota de réplicas, cada uma delas uma instância em execução do mesmo servidor. Uma célula agrupa o armazenamento partilhado com um conjunto de réplicas e os respetivos serviços de suporte. Assim, as réplicas de uma célula podem aceder ao mesmo sistema de ficheiros partilhado, em vez de manterem cópias independentes de cada repositório.
Este armazenamento partilhado permite que as réplicas se mantenham sem estado. Qualquer réplica da célula pode servir qualquer um dos seus repositórios, pelo que substituir ou adicionar réplicas não exige mover dados de repositórios entre servidores. Normalmente, os pedidos para um repositório vão para a mesma réplica, para manter as suas caches úteis, mas o repositório não depende de essa instância específica continuar disponível.
O passo de aceitação verifica as invariantes do repositório para garantir que um commit aceite corresponde a um estado válido do repositório. Definimos um contrato explícito para cada repositório, para que verificações mecânicas impeçam que cresça demasiado. Os ficheiros grandes e binários, como PDF e imagens, são armazenados através do Git LFS, em vez de serem guardados como blobs Git em bruto. A compactação mantém o histórico recente disponível e limita o tamanho do repositório. Após uma submissão bem-sucedida, a CLI pergunta ao serviço Git se o repositório precisa de compactação. Se o número de commits retidos exceder um limiar, o serviço Git mantém apenas um conjunto mais pequeno dos commits mais recentes. O histórico mais antigo é substituído por um único snapshot inicial, e os commits recentes são reaplicados para atualizar os identificadores de commit.
Um passo de sincronização simples controla os escritores concorrentes. Acompanha o commit aceite mais recente, ou head. Quando recebe uma submissão, só a aceita se tiver sido construída sobre esse head. Caso contrário, envia uma resposta estruturada de base desatualizada; o perdedor tem então de reaplicar a sua alteração sobre o novo head e voltar a submeter. Esta abordagem garante que os agentes concorrentes não substituem silenciosamente o trabalho uns dos outros, sem causar abrandamentos significativos. Nos nossos fluxos de trabalho de produção, menos de 2% das submissões são rejeitadas por estarem desatualizadas. No geral, a latência mediana de submissão é inferior a 1,7 segundos e a latência p99 é inferior a 8 segundos.
O serviço Git também regista cada alteração aceite. Por cada escrita aceite, adiciona uma entrada a uma caixa de saída (outbox), um registo que indica o repositório, o novo commit, o utilizador que fez a alteração e os caminhos alterados. Os serviços a jusante, como o parser, leem este registo para encontrar novo trabalho.
Em conjunto, estas peças formam uma camada de gestão de repositórios, sem as partes de que os agentes não precisam. Os pull requests são desnecessários, porque nenhum humano revê cada alteração. Em vez disso, o serviço Git verifica o contrato no momento da submissão, o agente que perde uma corrida volta a aplicar a sua própria alteração e o histórico de commits regista quem alterou o quê. As verificações determinísticas mantêm cada repositório dentro do seu contrato, em vez de dependerem de um operador humano para gerir o crescimento.
Armazenamento: garantir a durabilidade do trabalho
A camada de armazenamento guarda de forma duradoura os dados dos repositórios, independentemente das sandboxes e das réplicas do serviço Git. Os repositórios residem no AWS S3Files, que expõe armazenamento baseado no S3 através de uma interface de sistema de ficheiros que o Git padrão pode usar sem modificações. Cada um é um repositório Git bare no sistema de ficheiros partilhado, que contém os objetos e as referências do repositório em vez de um checkout de trabalho.
Desacoplar o armazenamento da computação permite que as sandboxes se mantenham efémeras. Cada agente recebe a sua própria sandbox, e muitos agentes podem trabalhar no mesmo projeto sem partilharem uma máquina. Se uma sandbox falhar, só o trabalho que ainda não foi submetido fica em risco.
Em alternativa, poderíamos dar a cada projeto uma sandbox de longa duração partilhada por todos os seus agentes, para que os ficheiros do projeto residissem no disco dessa máquina. No entanto, isso ligaria a computação dos agentes ao local onde a máquina é executada e obrigaria a dimensioná-la para os seus períodos de maior atividade. Também teria de se manter em bom estado durante meses, com cópias de segurança e recuperação geridas como parte do sistema de armazenamento do projeto.
Processamento a jusante: tornar os documentos legíveis para os agentes
O principal componente a jusante é um pipeline de parsers que extrai texto e metadados de documentos recém-adicionados ou atualizados, para tornar os ficheiros do projeto facilmente legíveis pelos agentes. Um worker do parser consome atualizações da fila do fluxo de alterações, deriva os ficheiros alterados a partir dos metadados do commit e obtém os bytes em bruto através do hash do conteúdo. Em seguida, processa o documento para produzir o texto extraído e os metadados do documento.
Os resultados do processamento ficam fora do repositório, num armazenamento indexado pelo hash do documento de origem. Estes artefactos nunca são enviados como commit para o repositório, pois isso poluiria desnecessariamente o histórico e aumentaria o número de escritas concorrentes. Em vez disso, os resultados do processamento chegam a uma sandbox através do checkout e da sincronização. Cada checkout inclui um diretório reservado que a CLI utiliza para materializar os artefactos. O processamento ocorre de forma assíncrona, pelo que um worker do parser em segundo plano não bloqueia os checkouts.
Como os agentes utilizam o espaço de trabalho
Os agentes exploram a versão do repositório carregada na sandbox com ferramentas padrão de sistema de ficheiros. Em vez de seguirem um pipeline fixo de pesquisar e depois ler, listam pastas, pesquisam o conteúdo dos ficheiros com grep, leem as passagens relevantes e usam o que encontram para decidir onde procurar a seguir.
Tal como o Computer, o Search utiliza a mesma abordagem através das suas ferramentas de ficheiros padrão. Um agente de exploração separado pesquisa o projeto com um orçamento mais limitado e devolve caminhos de ficheiros relevantes e excertos de apoio. O modelo de resposta lê então os ficheiros selecionados e gera a resposta. Reutilizar uma sandbox de projeto existente reduz o tempo de preparação: ligar a um checkout já aquecido demora cerca de 2,9 segundos, em comparação com cerca de 8 segundos num arranque a frio.
O texto processado torna os documentos maiores, como PDF e ficheiros do Office, pesquisáveis com as mesmas ferramentas. Primeiro, o agente consulta um manifesto, uma lista que mostra que documentos têm texto extraído disponível, e depois pesquisa e lê esse texto como ficheiros comuns. Só descarrega o documento original quando o texto não é suficiente, por exemplo, para inspecionar figuras, a disposição ou dados incorporados.
Comparámos esta abordagem com a pesquisa semântica sobre um índice, em 150 perguntas financeiras de documento único sobre o mesmo corpus. O agente de exploração obteve 0,867 na recuperação do documento correto e 0,627 na resposta correta, face a cerca de 0,39 e 0,37 da pesquisa semântica, ou seja, cerca de 1,7x melhor nas respostas e 2x melhor na recuperação, com uma latência cerca de 25% inferior. O agente de exploração trabalha sobretudo com texto extraído e raramente descarrega os PDF originais.
Uma infraestrutura partilhada
A memória persistente do Computer utiliza a mesma infraestrutura de sistema de ficheiros. O Perplexity Brain, a wiki de conhecimento do Computer, armazena a memória em repositórios de conhecimento com histórico e políticas próprios. Manter o conhecimento separado dos ficheiros do projeto significa que as atualizações de memória em segundo plano não competem com as edições a esses ficheiros. Uma sessão que precise de ambos carrega os dois repositórios.
Os agentes em segundo plano leem o conhecimento existente, incorporam novas informações e guardam as páginas atualizadas como commits. Outros agentes leem essas páginas com ferramentas de ficheiros comuns, e as pessoas também as podem editar. Quem escreve partilha o seu trabalho através do repositório, em vez de se coordenar diretamente com cada leitor. O histórico de commits regista quem alterou o quê, enquanto a caixa de saída comunica as atualizações aceites aos serviços a jusante. Pessoas e agentes podem partir do trabalho uns dos outros, com um registo de como o conhecimento evoluiu.
Conclusão
Quando pessoas e agentes partilham um projeto, o espaço de trabalho faz mais do que armazenar ficheiros. Proporciona um local comum para combinar contribuições e acompanhar o que mudou. O Git já fornece grande parte dessa base. Acrescentamos coordenação e verificações automáticas para que os agentes possam submeter trabalho sem que uma pessoa aprove cada atualização. O resultado é uma forja reduzida ao essencial, já que a colaboração entre agentes e o desenvolvimento de software com vários contribuidores são, no fundo, o mesmo problema.
Os agentes trabalham em sandboxes independentes e temporárias enquanto contribuem para repositórios duradouros. Os limites dos repositórios mantêm o crescimento controlável, os downloads explícitos permitem que os agentes escolham o que obter e os ficheiros comuns permitem-lhes explorar com ferramentas familiares. As atualizações em segundo plano, as edições interativas e as tarefas agendadas podem partir do trabalho umas das outras sem coordenação direta.
À medida que mais agentes trabalham de forma autónoma dentro dos projetos, o seu espaço de trabalho partilhado tem de continuar a ser fiável e compreensível para as pessoas. O objetivo é simples: cada alteração deve ser mais duradoura do que o agente que a produziu, ficar disponível para o colaborador seguinte e deixar um registo claro do que mudou.
Citação
@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}
}