為人與 AI 代理程式打造共用工作區

Perplexity 專案如何讓長期工作保持持久、並行且可追溯。

作者Perplexity Engineering

我們最近推出了 專案功能,讓人們與 AI 代理程式在 Perplexity Computer 中攜手處理長期任務。每個專案都建立在一個共用工作區上,其檔案系統會跨工作階段、AI 代理程式與使用者累積脈絡。橫跨數月的多人協作需要具備持久性、並行性與可追溯性:

  • 持久性:工作成果應能超越任何單一 AI 代理程式工作階段或沙箱而持久保存,讓同一位使用者或代理程式日後能接續進行,任何協作者也能在此基礎上繼續發展。
  • 並行性:同一個專案中的多位使用者,各自可以有多個 AI 代理程式平行進行編輯,共同推進共用的狀態,而不是互相覆寫。
  • 可追溯性:使用者與 AI 代理程式都應能查看歷史記錄,以便確認自上次工作階段以來誰變更了什麼,而不必重新閱讀整個專案,並能在需要時復原編輯。

這些挑戰對軟體工程師而言並不陌生。Git 程式碼託管平台(Git forge)早在數十年前便應運而生,以滿足這些需求:它是一種託管服務,在版本控制之上加入協作功能,讓眾多貢獻者能匯聚於單一可信來源。驅動專案功能的檔案系統,正是這樣一個 Git 程式碼託管平台,專為人與 AI 代理程式之間,以及 AI 代理程式彼此之間的協作而打造。

一個專案:互動式 AI 代理程式、排程 AI 代理程式與其他使用者的 AI 代理程式,全都匯聚到同一個儲存庫。

架構

Git 本身就已處理了持久性、並行性與可追溯性。它依據內容來識別每個檔案,因此未變更的檔案只會儲存一次,已儲存的副本也永遠不會過時。每次提交都會一次儲存所有更新過的檔案,因此協作者永遠不會看到做到一半的狀態。當兩個寫入者發生衝突時,落敗的一方可以在新版本上重新套用自己的變更並再試一次。提交鏈會顯示誰變更了什麼,也讓還原先前版本變得容易。AI 代理程式不需要的,是為人類打造的程式碼託管平台(forge)中的其他部分,例如審查畫面、分支管理和通知。

我們的架構在雲端執行整個流程,並支援程式設計以外的各種知識工作。每個 Computer 專案都由一個 Git 儲存庫支撐,而該儲存庫由 5 個元件提供服務:

  • CLI 會在每個沙箱中維護本機簽出副本、同步更新,並送出 AI 代理程式的變更。
  • 控制平面會找出專案儲存庫,並核發用於存取該儲存庫的短期憑證。
  • Git 服務會將儲存庫資料傳送至沙箱、接收沙箱送出的內容,並決定哪一次送出會成為最新的已接受提交。
  • 以 AWS S3 為基礎的儲存空間會持久保存儲存庫資料。
  • 下游處理會從已儲存的文件中擷取文字和其他實用資訊,並在 AI 代理程式載入或重新整理專案時提供使用。

每個 AI 代理程式都有自己獨立的沙箱。在沙箱內,它會使用由小型 CLI 管理的儲存庫本機副本進行工作。CLI 會請控制平面找出儲存庫,接著透過 Git 服務取得與送出變更。AI 代理程式 Proxy 會在沙箱請求到達 Git 服務之前檢查存取權限。Git 服務會在共用檔案系統上讀寫儲存庫,並決定每次送出的內容是否成為最新的已接受提交。該檔案系統由 AWS S3Files 提供,讓以 S3 為基礎的儲存空間能以一般檔案和目錄的形式存取。儲存空間被劃分為數個隔離的儲存區,每個儲存區都有各自的檔案系統與 Git 服務複本。提交被接受後,背景工作程序會從變更的文件中擷取文字和其他實用資訊,將結果與儲存庫歷史記錄分開存放,並在 AI 代理程式載入或重新整理專案時提供使用。

接下來,我們將逐一說明各個元件。

