當我們在去年六月推出 Cloudflare Sandboxes 時,最初的構想很簡單:AI 智慧體需要開發與執行程式碼,而且必須在安全的環境中進行。
如果智慧體要像開發人員一樣行事,那就會涉及複製存放庫、以多種語言建置程式碼、執行開發伺服器等。要有效完成這些任務,智慧體通常需要一台完整的電腦(如果沒有,也可以選擇輕量級的方案)。
許多開發人員正在利用 VM 或現有的容器解決方案來拼湊出可行的架構,但仍有許多棘手的問題需要解決:
突發性 – 每個工作階段都需要自己的沙箱,因此經常需要快速啟動大量的沙箱,但又不希望為了待命的閒置運算資源付費。
快速狀態還原 – 每個工作階段必須能快速啟動、快速重啟,並恢復先前的狀態。
安全性:智慧體需要安全地存取服務,但不能將認證交給它們。
控制能力 – 必須能夠以程式化方式簡單地控制沙箱的生命週期、執行指令、處理檔案等。
人體工學 - 需要提供簡單的介面,讓人類和智慧體都能輕鬆進行常見操作。
我們已投入大量時間解決這些問題,讓您無需為此操心。自最初發布以來,我們不斷最佳化 Sandboxes,使其成為大規模執行智慧體的理想平台。我們與 Figma 等早期合作夥伴攜手合作,他們使用 Figma Make 在容器中執行智慧體:
「Figma Make 旨在幫助各種背景的建立者和創造者更快地將想法轉化為產品。為了實現這一目標,我們需要一套基礎架構解決方案,能夠提供可靠、高度可擴展的沙箱,以便在其中執行智慧體和使用者編寫的不受信任程式碼。Cloudflare Containers 正是這樣的解決方案。」
——Alex Mullans,Figma AI 和開發人員平台負責人
我們希望將 Sandboxes 帶給更多優秀的組織,因此,今天我們很高興地宣布,Sandboxes 和 Cloudflare Containers 均已正式上市。
讓我們來看看 Sandboxes 的一些最新變更:
安全認證插入讓智慧體能在無需存取認證的情況下進行需要身分驗證的呼叫
PTY 支援為您和智慧體提供真實的終端
持久性程式碼解譯器讓您的智慧體能開箱即用地執行具狀態的 Python、JavaScript 和 TypeScript
背景處理序與即時預覽 URL 提供簡單的方式與開發伺服器互動,並驗證進行中的變更
檔案系統監視可提升智慧體修改程式碼時的反覆運算速度
快照可讓您快速復原智慧體的編碼工作階段
更高的限制與活動 CPU 計價模式讓您能大規模部署一整批智慧體,且不需為未使用的 CPU 週期付費
在深入探討近期的一些變更之前,讓我們先快速瞭解一下基本概念。
Cloudflare Sandbox 是一個由 Cloudflare Containers 提供支援的持久性、隔離環境。您可以透過名稱請求一個沙箱。如果它正在執行,您就會取得它;如果沒有,它就會啟動。當它處於閒置狀態時,會自動休眠,並在收到請求時喚醒。透過 exec、gitClone、writeFile 以及其他方法,您可以輕鬆地以程式化方式與沙箱互動。
import { getSandbox } from "@cloudflare/sandbox";
export { Sandbox } from "@cloudflare/sandbox";
export default {
async fetch(request: Request, env: Env) {
// Ask for a sandbox by name. It starts on demand.
const sandbox = getSandbox(env.Sandbox, "agent-session-47");
// Clone a repository into it.
await sandbox.gitCheckout("https://github.com/org/repo", {
targetDir: "/workspace",
depth: 1,
});
// Run the test suite. Stream output back in real time.
return sandbox.exec("npm", ["test"], { stream: true });
},
};
只要您提供相同的 ID,後續的請求無論從世界哪個角落發出,都能連接到這個相同的沙箱。
自主式工作負載中最棘手的問題之一就是驗證。您經常需要讓智慧體存取私人服務,但又不能完全信任它們持有原始認證。
Sandboxes 透過在網路層使用可程式設計的輸出代理插入認證來解決這個問題。這意味著沙箱內的智慧體永遠無法存取認證,而且您可以根據需求完全自訂驗證邏輯:
class OpenCodeInABox extends Sandbox {
static outboundByHost = {
"my-internal-vcs.dev": (request, env, ctx) => {
const headersWithAuth = new Headers(request.headers);
headersWithAuth.set("x-auth-token", env.SECRET);
return fetch(request, { headers: headersWithAuth });
}
}
}
若想深入瞭解其運作原理,包括身分感知認證插入、動態修改規則以及與 Workers 綁定整合,請閱讀我們近期關於沙箱驗證的部落格文章。
早期的智慧體系統通常將 Shell 存取建模為請求-回應迴圈:執行指令、等待輸出、把輸出文字塞回提示詞,然後重複。這雖然可行,但這並不是開發人員實際使用終端機的方式。
人類會執行某個指令,觀察輸出串流、中斷它、稍後重新連接,然後繼續操作。智慧體也能從這種回饋迴圈中受益。
今年二月,我們推出了 PTY 支援。這是一個在沙箱內的偽終端機工作階段,透過 WebSocket 代理,並與 xterm.js 相容。
只需呼叫 sandbox.terminal 即可為後端提供服務:
// Worker: upgrade a WebSocket connection into a live terminal session
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
if (url.pathname === "/terminal") {
const sandbox = getSandbox(env.Sandbox, "my-session");
return sandbox.terminal(request, { cols: 80, rows: 24 });
}
return new Response("Not found", { status: 404 });
},
};
並使用 xterm addon 從用戶端呼叫它:
// Browser: connect xterm.js to the sandbox shell
import { Terminal } from "xterm";
import { SandboxAddon } from "@cloudflare/sandbox/xterm";
const term = new Terminal();
const addon = new SandboxAddon({
getWebSocketUrl: ({ origin }) => `${origin}/terminal`,
});
term.loadAddon(addon);
term.open(document.getElementById("terminal-container")!);
addon.connect({ sandboxId: "my-session" });
這讓智慧體和開發人員能使用完整的 PTY 即時偵錯這些工作階段。
每個終端機工作階段都有自己隔離的 Shell、自己的工作目錄和環境。您可以像在自己的電腦上一樣,視需要開啟多個終端機。輸出會在伺服器端緩衝,因此重新連接時會重播您錯過的內容。
針對資料分析、指令碼編寫和探索性工作流程,我們也提供了更高層級的抽象:持久性程式碼執行環境。
關鍵字是「持久性」。許多程式碼解譯器的實作是在隔離區中執行每個程式碼片段,導致狀態在呼叫之間會消失。您無法在一個步驟中設定變數,然後在下一個步驟中讀取它。
Sandboxes 允許您建立「上下文」來持久保存狀態。變數和匯入項目會像在 Jupyter Notebook 中一樣,在呼叫之間持續存在:
// Create a Python context. State persists for its lifetime.
const ctx = await sandbox.createCodeContext({ language: "python" });
// First execution: load data
await sandbox.runCode(`
import pandas as pd
df = pd.read_csv('/workspace/sales.csv')
df['margin'] = (df['revenue'] - df['cost']) / df['revenue']
`, { context: ctx });
// Second execution: df is still there
const result = await sandbox.runCode(`
df.groupby('region')['margin'].mean().sort_values(ascending=False)
`, { context: ctx, onStdout: (line) => console.log(line.text) });
// result contains matplotlib charts, structured json output, and Pandas tables in HTML
當智慧體能夠建置產品並立即展示給使用者時,它們會更有用。Sandboxes 支援背景處理序、就緒性檢查和預覽 URL。這讓智慧體無需離開對話視窗,就能啟動開發伺服器並分享即時連結。
// Start a dev server as a background process
const server = await sandbox.startProcess("npm run dev", {
cwd: "/workspace",
});
// Wait until the server is actually ready — don't just sleep and hope
await server.waitForLog(/Local:.*localhost:(\d+)/);
// Expose the running service with a public URL
const { url } = await sandbox.exposePort(3000);
// url is a live public URL the agent can share with the user
console.log(`Preview: ${url}`);
透過 waitForPort() 和 waitForLog(),智慧體可以根據執行程式發出的真實訊號來安排工作順序,而不是靠猜測。這比常見的替代方案(通常是某種 sleep(2000),然後祈禱它成功)要好得多。
現代的開發循環是事件驅動的。儲存檔案、重新執行建置;編輯設定、重啟伺服器;變更測試、重新執行測試套件。
我們在三月份推出了 sandbox.watch()。它回傳一個由原生 inotify(Linux 用於檔案系統事件的內核機制)支援的 SSE 串流。
import { parseSSEStream, type FileWatchSSEEvent } from '@cloudflare/sandbox';
const stream = await sandbox.watch('/workspace/src', {
recursive: true,
include: ['*.ts', '*.tsx']
});
for await (const event of parseSSEStream<FileWatchSSEEvent>(stream)) {
if (event.type === 'modify' && event.path.endsWith('.ts')) {
await sandbox.exec('npx tsc --noEmit', { cwd: '/workspace' });
}
}
這是一種默默改變智慧體能力的基礎功能。能夠即時監控檔案系統的智慧體可以像人類開發人員一樣參與相同的回饋循環。
想像一位(人類)開發人員正在筆記型電腦上工作。他們 git clone 一個存放庫,執行 npm install,撰寫程式碼,推送 PR,然後在等待程式碼審查時合上筆記型電腦。當需要恢復工作時,他們只需重新開啟筆記型電腦,從上次離開的地方繼續即可。
如果智慧體想在普通的容器平台上複製這個工作流程,您會遇到阻礙。如何快速從上次離開的地方恢復?您可以讓沙箱持續執行,但這樣您就要為閒置的運算資源付費。您可以從容器映像重新開始,但這樣您必須等待漫長的 git clone 和 npm install。
我們的解決方案是快照,該功能將在未來幾週內推出。
快照會保留容器的完整磁碟狀態、作業系統組態、已安裝的依賴項目、已修改的檔案、資料檔案等等,並讓您稍後快速還原它。
您可以設定沙箱在進入休眠時自動建立快照。
class AgentDevEnvironment extends Sandbox {
sleepAfter = "5m";
persistAcrossSessions = {type: "disk"}; // you can also specify individual directories
}
您也可以透過程式設計方式建立快照並手動還原。這對於檢查點工作或分叉工作階段很有用。例如,如果您想平行執行一個智慧體的四個執行個體,您可以輕鬆地從相同狀態啟動四個沙箱。
class AgentDevEnvironment extends Sandbox {}
async forkDevEnvironment(baseId, numberOfForks) {
const baseInstance = await getSandbox(baseId);
const snapshotId = await baseInstance.snapshot();
const forks = Array.from({ length: numberOfForks }, async (_, i) => {
const newInstance = await getSandbox(`${baseId}-fork-${i}`);
return newInstance.start({ snapshot: snapshotId });
});
await Promise.all(forks);
}
快照會儲存在您帳戶內的 R2 中,為您提供持久性和位置獨立性。R2 的 Tiered Caching 系統允許在全球快速還原。
在未來的版本中,我們也會擷取即時記憶體狀態,允許執行中的處理序從上次離開的地方精確恢復。終端機和編輯器將會以關閉時的確切狀態重新開啟。
如果您想在快照正式上線前還原工作階段狀態,您現在就可以使用備份和還原方法。這些方法同樣使用 R2 來持久化和還原目錄,雖然效能不如真正的 VM 層級快照,但與簡單地重新建立工作階段狀態相比,它們仍然可以顯著提高速度。
啟動沙箱、複製「axios」並執行 npm install 需要 30 秒。從備份還原只需 2 秒。
請持續關注快照功能的正式發布。
自首次推出以來,我們一直在穩步增加容量。現在可以執行 15,000 個並行的輕量型執行個體、6000 個基本型執行個體,以及超過 1000 個並行的大型執行個體。如果需要執行更多,請聯繫我們!
我們也改變了定價模式,使其在大規模執行時更具成本效益。Sandboxes 現在僅對積極使用的 CPU 週期收費。這意味著當您的智慧體正在等待 LLM 回應時,您無需為閒置的 CPU 付費。
九個月前,我們推出的沙箱只能執行指令和存取檔案系統。那時足以證明概念。
我們現在擁有的則是質的不同。今天的沙箱是一個完整的開發環境:一個可以連接瀏覽器的終端機、一個具有持久狀態的程式碼解譯器、帶有即時預覽 URL 的背景處理序、一個能即時發出變更事件的檔案系統、用於安全認證插入的輸出代理,以及一個幾乎可以瞬間完成熱啟動的快照機制。
當您在此基礎上建構時,一個令人滿意的模式隨之浮現:智慧體可以執行真正的工程工作。複製存放庫、安裝它、執行測試、閱讀失敗報告、編輯程式碼、再次執行測試。這種讓人類工程師高效工作的緊密回饋迴圈,現在智慧體也擁有了。
SDK 版本已更新至 0.8.9。您可以立即開始使用:
npm i @cloudflare/sandbox@latest