Concevoir des espaces de travail partagés pour les humains et les agents

Comment les Projets de Perplexity assurent la persistance, la concurrence et la traçabilité du travail de longue haleine.

AuteursPerplexity Engineering

Nous avons récemment lancé Projets, où humains et agents collaborent sur des tâches de longue haleine dans Perplexity Computer. Chaque projet repose sur un espace de travail partagé doté d’un système de fichiers qui accumule le contexte au fil des sessions, des agents et des utilisateurs. Une collaboration multijoueur qui s’étend sur des mois exige persistance, concurrence et traçabilité :

  • Persistance : le travail doit perdurer au-delà de toute session d’agent ou de tout bac à sable individuel, afin que le même utilisateur ou agent puisse le poursuivre plus tard et que tout collaborateur puisse s’en servir comme base.
  • Concurrence : plusieurs utilisateurs d’un même projet peuvent chacun disposer de plusieurs agents qui effectuent des modifications en parallèle, lesquelles font progresser un état partagé plutôt que de s’écraser mutuellement.
  • Traçabilité : les utilisateurs comme les agents doivent pouvoir consulter l’historique afin de vérifier qui a modifié quoi depuis leur dernière session, sans relire l’ensemble du projet, et d’annuler des modifications au besoin.

Ces défis sont familiers aux ingénieurs logiciels. Les forges Git sont apparues il y a des décennies pour répondre à ces exigences : un service hébergé qui enrichit la gestion de versions de fonctionnalités collaboratives afin que de nombreux contributeurs puissent converger vers une source de vérité unique. Le système de fichiers qui propulse les Projets est une forge Git de ce type, conçue pour la collaboration entre humains et agents, et entre agents.

Un seul projet : les agents interactifs, les agents planifiés et les agents d’autres utilisateurs convergent tous vers le même dépôt.

Architecture

Git gère déjà la persistance, la concurrence et la traçabilité. Il identifie chaque fichier par son contenu : les fichiers inchangés ne sont donc stockés qu’une seule fois et les copies enregistrées ne deviennent jamais obsolètes. Chaque commit enregistre tous les fichiers mis à jour en une seule opération, de sorte que les collaborateurs ne voient jamais un état à moitié terminé. Lorsque deux écritures entrent en collision, celle qui a perdu peut réappliquer ses modifications sur la nouvelle version et réessayer. La chaîne de commits montre qui a modifié quoi et permet de restaurer facilement des versions antérieures. Ce dont les agents n’ont pas besoin, c’est du reste d’une forge conçue pour les humains, comme les écrans de revue, la gestion des branches et les notifications.

Notre architecture exécute l’ensemble du processus dans le nuage et prend en charge toutes les formes de travail intellectuel, au-delà de la programmation. Chaque projet Computer repose sur un dépôt Git servi par 5 composants :

  • La CLI gère les copies locales, synchronise les mises à jour et soumet les modifications de l’agent dans chaque bac à sable.
  • Le plan de contrôle localise le dépôt du projet et délivre des identifiants de courte durée pour y accéder.
  • Le service Git envoie les données des dépôts aux bacs à sable, reçoit leurs soumissions et décide quelle soumission devient le dernier commit accepté.
  • Le stockage reposant sur AWS S3 conserve durablement les données des dépôts.
  • Le traitement en aval extrait le texte et d’autres informations utiles des documents enregistrés et les rend disponibles lorsque les agents chargent ou actualisent le projet.

Chaque agent dispose de son propre bac à sable isolé. À l’intérieur de celui-ci, il travaille sur une copie locale du dépôt, gérée par une petite CLI. La CLI demande au plan de contrôle de localiser le dépôt, puis récupère et soumet les modifications par l’intermédiaire du service Git. Un proxy d’agent vérifie les droits d’accès des requêtes provenant des bacs à sable avant qu’elles n’atteignent le service Git. Le service Git lit et écrit les dépôts sur un système de fichiers partagé, et décide si chaque soumission devient le dernier commit accepté. Ce système de fichiers est fourni par AWS S3Files, qui rend le stockage reposant sur S3 accessible sous forme de fichiers et de répertoires ordinaires. Le stockage est divisé en cellules isolées, chacune dotée de son propre système de fichiers et de ses propres répliques du service Git. Une fois un commit accepté, des processus en arrière-plan extraient le texte et d’autres informations utiles des documents modifiés, stockent les résultats séparément de l’historique du dépôt et les rendent disponibles lorsque les agents chargent ou actualisent le projet.

Nous passons maintenant en revue chacun des composants.

La CLI contacte le plan de contrôle pour localiser son dépôt, puis effectue les récupérations et les soumissions auprès du service Git par l’intermédiaire du proxy d’agent. Le service Git vérifie les soumissions et met à jour la tête acceptée et la boîte d’envoi dans DynamoDB. Les répliques propres à chaque cellule utilisent le stockage S3Files, tandis que des processus en aval extraient le texte destiné aux copies locales et à la synchronisation.

