建構雲端 Agent 基礎設施:差異之處與我們的經驗總結

@intuitiveml
英語1 個月前 · 2026年6月05日
311K
857
154
21
2.1K

TL;DR

CREAO 分享了建構雲端 Agent 基礎設施的關鍵經驗,重點在於將使用者環境與平台程式碼解耦,並在沙盒之外保護憑證安全。

Peter Pang - inline image

現在大多數的 Agent 框架都假設在桌面環境執行。一位使用者、一台機器、一個程序。Agent 在筆電開啟時運行,寫入本機檔案系統,將 API 金鑰放在環境變數中,並在終端機關閉時終止。當出錯時,使用者會重試。當 Agent 需要套件時,pip install 會將其安裝到使用者的 Python 環境中。狀態、機密和生命週期都落在單一可信邊界內。

雲端 Agent 基礎架構卻沒有這些奢侈條件。

Agent 運行於一個每次啟動都是全新狀態的沙盒中,硬體與陌生人共用,由使用者從未見過的呼叫者觸發:排程、HTTP 請求、另一個 Agent。使用者通常正在睡覺。沙盒內的程式碼可能帶有惡意。檔案系統必須能在部署中存活。憑證不能存放在 Agent 所在的位置。桌面環境免費提供的每一項保證——持久性、身份識別、網路信任、重試——都必須以明確的系統重新建構。

過去幾個月我們在 CREAO 加強了這一層。從中學到了兩個教訓。如果你曾經部署過桌面 Agent,並好奇當它搬到雲端時會發生什麼改變,這就是答案。

教訓一:將變化慢的事物與變化快的事物分離

Peter Pang - inline image

在桌面上,使用者的環境與 Agent 的執行環境是同一回事,由同一個人以同樣的節奏更新。在雲端,它們不是。

一個 Agent 應用程式會在平台端累積狀態。一位股票分析師安裝 matplotlib、下載市場數據、編寫圖表腳本。這個環境就是 Agent 的肌肉記憶。我們在使用者滿意該環境的那一刻將其凍結成沙盒快照,並保持該快照凍結,直到使用者再次編輯環境。每次執行都從同一個映像檔啟動。相同的套件、相同的檔案、相同的版本。週一的執行表現得像週五,因為底層沒有任何變動。

這是桌面框架無法免費提供的特性。六個月前的 pip install 在今日解析到不同的版本。雲端快照則永遠解析到相同的位元組。可重現性是平台欠使用者的承諾,而凍結的快照是兌現它的最便宜方式。

然後耦合問題出現了。

凍結使用者環境的同一個映像檔也包含 Runner 程式碼——我們開發的一個小型控制庫,負責在每次執行中管理 Agent。使用者希望他們的環境保持不變。我們希望我們的 Runner 一天能部署多次。一個構件,兩個相反的需求。

我們最初的修正很直接。啟動時,檢查快照內的 Runner 是否與我們剛部署的版本相符。如果不符合,就丟棄該快照並從乾淨模板啟動。它有效,也沒有人抱怨。影響只發生在部署後的第一次執行。

無人值守的執行摧毀了那個保護傘。週一早上 9 點的 Cron 工作不該因為我們在 8:55 部署而失去其環境。我們一直在悄悄違反的合約——「你的環境在你改變它之前保持凍結」——被打破了。

這個修正花了我們比應有還長的時間才看清楚。使用者的環境與 Runner 程式碼以完全不同的速率變化。使用者在他們選擇的時候編輯 Agent。我們一天部署平台多次。將它們視為一個構件,迫使每次部署都要做出選擇:保留過時的 Runner 程式碼,或摧毀使用者明確要求我們保留的凍結環境。

我們最終採用的模型借鑒了作業系統處理更新的方式。核心改變。你的家目錄不變。你不會為了安裝安全修補程式而清除整個磁碟。