CLI 會聯繫控制平面以找出其儲存庫,接著經由 AI 代理程式 Proxy,透過 Git 服務取得與送出內容。Git 服務會檢查送出的內容,並更新 DynamoDB 中已接受的 head 與寄件匣。儲存區內的複本使用 S3Files 儲存空間,而下游工作程序則會擷取文字,供簽出與同步使用。

CLI:在沙箱中使用本機檔案

AI 代理程式在 SPACE 中執行,這是我們內部自行開發的沙箱平台。每個沙箱都有一個小型 CLI,負責將儲存庫實體化並保持同步。代理程式每完成一個有意義的工作單位,CLI 就會將變更以提交的形式送出。

AI 代理程式通常只會用到一小部分的專案檔案,因此不需要事先將整個儲存庫實體化。基於這點,CLI 採用延遲實體化:透過 Git 大型檔案儲存(LFS)存放的大型檔案與二進位檔案,會以小型指標檔案的形式送達,其中記錄了物件的實際大小,讓代理程式能依據名稱和大小判斷是否值得下載。對於 PDF 等文件,代理程式會先讀取解析後的文字,只有在必要時才下載原始檔。

另一個自然的選項是使用虛擬檔案系統。我們測試過以 FUSE 為基礎的實作,但在大量使用檔案系統的工作負載上,它比本機檔案慢了約 400 倍,因為每個請求都需要一次網路往返。它通常也需要主機提供特權功能,因此每個 AI 代理程式都必須在具特權的沙箱中執行。

由指標大小與解析資訊清單決定:讀取解析後的文字、下載原始檔,或是略過。

控制平面:找出儲存庫並核發存取權限

控制平面負責找出每個儲存庫的儲存位置,並核發存取權限。建立儲存庫時,控制平面會將其指派給一個儲存區(cell),也就是擁有專屬 Git 服務複本的隔離儲存單位。當 AI 代理程式開始處理某個專案時,CLI 會向控制平面詢問儲存庫的儲存位置。控制平面會回傳該位置以及存取 Git 服務所需的臨時憑證。控制平面從不讀取或寫入儲存庫資料;由 Git 服務決定哪些內容可以進入儲存庫。

Git 服務:搬移資料並協調更新

Git 服務負責執行 Git 操作,並在沙箱與儲存空間之間傳輸儲存庫內容與版本歷史記錄。它是 Git 本身服務指令的輕量包裝層。它支援 ref 探索,用於告訴用戶端儲存庫的 head 位於何處;支援 upload-pack,用於複製(clone)與取得(fetch);也支援 receive-pack,用於接收新物件以及推進儲存庫 head 的請求。它也提供 Git LFS API:針對大型檔案與二進位檔案,它會核發短期連結,讓沙箱能直接從 S3 上傳和下載這些檔案。

我們一開始使用現成的程式碼託管平台伺服器,這樣就能一邊打造自有的輕量級程式碼託管平台,一邊平行開發 AI 代理程式與使用者介面的原型;我們自己的平台只專注於所需的 Git 操作。

此服務由一組複本組成,每個複本都是同一伺服器的一個執行中執行個體。每個儲存區(cell)將共用儲存空間與一組複本及其支援服務組合在一起。如此一來,同一儲存區內的複本便能存取相同的共用檔案系統,而不必各自維護每個儲存庫的獨立副本。

這種共用儲存方式讓複本能保持無狀態。儲存區內的任何複本都能為該儲存區的任何儲存庫提供服務,因此替換或新增複本時,不需要在伺服器之間搬移儲存庫資料。針對某個儲存庫的請求通常會導向同一個複本,以發揮其快取的效用,但儲存庫並不依賴該特定執行個體持續可用。

接受步驟會檢查儲存庫的不變條件,確保被接受的提交是有效的儲存庫狀態。我們為每個儲存庫定義明確的契約,讓機械式檢查能防止儲存庫變得過於龐大。PDF 和圖片等大型檔案與二進位檔案會透過 Git LFS 儲存,而不是以原始 Git blob 的形式存放。壓縮(compaction)能在限制儲存庫大小的同時,讓近期的歷史記錄維持可用。成功送出後,CLI 會詢問 Git 服務該儲存庫是否需要壓縮。若保留的提交數量超過門檻,Git 服務只會保留一小組最新的提交。較舊的歷史記錄會由單一的起始快照取代,近期的提交則會重新套用,以更新提交識別碼。