CLI : travailler avec des fichiers locaux dans les bacs à sable

Les agents s’exécutent dans SPACE, notre plateforme interne de bacs à sable. Chaque bac à sable comporte une petite CLI qui matérialise le dépôt et le maintient synchronisé. Pour chaque unité de travail significative effectuée par l’agent, elle soumet les modifications sous forme de commit.

Les agents ne touchent généralement qu’une petite fraction des fichiers du projet; il n’est donc pas nécessaire de matérialiser l’intégralité du dépôt dès le départ. C’est pourquoi la CLI procède à une matérialisation différée : les fichiers volumineux et binaires stockés au moyen de Git Large File Storage (LFS) arrivent sous forme de petits fichiers pointeurs indiquant la taille réelle de l’objet, ce qui permet à l’agent de se fier au nom et à la taille pour décider si un téléchargement en vaut la peine. Pour les documents comme les PDF, l’agent lit d’abord le texte analysé et ne télécharge les fichiers sources qu’en cas de besoin.

Une autre option naturelle serait d’utiliser un système de fichiers virtuel. Nous avons testé une implémentation reposant sur FUSE, mais elle était environ 400 fois plus lente que les fichiers locaux pour les charges de travail sollicitant intensivement le système de fichiers, puisque chaque requête nécessite un aller-retour réseau. Elle exige aussi généralement des capacités privilégiées sur l’hôte, de sorte que chaque agent devrait s’exécuter dans un bac à sable privilégié.

La taille du pointeur et le manifeste d’analyse déterminent la marche à suivre : lire le texte analysé, télécharger la source ou ignorer le fichier.

Plan de contrôle : localiser les dépôts et accorder l’accès

Le plan de contrôle localise l’emplacement de stockage de chaque dépôt et en accorde l’accès. Lorsqu’un dépôt est créé, le plan de contrôle l’attribue à une cellule de stockage, une unité de stockage isolée dotée de ses propres répliques du service Git. Lorsqu’un agent commence à travailler sur un projet, la CLI demande au plan de contrôle où le dépôt est stocké. Le plan de contrôle renvoie l’emplacement ainsi que des identifiants temporaires pour le service Git. Le plan de contrôle ne lit ni n’écrit jamais les données des dépôts. C’est le service Git qui décide de ce qui entre dans un dépôt.

Service Git : déplacer les données et coordonner les mises à jour

Le service Git exécute les opérations Git et transfère le contenu et l’historique des versions des dépôts entre les bacs à sable et le stockage. Il s’agit d’une mince surcouche des commandes de service propres à Git. Il prend en charge la découverte des références, qui indique au client où se trouve la tête du dépôt, upload-pack pour le clonage et la récupération, et receive-pack pour la réception de nouveaux objets et d’une demande d’avancement de la tête du dépôt. Il sert également l’API Git LFS : pour les fichiers volumineux et binaires, il émet des liens de courte durée afin que les bacs à sable puissent téléverser et télécharger ces fichiers directement depuis S3.

Nous avons commencé avec un serveur de forge prêt à l’emploi, ce qui nous a permis de prototyper les interfaces agent et utilisateur tout en construisant en parallèle notre propre forge légère, axée uniquement sur les opérations Git dont nous avons besoin.

Le service se compose d’un parc de répliques, chacune étant une instance en cours d’exécution du même serveur. Une cellule regroupe un stockage partagé, un ensemble de répliques et leurs services de soutien. Les répliques d’une même cellule peuvent ainsi accéder au même système de fichiers partagé, plutôt que de maintenir des copies indépendantes de chaque dépôt.

Ce stockage partagé permet aux répliques de rester sans état. N’importe quelle réplique de la cellule peut servir n’importe lequel de ses dépôts; remplacer ou ajouter des répliques ne nécessite donc pas de déplacer les données des dépôts d’un serveur à l’autre. Les requêtes visant un dépôt sont normalement dirigées vers la même réplique afin que ses caches restent utiles, mais le dépôt ne dépend pas de la disponibilité continue de cette instance en particulier.

L’étape d’acceptation vérifie les invariants du dépôt afin de garantir qu’un commit accepté correspond à un état valide du dépôt. Nous définissons un contrat explicite pour chaque dépôt, afin que des vérifications automatisées puissent l’empêcher de devenir trop volumineux. Les fichiers volumineux et binaires, comme les PDF et les images, sont stockés au moyen de Git LFS plutôt que sous forme de blobs Git bruts. La compaction préserve l’historique récent tout en limitant la taille du dépôt. Après une soumission réussie, la CLI demande au service Git si le dépôt doit être compacté. Si le nombre de commits conservés dépasse un seuil, le service Git ne garde qu’un ensemble plus restreint des commits les plus récents. L’historique plus ancien est remplacé par un instantané de départ unique, et les commits récents sont rejoués pour mettre à jour les identifiants de commit.