我們劃出了同樣的邊界。沙盒從使用者凍結的快照啟動,保持不變。然後我們只熱交換 Runner。順序如下:

  1. 將新的 Runner 暫存在沙盒內的臨時目錄中。
  2. 使用 node --check 驗證它,以便在觸碰任何正式內容之前發現任何語法錯誤。
  3. 原子性地交換:解鎖舊 Runner 上的不可變標誌,複製新的覆蓋過去,用 chattr +i 重新鎖定,然後隱藏 chattr 本身,使沙盒程式碼無法逆向解鎖。
  4. 清除 V8 的編譯快取(/home/user/.cache/v8-compile-cache/*),以便新檔案實際載入而非執行過時的位元組碼。
  5. 如果任何步驟失敗,殺死沙盒並用新的沙盒重試。絕不讓半升級的狀態執行 Agent。

整個交換過程大約花費 300 毫秒。我們只在 Runner 程式碼被交換後才在成功執行後重新快照,將更新後的程式碼烘焙到使用者的映像檔中,使下一次執行跳過整個交換。平台部署永遠不會丟棄使用者的狀態;它們將新的 Runner 摺疊進去。使用者的套件、檔案和自定義項目不變地延續。

如果你從這個教訓中只學到一件事,那就是診斷性問題。對於你在雲端平台中持久化的任何事物,問:誰控制這個構件的變化節奏?如果使用者和平台都擁有它,你最終會為耦合付出代價。沿著擁有權邊界分割構件,讓每一方以自己的時鐘更新。

教訓二:將機密保留在執行邊界之外

Peter Pang - inline image

這個教訓將雲端 Agent 基礎架構與其他一切區分開來。

桌面 Agent 以使用者的身份執行。它使用使用者的金鑰,在使用者的機器上,針對使用者的網路。雲端 Agent 以「無人」的身份執行,在共享硬體上,針對開放的網際網路,執行由 LLM 撰寫的程式碼,而該 LLM 的提示可能帶有惡意。安全模型必須假設沙盒內的程式碼已經被入侵,而不是希望它不會。

我們堅持的規則很簡單。任何長期有效的憑證永遠不會存在沙盒內部。

當 Agent 需要呼叫經過身份驗證的服務——Slack、GitHub、使用者自己的 API——它不會持有 Token。它向一個在沙盒外部運行的 API 橋接器發送本機 HTTP 請求。橋接器在主機端附加 OAuth Token 並轉發呼叫。回應返回時,Token 從未進入沙盒的記憶體或環境。

有趣的部分是橋接器如何知道沙盒有權提出請求。兩個檢查,刻意分層。

首先,IP 允許清單。橋接器只接受來自我們沙盒主機所在的內部網路範圍的連線。來自其他任何地方——開發者筆電、洩漏的 URL、公開網際網路——的呼叫在網路層被丟棄,在執行任何應用程式程式碼之前。這將橋接器限制在一個實體基礎架構上,使其對外部任何人無用。

其次,每次執行鑄造一個短期有效的 JWT。當沙盒啟動時,平台簽署一個 Token,其範圍限定於該特定執行:哪個使用者、哪個 App、哪個工作階段,到期時間涵蓋執行視窗而沒有更多。沙盒在每次橋接器呼叫時出示該 Token。橋接器驗證簽名、檢查到期時間,然後才解析使用者儲存的憑證並在主機端附加。如果沙盒被劫持,攻擊者繼承的 Token 會隨著執行終止而失效,並且只授權限定於該工作階段的呼叫。沒有主憑證可竊取。

同一個橋接器也將計費扣款、日誌和指標傳送出去,因此它是唯一一個在沙盒邊界雙向穿越的介面。沙盒內的一切其他內容預設都被視為已受損。

如果提示注入讓 Agent 明天將 process.env 傾印到某個 Webhook,攻擊者只會得到一個短期 JWT,該 JWT 只能從我們的網路內部使用,並隨著執行終止而失效。這個屬性讓我們能夠在共享基礎架構上執行不受信任的使用者程式碼,而不必擔心。

底層的模式

可靠、安全的雲端 Agent 基礎架構並非一個新穎的系統。它是幾個毫無例外地維持的屬性:

  • 狀態存在沙盒中,凍結直到使用者改變它。
  • 程式碼可熱交換,獨立於狀態。
  • 憑證存在主機端,絕不在 Agent 內部。
  • 一個統一的執行管線服務所有的呼叫者,無論觸發者是真人、排程器還是另一個軟體。

最後一個屬性是整個設計的關鍵。一個 executeAgent 函式處理 UI 點擊、排程執行和 API 呼叫。計費系統、扣款日誌、可觀測性信號——全部相同,無論是人類點擊「執行」、Cron 觸發還是腳本呼叫 API。新增一個觸發面只是路由變更,而非架構變更。Agent 本身不知道也不關心誰觸發了它。

這就是桌面框架無法提供,而讓雲端版本值得建構的原因。筆電上的 Agent 受限於筆電。雲端中的 Agent 是一個你的其餘技術棧可以呼叫的函式。使用者撰寫一次。平台讓它在部署中存活、安全地在共享硬體上執行,並接受使用者從未預料到的呼叫者。

Agent 是一個具有自然語言介面的函式。其實現屬於使用者。其觸發面、執行時間、安全邊界屬於平台。紀律在於建構各層,使每一層以自己的時鐘演化,並花時間在他人發現之前找出系統之間的裂縫。

這就是讓下一個表面能夠廉價且安全地出貨的原因。

一鍵儲存

使用 YouMind AI 深度閱讀爆款文章

保存原文、追問細節、總結觀點,並在一個 AI 工作空間裡把爆款文章沉澱成可複用筆記。

了解 YouMind
寫給創作者

把你的 Markdown 變成乾淨的 𝕏 文章

圖片上傳、表格、程式碼區塊,往 𝕏 上手動重排太痛苦。YouMind 把整篇 Markdown 一鍵轉成乾淨、可直接發佈的 𝕏 文章草稿。

試試 Markdown 轉 𝕏

更多可拆解樣本

近期爆款文章

探索更多爆款文章