壓縮會保留最新的提交,將較舊的歷史記錄併入單一快照根節點,並以新的識別碼重新套用近期的提交;新的 head 會保有相同的檔案。

一個簡單的同步步驟負責控管並行的寫入者。它會追蹤最新的已接受提交,也就是 head。收到送出的內容時,只有在該次送出是以這個 head 為基礎時才會接受。若非如此,它會傳回結構化的「基底過時」(stale-base)回應;落敗的一方接著必須在新的 head 上重新套用其變更並重新送出。此設計可確保並行的 AI 代理程式不會在不知不覺中互相覆寫,也不會造成明顯的效能下降。在我們的正式環境工作流程中,因過時而遭拒的送出不到 2%。整體而言,送出延遲的中位數低於 1.7 秒,p99 延遲則低於 8 秒。

兩個 AI 代理程式同時送出;其中一個被接受,另一個收到基底過時回應,在新的 head 上重新套用後重新送出。

Git 服務也會記錄每一項已接受的變更。每次接受寫入時,它都會在寄件匣(outbox)中新增一筆項目;寄件匣是一份記錄檔,列出儲存庫、新的提交、做出變更的使用者,以及有所變更的路徑。解析器等下游服務會讀取此記錄檔,以找出新的工作。

這些元件共同構成一個儲存庫管理層,並捨去了 AI 代理程式用不到的部分。拉取請求並非必要,因為沒有人需要逐一審查每項變更。取而代之的是:Git 服務在送出時檢查契約,在競爭中落敗的代理程式會重新套用自己的變更,而提交歷史記錄則記載了誰變更了什麼。確定性的檢查讓每個儲存庫都維持在其契約範圍內,而不必仰賴人工操作員來管理成長。

儲存:讓工作成果持久保存

儲存層會獨立於沙箱與 Git 服務複本之外,持久保存儲存庫資料。儲存庫存放在 AWS S3Files 上,它透過檔案系統介面提供以 S3 為基礎的儲存空間,標準 Git 無需任何修改即可使用。每個儲存庫都是共用檔案系統上的一個裸(bare)Git 儲存庫,其中包含該儲存庫的物件與參照,而非工作用的簽出副本。

將儲存與運算解耦,讓沙箱能維持臨時性質。每個 AI 代理程式都有自己的沙箱,許多代理程式可以處理同一個專案,而不必共用一台機器。若沙箱當機,只有尚未送出的工作會面臨風險。

我們也可以改為給每個專案一個長期存在、由其所有 AI 代理程式共用的沙箱,讓專案的檔案存放在該機器的磁碟上。然而,這會讓代理程式的運算資源受限於該機器的執行位置,而且機器必須依照最繁忙時段的需求來配置規格。它還需要連續數月保持正常運作,並將備份與復原納入專案儲存系統的一部分來管理。

由專案的 AI 代理程式共用的單一長期沙箱,對比各 AI 代理程式專屬的短期沙箱;後者透過無狀態 Git 服務複本存取持久的共用儲存空間。

下游處理:讓 AI 代理程式能讀取文件

主要的下游元件是一條解析器管線,負責從新增或更新的文件中擷取文字與中繼資料,讓 AI 代理程式能輕鬆讀取專案檔案。解析器工作程序會從變更串流佇列中取用更新,根據提交中繼資料推導出變更的檔案,並使用內容雜湊值取得原始位元組。接著,它會解析文件,產生擷取出的文字與文件中繼資料。

解析後的輸出存放在儲存庫之外,位於以來源文件雜湊值為鍵的存放區中。這些成品絕不會提交回儲存庫,因為那樣會不必要地汙染歷史記錄,並增加並行寫入的次數。取而代之的是,解析後的輸出會透過簽出與同步送達沙箱。每個簽出副本都帶有一個保留目錄,供 CLI 用來將成品實體化。解析是以非同步方式進行,因此背景解析器工作程序不會阻擋簽出。