La compaction conserve les commits les plus récents, regroupe l’historique plus ancien dans une seule racine d’instantané et rejoue les commits récents avec de nouveaux identifiants; la nouvelle tête conserve les mêmes fichiers.

Une simple étape de synchronisation gère les écritures concurrentes. Elle suit le dernier commit accepté, appelé tête (head). Lorsqu’elle reçoit une soumission, elle ne l’accepte que si celle-ci a été construite sur cette tête. Sinon, elle renvoie une réponse structurée de base obsolète; le perdant doit alors rejouer sa modification par-dessus la nouvelle tête et la soumettre de nouveau. Cette conception garantit que les agents concurrents ne s’écrasent pas mutuellement en silence, sans pour autant causer de ralentissements notables. Dans nos flux de travail en production, moins de 2 % des soumissions sont rejetées comme obsolètes. Dans l’ensemble, la latence médiane des soumissions est inférieure à 1,7 seconde, et la latence p99 est inférieure à 8 secondes.

Deux agents soumettent simultanément; l’un est accepté, l’autre reçoit une réponse de base obsolète, rejoue sa modification sur la nouvelle tête et la soumet de nouveau.

Le service Git consigne aussi chaque modification acceptée. Pour chaque écriture acceptée, il ajoute une entrée dans une boîte d’envoi (outbox), un journal qui indique le dépôt, le nouveau commit, l’utilisateur à l’origine de la modification et les chemins modifiés. Les services en aval, comme l’analyseur, lisent ce journal pour trouver du nouveau travail.

Ensemble, ces éléments forment une couche de gestion des dépôts, sans les parties dont les agents n’ont pas besoin. Les pull requests sont inutiles, car aucun humain n’examine chaque modification. À la place, le service Git vérifie le contrat au moment de la soumission, l’agent qui perd la course réapplique sa propre modification, et l’historique des commits consigne qui a modifié quoi. Des vérifications déterministes maintiennent chaque dépôt dans les limites de son contrat, plutôt que de compter sur un opérateur humain pour en gérer la croissance.

Stockage : assurer la durabilité du travail

La couche de stockage conserve durablement les données des dépôts, indépendamment des bacs à sable et des répliques du service Git. Les dépôts résident sur AWS S3Files, qui expose un stockage reposant sur S3 au moyen d’une interface de système de fichiers que Git standard peut utiliser sans modification. Chacun est un dépôt Git nu (bare) sur le système de fichiers partagé, qui contient les objets et les références du dépôt plutôt qu’une copie de travail.

Le découplage du stockage et du calcul permet aux bacs à sable de rester éphémères. Chaque agent obtient son propre bac à sable, et de nombreux agents peuvent travailler sur le même projet sans partager de machine. Si un bac à sable plante, seul le travail qui n’a pas encore été soumis risque d’être perdu.

Nous pourrions plutôt attribuer à chaque projet un bac à sable de longue durée partagé par tous ses agents, de sorte que les fichiers du projet résideraient sur le disque de cette machine. Cependant, cela lierait la puissance de calcul des agents à l’endroit où la machine est hébergée et obligerait à la dimensionner en fonction de ses périodes de pointe. Elle devrait également rester en bon état pendant des mois, avec des sauvegardes et une reprise gérées dans le cadre du système de stockage du projet.

Un bac à sable de longue durée partagé par les agents d’un projet, comparé à des bacs à sable de courte durée propres à chaque agent qui accèdent à un stockage partagé durable par l’intermédiaire de répliques sans état du service Git.

Traitement en aval : rendre les documents lisibles pour les agents

Le principal composant en aval est un pipeline d’analyse qui extrait le texte et les métadonnées des documents nouvellement ajoutés ou mis à jour afin de rendre les fichiers du projet facilement lisibles par les agents. Un processus d’analyse consomme les mises à jour de la file d’attente du flux de modifications, déduit les fichiers modifiés à partir des métadonnées du commit et récupère les octets bruts à l’aide du hachage du contenu. Il analyse ensuite le document pour produire le texte extrait et les métadonnées du document.

Les résultats d’analyse résident à l’extérieur du dépôt, dans un magasin indexé par le hachage du document source. Ces artefacts ne sont jamais réintégrés au dépôt par commit, car cela polluerait inutilement l’historique et augmenterait le nombre d’écritures concurrentes. Les résultats d’analyse parviennent plutôt au bac à sable lors de la création de la copie locale et de la synchronisation. Chaque copie locale comporte un répertoire réservé que la CLI utilise pour matérialiser les artefacts. L’analyse s’effectue de façon asynchrone, de sorte qu’un processus d’analyse en arrière-plan ne bloque pas la création des copies locales.

