Sandboxes GA:agent 拥有了自己的电脑
原文:Agents have their own computers with Sandboxes GA / 2026-04-13 Source: https://blog.cloudflare.com/sandbox-ga/
去年六月我们发布 Cloudflare Sandboxes 时,前提很简单:AI agent 需要开发和运行代码,而它们需要在某个安全的地方做。
如果一个 agent 像开发者一样行事,这意味着克隆仓库、用多种语言构建代码、运行开发服务器等等。要有效地做这些,它们通常需要一台完整的电脑(如果不需要,它们可以 伸手够一些更轻量的东西)。
很多开发者用 VM 或现有容器方案拼凑解法,但有一堆难题要解决:
-
突发性 —— 每个会话都需要自己的沙箱,你常常需要快速拉起多个,但又不想为待机的闲置算力付费。
-
快速状态恢复 —— 每个会话都应该快速启动、快速重启,恢复过去的状态。
-
安全 —— agent 需要安全访问服务,但不能被托付凭据。
-
控制 —— 需要简单地以编程方式控制沙箱的生命周期、执行命令、处理文件等等。
-
人机工效 —— 你需要为人类和 agent 都给出一个简单接口来做常见操作。
我们花时间解决了这些问题,这样你就不必。从最初发布以来,我们让 Sandboxes 成为一个更适合规模化运行 agent 的地方。我们和最初的合作伙伴(如在 Figma Make 中用容器跑 agent 的 Figma)一起工作:
“Figma Make 旨在帮助各种背景的构建者和创造者更快地从想法走向生产。要兑现这个目标,我们需要一个能提供可靠、高度可扩展沙箱的基础设施方案,在那里可以运行不可信的 agent 和用户编写的代码。Cloudflare Containers 就是这个方案。”
— Alex Mullans,Figma 的 AI 与开发者平台
我们想把 Sandboxes 带给更多优秀组织,所以今天我们激动地宣布:Sandboxes 和 Cloudflare Containers 现已正式可用(GA)。
下面看看 Sandboxes 最近的几项变化:
-
安全凭据注入 让你在 agent 从不接触凭据的情况下完成认证调用
-
PTY 支持 给你和你的 agent 一个真实的终端
-
持久代码解释器 给你的 agent 一个开箱即用、跨调用保留状态的执行 Python、JavaScript 和 TypeScript 的位置
-
后台进程和实时预览 URL 提供一种简单方式与开发服务器交互、验证进行中的修改
-
文件系统监听 提升 agent 修改时的迭代速度
-
快照 让你快速恢复 agent 的编码会话
-
更高的限额和按 Active CPU 计价 让你以规模部署 agent 队列,而无需为未使用的 CPU 周期付费
Sandboxes 101
在进入最近的变化之前,我们先快速看看基础。
一个 Cloudflare Sandbox 是一个由 Cloudflare Containers 驱动的、持久且隔离的环境。你按名字请求一个 sandbox。如果它在跑,你拿到它。如果它不在,它启动。当它闲置,它自动睡眠并在收到请求时唤醒。用诸如 exec、gitClone、writeFile 以及 更多 方法以编程方式与 sandbox 交互很容易。
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,后续请求可以从世界上任何地方触达同一个 sandbox。
安全凭据注入
agentic 工作负载里最难的问题之一是认证。你常常需要 agent 访问私有服务,但又不能完全信任它们持有原始凭据。
Sandboxes 通过在网络层使用可编程的出口代理注入凭据来解决这个问题。这意味着 sandbox 内的 agent 永远不会接触凭据,你可以按需完全自定义认证逻辑:
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 bindings 的集成——请阅读我们最近关于 Sandbox auth 的博文。
真实的终端,不是模拟
早期 agent 系统常常把 shell 访问建模成请求-响应循环:跑一个命令、等输出、把记录塞回 prompt、重复。它能用,但不是开发者真正使用终端的方式。
人类跑些什么、看着输出流入、打断它、稍后重连、继续。Agent 也能从同样的反馈循环受益。
二月,我们发布了 PTY 支持。一个 sandbox 内的伪终端会话,通过 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" });
这让 agent 和开发者可以用一个完整的 PTY 现场调试这些会话。
每个终端会话有自己的隔离 shell、自己的工作目录、自己的环境。你需要多少就开多少,就像在自己机器上一样。输出在服务端缓冲,所以重连会回放你错过的内容。
一个会记忆的代码解释器
对数据分析、脚本编写和探索性工作流,我们也提供了一个更高层的抽象:一个持久的代码执行上下文。
关键词是“持久“。许多代码解释器实现把每个片段隔离运行,所以状态在调用之间消失。你不能在一步设置变量、下一步读取它。
Sandboxes 让你创建保留状态的“context“。变量和导入跨调用保留,就像 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
启动一个服务器,得到一个 URL,发布它
Agent 在能构建一些东西并立刻给用户看时更有用。Sandboxes 支持后台进程、就绪检查和 预览 URL。这让 agent 可以启动一个开发服务器,并在不离开对话的情况下分享一个实时链接。
// 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(),agent 可以基于运行程序发出的真实信号来安排工作,而不是靠猜。这比常见替代方案——通常是 sleep(2000) 然后祈祷——好得多。
监听文件系统并立即响应
现代开发循环是事件驱动的。保存一个文件,重新构建。改一个 config,重启服务器。改一个测试,重跑套件。
我们三月发布了 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' });
}
}
这是那种悄悄改变 agent 能做什么的原语之一。一个能实时观察文件系统的 agent,可以参与到与人类开发者同样的反馈循环中。
用快照快速唤醒
想象一个(人类)开发者在笔记本上工作。他 git clone 一个仓库,跑 npm install,写代码,推一个 PR,然后在等代码审查时合上笔记本。当要继续工作时,他重新打开笔记本,从离开的地方继续。
如果一个 agent 想在朴素的容器平台上复刻这个工作流,你会撞上一个坎。如何快速从离开的地方继续?你可以让 sandbox 一直跑,但那要为闲置算力付费。你可以从容器镜像全新启动,但要等漫长的 git clone 和 npm install。
我们的答案是快照,将在未来几周陆续发布。
快照保留容器的完整磁盘状态,OS config、安装的依赖、修改过的文件、数据文件等等,然后让你稍后快速恢复。
你可以配置一个 Sandbox,在它进入睡眠时自动快照。
class AgentDevEnvironment extends Sandbox {
sleepAfter = "5m";
persistAcrossSessions = {type: "disk"}; // you can also specify individual directories
}
你也可以以编程方式拍快照并手动恢复。这对检查点工作或分叉会话很有用。例如,如果你想并行跑四个 agent 实例,你可以轻松地从同一状态启动四个 sandbox。
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 的 分层缓存 系统让在 Region: Earth 范围内的恢复都很快。
未来发布中,实时内存状态也将被捕获,让运行中的进程能从离开的地方精确继续。一个终端和一个编辑器将以上次关闭时的精确状态重新打开。
如果你有兴趣在快照上线前恢复会话状态,你今天可以使用 backup and restore 方法。它们也用 R2 持久化和恢复目录,但不如真正的 VM 级快照高性能。不过它们仍然能比朴素地重建会话状态带来可观的速度提升。
启动一个 sandbox、克隆 ‘axios’ 并 npm install 用 30 秒。从备份恢复用 2 秒。
请关注官方快照发布。
更高限额与按 Active CPU 计价
自最初发布以来,我们一直在稳步增加容量。标准价格计划上的用户现在可以并发跑 15,000 个 lite 实例、6,000 个 basic 实例,以及 1,000+ 个更大的并发实例。要跑更多请 联系我们!
我们也调整了价格模型,使其在规模运行时更具成本效益。Sandboxes 现在 只对实际使用的 CPU 周期计费。这意味着你不会为 agent 等 LLM 响应时的闲置 CPU 付费。
这就是一台电脑该有的样子
九个月前,我们发布了一个能跑命令、访问文件系统的 sandbox。那足以验证概念。
我们现在拥有的是另一个层面的东西。今天的 Sandbox 是一个完整的开发环境:可以连接浏览器的终端、带持久状态的代码解释器、带实时预览 URL 的后台进程、实时发出变更事件的文件系统、用于安全凭据注入的出口代理,以及让热启动几乎瞬间完成的快照机制。
当你在它之上构建,会浮现一个令人满意的模式:做真实工程工作的 agent。克隆一个仓库,装它,跑测试,读失败,改代码,再跑测试。让一个人类工程师高效的那种紧密反馈循环——现在 agent 也拥有了。
我们处在 SDK 的 0.8.9 版本。今天就能开始:
npm i @cloudflare/sandbox@latest
– 原文译于 2026-04-30