AI 代理程式如何使用工作區

AI 代理程式會使用標準檔案系統工具,探索載入沙箱中的儲存庫版本。它們不遵循固定的「先搜尋再讀取」流程,而是列出資料夾、以 grep 搜尋檔案內容、閱讀相關段落,再根據所得結果決定下一步要查看哪裡。

與 Computer 類似,Search 也透過其標準檔案工具採用相同的方法。另一個獨立的探索型 AI 代理程式會在更有限的預算內搜尋專案,並傳回相關的檔案路徑與佐證摘錄。接著,回答模型會讀取所選檔案並產生答案。重複使用既有的專案沙箱可縮短設定時間:連接到已預熱的簽出副本約需 2.9 秒,而冷啟動則約需 8 秒。

Computer 沙箱、Ask 的探索子代理程式、背景知識寫入者與解析器工作程序,全都在同一個儲存庫和寄件匣中讀取與寫入。

解析後的文字讓 PDF 和 Office 檔案等較大型的文件,也能以相同的工具進行搜尋。AI 代理程式會先查看資訊清單,也就是列出哪些文件已有擷取文字可用的清單,然後將這些文字當作一般檔案來搜尋與閱讀。只有在文字不足以應付需求時,例如需要檢視圖表、版面配置或內嵌資料,它才會下載原始文件。

我們以同一語料庫中的 150 道單一文件金融問題,將此方法與基於索引的語意搜尋進行基準測試。探索型 AI 代理程式在檢索正確文件上得分 0.867,在正確回答上得分 0.627,而語意搜尋分別約為 0.39 和 0.37;換言之,答案表現約為語意搜尋的 1.7 倍,檢索表現約為 2 倍,延遲也降低約 25%。探索型代理程式大多使用擷取出的文字,很少下載原始 PDF。

探索式搜尋與語意檔案搜尋在內部基準測試中的比較。

同一套共用基礎架構

Computer 的持久記憶也採用相同的檔案系統基礎架構。Perplexity Brain 是 Computer 的知識 wiki,會將記憶儲存在知識儲存庫中,這些儲存庫擁有各自的歷史記錄與政策。將知識與專案檔案分開,代表背景記憶更新不會與這些檔案的編輯互相競爭。需要兩者的工作階段會同時載入兩個儲存庫。

背景 AI 代理程式會讀取既有知識、整合新資訊,並將更新後的頁面儲存為提交。其他代理程式會以一般檔案工具讀取這些頁面,人們也可以編輯它們。寫入者透過儲存庫分享成果,而不是直接與每位讀取者協調。提交歷史記錄記載誰變更了什麼,寄件匣則將已接受的更新通報給下游服務。人與 AI 代理程式可以在彼此的成果上持續建構,並留下知識如何演進的紀錄。

結論

當人與 AI 代理程式共用一個專案時,工作區的作用就不只是儲存檔案。它提供一個共同的地方,用來整合各方貢獻並追蹤變更內容。Git 已經提供了大部分的基礎。我們再加上協調機制與自動化檢查,讓代理程式不需要有人逐一核准每次更新,就能送出工作成果。最終得到的是一個精簡到只剩核心要素的程式碼託管平台,因為跨 AI 代理程式協作與多人參與的軟體開發,本質上是同一個問題。

AI 代理程式在各自獨立的臨時沙箱中工作,同時為持久的儲存庫做出貢獻。儲存庫限制讓成長保持在可控範圍內,明確的下載機制讓代理程式自行選擇要取得的內容,而一般檔案則讓它們能以熟悉的工具進行探索。背景更新、互動式編輯和排程任務都能以彼此的成果為基礎,而無需直接協調。

隨著越來越多 AI 代理程式在專案中自主工作,它們的共用工作區必須保持可靠,並且讓人們易於理解。目標很簡單:每項變更都應比產生它的代理程式更持久、能供下一位協作者使用,並清楚記錄變更內容。

引用

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