Comment les agents utilisent l’espace de travail

Les agents explorent la version du dépôt chargée dans le bac à sable à l’aide d’outils standards de système de fichiers. Plutôt que de suivre un pipeline fixe de recherche puis de lecture, ils listent les dossiers, cherchent dans le contenu des fichiers avec grep, lisent les passages pertinents et s’appuient sur ce qu’ils trouvent pour décider où chercher ensuite.

À l’instar de Computer, Search applique la même approche au moyen de ses outils de fichiers standards. Un agent d’exploration distinct parcourt le projet avec un budget plus limité et renvoie les chemins des fichiers pertinents ainsi que des extraits à l’appui. Le modèle de réponse lit ensuite les fichiers sélectionnés et génère la réponse. Réutiliser un bac à sable de projet existant réduit le temps de préparation : se rattacher à une copie locale déjà prête prend environ 2,9 secondes, contre environ 8 secondes pour un démarrage à froid.

Les bacs à sable de Computer, le sous-agent d’exploration d’Ask, les rédacteurs de connaissances en arrière-plan et les processus d’analyse lisent et écrivent tous dans le même dépôt et la même boîte d’envoi.

Le texte analysé permet d’effectuer des recherches dans des documents plus volumineux, comme les PDF et les fichiers Office, avec les mêmes outils. L’agent consulte d’abord un manifeste, soit une liste indiquant les documents dont le texte extrait est disponible, puis cherche dans ce texte et le lit comme des fichiers ordinaires. Il ne télécharge le document original que lorsque le texte ne suffit pas, par exemple pour examiner des figures, la mise en page ou des données intégrées.

Nous avons comparé cette approche à une recherche sémantique sur un index, à l’aide de 150 questions financières portant chacune sur un seul document du même corpus. L’agent d’exploration a obtenu un score de 0,867 pour la récupération du bon document et de 0,627 pour l’exactitude des réponses, contre environ 0,39 et 0,37 pour la recherche sémantique, soit des résultats environ 1,7 fois meilleurs pour les réponses et 2 fois meilleurs pour la récupération, avec une latence inférieure d’environ 25 %. L’agent d’exploration travaille surtout avec le texte extrait et télécharge rarement les PDF originaux.

Comparaison entre l’exploration et la recherche sémantique de fichiers sur le banc d’essai interne.

Une seule infrastructure partagée

La mémoire persistante de Computer repose sur la même infrastructure de système de fichiers. Perplexity Brain, le wiki de connaissances de Computer, stocke la mémoire dans des dépôts de connaissances dotés de leur propre historique et de leurs propres politiques. Séparer les connaissances des fichiers de projet évite que les mises à jour de mémoire en arrière-plan entrent en concurrence avec les modifications de ces fichiers. Une session qui a besoin des deux charge les deux dépôts.

Des agents en arrière-plan lisent les connaissances existantes, intègrent les nouvelles informations et enregistrent les pages mises à jour sous forme de commits. D’autres agents lisent ces pages avec des outils de fichiers ordinaires, et les humains peuvent aussi les modifier. Les rédacteurs partagent leur travail par l’intermédiaire du dépôt plutôt que de se coordonner directement avec chaque lecteur. L’historique des commits consigne qui a modifié quoi, tandis que la boîte d’envoi signale les mises à jour acceptées aux services en aval. Humains et agents peuvent s’appuyer sur le travail des uns et des autres, avec une trace de l’évolution des connaissances.

Conclusion

Lorsque des humains et des agents partagent un projet, l’espace de travail ne se contente pas de stocker des fichiers. Il offre un lieu commun pour combiner les contributions et suivre ce qui a changé. Git fournit déjà une grande partie de ces fondations. Nous y ajoutons de la coordination et des vérifications automatisées afin que les agents puissent soumettre leur travail sans qu’une personne approuve chaque mise à jour. Le résultat est une forge réduite à l’essentiel, car la collaboration entre agents et le développement logiciel à contributeurs multiples sont, au fond, le même problème.

Les agents travaillent dans des bacs à sable indépendants et temporaires tout en contribuant à des dépôts durables. Les limites de dépôt permettent de maîtriser la croissance, les téléchargements explicites laissent les agents choisir ce qu’ils récupèrent, et les fichiers ordinaires leur permettent d’explorer avec des outils familiers. Les mises à jour en arrière-plan, les modifications interactives et les tâches planifiées peuvent s’appuyer sur le travail des uns et des autres sans coordination directe.

À mesure que de plus en plus d’agents travaillent de façon autonome au sein des Projets, leur espace de travail partagé doit demeurer fiable et compréhensible pour les humains. L’objectif est simple : chaque modification doit survivre à l’agent qui l’a produite, devenir accessible au prochain collaborateur et laisser une trace claire de ce qui a changé.

Citation

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