為人與 AI 代理程式打造共享工作空間
Perplexity 專案功能如何讓長期工作保持持久、可並行且可追溯。
我們最近推出了 專案功能,讓人與 AI 代理程式在 Perplexity Computer 中攜手處理長期任務。每個專案都建基於一個共享工作空間,其檔案系統會跨工作階段、AI 代理程式和用戶累積脈絡。橫跨數月的多人協作需要持久性、並行性和可追溯性:
- 持久性:工作成果應能在任何單一 AI 代理程式工作階段或沙箱結束後持續保存,讓同一用戶或 AI 代理程式日後可以繼續工作,任何協作者亦可在此基礎上發展。
- 並行性:同一專案中的多位用戶,各自可以有多個 AI 代理程式同時進行編輯,共同推進同一個共享狀態,而不會互相覆寫。
- 可追溯性:用戶和 AI 代理程式都應能查看歷史記錄,以便檢查自上次工作階段以來誰更改了甚麼,而無需重新閱讀整個專案,並在需要時還原編輯。
這些挑戰對軟件工程師來說並不陌生。數十年前,Git 代碼託管平台(Git forge)正是為了滿足這些需求而出現:這是一種託管服務,以協作功能包裝版本控制,讓眾多貢獻者能匯聚於單一可信來源。驅動專案功能的檔案系統,正是這樣一個 Git 代碼託管平台,專為人與 AI 代理程式之間,以及 AI 代理程式彼此之間的協作而打造。
架構
Git 本身已能處理持久性、並行性和可追溯性。它以內容來識別每個檔案,因此未更改的檔案只會儲存一次,已儲存的內容永遠不會過時。每次 commit 會一次過儲存所有已更新的檔案,因此協作者永遠不會看到只完成一半的狀態。當兩個寫入者發生衝突時,落敗的一方可以在新版本上重新套用其變更,然後再試一次。一連串的 commit 顯示了誰更改了甚麼,並讓還原至較早版本變得輕而易舉。AI 代理程式不需要的,是代碼託管平台中其餘為人類而設的部分,例如審查畫面、分支管理和通知。
我們的架構在雲端執行整個流程,並支援編程以外各種形式的知識工作。每個 Computer 專案都由一個 Git 儲存庫支援,而該儲存庫由 5 個元件提供服務:
- CLI 在每個沙箱中維護本機簽出、同步更新,並提交 AI 代理程式的變更。
- 控制平面負責找出專案儲存庫,並簽發存取該儲存庫的短期憑證。
- Git 服務負責將儲存庫資料傳送至沙箱、接收沙箱的提交,並決定哪一項提交成為最新獲接受的 commit。
- 以 AWS S3 為基礎的儲存層負責持久保存儲存庫資料。
- 下游處理會從已儲存的文件中擷取文字和其他有用資訊,並在 AI 代理程式載入或重新整理專案時提供使用。
每個 AI 代理程式都有自己獨立的沙箱。在沙箱內,它在由小型 CLI 管理的本機儲存庫上工作。CLI 會要求控制平面找出儲存庫,然後透過 Git 服務取得和提交變更。AI 代理程式 Proxy 會在沙箱請求到達 Git 服務之前檢查存取權限。Git 服務在共用檔案系統上讀取和寫入儲存庫,並決定每項提交是否成為最新獲接受的 commit。該檔案系統由 AWS S3Files 提供,讓以 S3 為基礎的儲存能以一般檔案和目錄的形式存取。儲存空間劃分為多個獨立的 cell,每個 cell 都有自己的檔案系統和 Git 服務副本。在 commit 獲接受後,背景工作程序會從變更的文件中擷取文字和其他有用資訊,將結果與儲存庫歷史記錄分開儲存,並在 AI 代理程式載入或重新整理專案時提供使用。
接下來,我們會逐一介紹各個元件。
CLI:在沙箱中處理本機檔案
AI 代理程式在我們自家開發的沙箱平台 SPACE 中執行。每個沙箱都有一個小型 CLI,負責將儲存庫實體化並保持同步。AI 代理程式每完成一個有意義的工作單位,CLI 便會將變更作為一個 commit 提交。
AI 代理程式通常只會接觸專案檔案中的一小部分,因此無須預先將整個儲存庫實體化。有見及此,CLI 採用延遲實體化:透過 Git Large File Storage(LFS)儲存的大型檔案和二進位檔案,會以小型指標檔案的形式送達,當中記錄了物件的實際大小,讓 AI 代理程式可以根據名稱和大小判斷是否值得下載。對於 PDF 等文件,AI 代理程式會先讀取解析後的文字,只在必要時才下載原始檔案。
另一個順理成章的選擇是使用虛擬檔案系統。我們測試過以 FUSE 為基礎的實作,但在大量使用檔案系統的工作負載上,它比本機檔案慢約 400 倍,因為每個請求都需要一次網絡往返。此外,它通常需要主機提供特權能力,因此每個 AI 代理程式都必須在具特權的沙箱中執行。
控制平面:定位儲存庫並授予存取權限
控制平面負責找出每個儲存庫的存放位置,並授予存取權限。建立儲存庫時,控制平面會將其指派到一個儲存 cell(storage cell),即一個擁有自己 Git 服務副本的獨立儲存單位。當 AI 代理程式開始處理某個專案時,CLI 會向控制平面查詢儲存庫的存放位置。控制平面會回傳該位置及 Git 服務的臨時憑證。控制平面從不讀取或寫入儲存庫資料。決定哪些內容能進入儲存庫的是 Git 服務。
Git 服務:傳輸資料與協調更新
Git 服務負責執行 Git 操作,並在沙箱與儲存之間傳輸儲存庫內容和版本歷史記錄。它是 Git 本身伺服器端命令的輕量封裝層。它支援 ref 探索(用來告訴用戶端儲存庫的 head 在哪裏)、用於複製和取得的 upload-pack,以及用於接收新物件和推進儲存庫 head 請求的 receive-pack。它亦提供 Git LFS API:對於大型檔案和二進位檔案,它會發出短期連結,讓沙箱直接從 S3 上載和下載這些檔案。
我們一開始使用現成的代碼託管平台伺服器,這樣便能一邊開發 AI 代理程式和用戶介面的原型,一邊建立我們自己的輕量級代碼託管平台,只專注於我們所需的 Git 操作。
這項服務由一組副本組成,每個副本都是同一伺服器的一個運行中執行個體。cell 將共用儲存、一組副本及其支援服務組合在一起。這樣,同一 cell 內的副本便能存取相同的共用檔案系統,而無需各自為每個儲存庫保存獨立的一份資料。
這種共用儲存讓副本能保持無狀態。cell 中的任何副本都能為該 cell 的任何儲存庫提供服務,因此更換或新增副本時,無需在伺服器之間搬移儲存庫資料。針對某個儲存庫的請求通常會傳送到同一個副本,以充分利用其快取,但儲存庫並不依賴該特定執行個體保持可用。
接受步驟會檢查儲存庫的不變條件,確保獲接受的 commit 代表有效的儲存庫狀態。我們為每個儲存庫訂立明確的約定,讓機械式檢查能防止儲存庫變得過於龐大。PDF 和圖片等大型檔案及二進位檔案會透過 Git LFS 儲存,而非以原始 Git blob 形式存放。壓縮(compaction)機制在限制儲存庫大小的同時,保留近期的歷史記錄。每次成功提交後,CLI 會詢問 Git 服務該儲存庫是否需要壓縮。如果保留的 commit 數量超過門檻,Git 服務只會保留較少量的最新 commit。較舊的歷史記錄會由單一起始快照取代,而近期的 commit 則會重新套用,以更新 commit 識別碼。
一個簡單的同步步驟負責處理並行寫入者。它會追蹤最新獲接受的 commit,即 head。收到提交時,只有當該提交是基於這個 head 建立的,它才會接受。否則,它會傳送一個結構化的「基底過時」(stale-base)回應;落敗的一方需要在新的 head 上重新套用其變更,然後重新提交。這個設計確保並行運作的 AI 代理程式不會在無聲無息間覆寫彼此的成果,同時不會明顯拖慢速度。在我們的生產環境工作流程中,只有不到 2% 的提交會因基底過時而遭拒絕。整體而言,提交延遲的中位數低於 1.7 秒,p99 延遲則低於 8 秒。
Git 服務亦會記錄每項獲接受的變更。每次寫入獲接受時,它都會在寄件匣(outbox)中新增一筆項目;寄件匣是一份記錄,列出儲存庫、新的 commit、作出變更的用戶,以及有所變更的路徑。解析器等下游服務會讀取這份記錄,以找出新的工作。
整合起來,這些元件構成了一個儲存庫管理層,同時省去了 AI 代理程式不需要的部分。拉取請求並無必要,因為不會有人逐一審查每項變更。取而代之的是:Git 服務會在提交時檢查約定,在競爭中落敗的 AI 代理程式會重新套用自己的變更,而 commit 歷史記錄則記下了誰更改了甚麼。確定性的檢查讓每個儲存庫都維持在約定範圍內,而無需依賴人手管理儲存庫的增長。
儲存:確保工作成果持久保存
儲存層獨立於沙箱和 Git 服務副本,持久保存儲存庫資料。儲存庫存放在 AWS S3Files 上;S3Files 透過檔案系統介面提供以 S3 為基礎的儲存,標準 Git 無需修改即可使用。每個儲存庫都是共用檔案系統上的一個裸 Git 儲存庫(bare repository),包含儲存庫的物件和參照,而不是工作目錄。
將儲存與運算分離,讓沙箱可以保持短暫存在。每個 AI 代理程式都有自己的沙箱,許多 AI 代理程式可以處理同一個專案而無需共用一部機器。如果沙箱當機,只有尚未提交的工作會受影響。
我們也可以改為給每個專案一個長期存在、由其所有 AI 代理程式共用的沙箱,讓專案檔案存放在該機器的磁碟上。然而,這樣會將 AI 代理程式的運算資源綁定在該機器的執行位置,而且機器必須按最繁忙時段的需求配置規格。它亦需要連續數月保持正常運作,並將備份和復原納入專案儲存系統的一部分來管理。
下游處理:讓 AI 代理程式能讀取文件
主要的下游元件是一條解析器管線,負責從新增或更新的文件中擷取文字和中繼資料,讓 AI 代理程式能輕鬆讀取專案檔案。解析器工作程序會從變更串流佇列中取用更新,根據 commit 中繼資料找出變更的檔案,並使用內容雜湊值取得原始位元組。接著,它會解析文件,產生擷取出的文字和文件中繼資料。
解析後的輸出存放在儲存庫之外,位於一個以來源文件雜湊值為鍵的儲存區中。這些成品永遠不會提交回儲存庫,因為這樣會無謂地污染歷史記錄,並增加並行寫入的次數。取而代之,解析後的輸出會透過簽出和同步送達沙箱。每個簽出都包含一個保留目錄,供 CLI 用來將成品實體化。解析以非同步方式進行,因此背景解析器工作程序不會阻礙簽出。
AI 代理程式如何使用工作空間
AI 代理程式使用標準檔案系統工具,探索已載入沙箱的儲存庫版本。它們不會遵循固定的「先搜尋、後讀取」流程,而是列出資料夾、使用 grep 搜尋檔案內容、閱讀相關段落,再根據找到的內容決定下一步要查看哪裏。
與 Computer 類似,Search 也透過其標準檔案工具採用相同方法。一個獨立的探索 AI 代理程式會在較有限的預算內搜尋專案,並回傳相關的檔案路徑和佐證摘錄。回答模型隨後會讀取所選檔案並產生答案。重用現有的專案沙箱可縮短設定時間:連接到已預熱的簽出約需 2.9 秒,而冷啟動則約需 8 秒。
有了解析後的文字,PDF 和 Office 檔案等較大型的文件也能以相同工具搜尋。AI 代理程式會先查看清單(manifest),即一份顯示哪些文件已有擷取文字可用的列表,然後將這些文字當作一般檔案搜尋和閱讀。只有在文字不足以應付時,例如需要檢查圖表、版面或嵌入的資料,它才會下載原始文件。
我們以同一語料庫中的 150 條單一文件財務問題,將這個方法與基於索引的語義搜尋進行基準測試比較。探索 AI 代理程式在檢索正確文件方面得分 0.867,在正確回答方面得分 0.627,而語義搜尋則分別約為 0.39 和 0.37;換言之,答案表現約為語義搜尋的 1.7 倍,檢索表現約為 2 倍,延遲亦低約 25%。探索 AI 代理程式主要使用擷取出的文字,甚少下載原始 PDF。
同一套共用基礎架構
Computer 的持久記憶使用相同的檔案系統基礎架構。Perplexity Brain 是 Computer 的知識 wiki,它將記憶儲存在擁有各自歷史記錄和策略的知識儲存庫中。將知識與專案檔案分開存放,意味著背景記憶更新不會與這些檔案的編輯互相競爭。需要兩者的工作階段會同時載入兩個儲存庫。
背景 AI 代理程式會讀取現有知識、整合新資訊,並將更新後的頁面儲存為 commit。其他 AI 代理程式會使用一般檔案工具讀取這些頁面,人們也可以編輯它們。寫入者透過儲存庫分享成果,而不是與每位讀取者直接協調。Commit 歷史記錄記下了誰更改了甚麼,而寄件匣則向下游服務報告獲接受的更新。人與 AI 代理程式可以在彼此的成果上繼續發展,同時保留知識如何演變的記錄。
結論
當人與 AI 代理程式共用一個專案時,工作空間的作用不止於儲存檔案。它提供一個共同的地方,用來整合各方貢獻並追蹤變更。Git 已提供了這方面的大部分基礎。我們再加入協調機制和自動化檢查,讓 AI 代理程式無需由人逐一批准每項更新,便能提交工作成果。最終得出的是一個精簡至只剩核心要素的代碼託管平台,因為跨 AI 代理程式協作與多人參與的軟件開發,本質上是同一個問題。
AI 代理程式在各自獨立的臨時沙箱中工作,同時為持久的儲存庫作出貢獻。儲存庫限制讓增長保持在可控範圍,明確的下載機制讓 AI 代理程式自行選擇要取得的內容,而一般檔案則讓它們能以熟悉的工具探索。背景更新、互動式編輯和排程任務都能在彼此的成果上繼續發展,而無需直接協調。
隨著愈來愈多 AI 代理程式在專案中自主工作,它們共用的工作空間必須保持可靠,並讓人易於理解。目標很簡單:每項變更都應比產生它的 AI 代理程式更持久、能供下一位協作者使用,並清楚記錄變更了甚麼。
引用
@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}
}