我们去年 6 月推出 Cloudflare Sandboxes时,初衷很简单:AI 智能体需要开发并运行代码,且必须在安全的环境中进行。
当 AI 智能体承担开发人员角色时,需完成代码仓库克隆、多语言代码构建、开发服务器运行等一系列操作。要高效完成这些操作,AI 智能体通常需要一套完整的计算环境(否则,可选用轻量化方案)。
许多开发人员通过虚拟机(VM)或现有容器方案自行组合解决方案,但仍有诸多技术难题亟待解决。
突发性 —— 由于每个会话都需要自己的沙盒,您通常需要快速启动许多沙盒,但又不想为随时待命的空闲计算成本付费。
快速状态恢复——每个会话都应快速启动并快速重新启动,恢复到过去的状态。
安全性——智能体需安全访问各类服务,但您不能将凭据直接交给其持有。
管控 —— 可通过编程方式便捷地管控沙盒的全生命周期、执行命令、处理文件及其他操作。
人机工程学—— 需为人类与智能体提供一个简洁界面,以执行各类常规操作。
我们已经花时间解决了这些问题,让您无需为此费心。自初次推出以来,我们持续优化 Sandboxes,使其更适合规模化运行智能体。我们已与初期合作伙伴展开合作,例如 Figma,其通过 Figma Make 在容器中运行智能体。
“Figma Make 旨在帮助各类背景的开发者与创作者,更快速地将创意落地并投入生产。为实现这一目标,我们需要一套基础设施解决方案,以提供可靠、高度可扩展的沙盒环境,用于运行由智能体与用户编写的不可信代码。Cloudflare Containers 就是这样一个解决方案。”
- Alex Mullans,AI 与开发人员平台,Figma
我们希望将 Sandboxes 推广至更多优秀企业,因此今天我们很高兴地宣布,Sandboxes 与 Cloudflare Containers 均正式发布。
让我们来看看 Sandboxes 最近的一些变化:
安全凭据注入支持您发起鉴权调用,且智能体全程无需接触凭据信息。
PTY 支持为您和智能体提供真实终端环境
持久性代码解释器为您的智能体提供一个开箱即用的有状态 Python、JavaScript 和 TypeScript 执行环境
后台进程和实时预览 URL 提供了一种与开发服务器交互并验证进行中更改的简单方式
文件系统观察可在智能体进行更改时提高迭代速度
快照让您快速恢复智能体的编码会话
更高资源配额与活动 CPU 计费模式,让您可规模化部署智能体集群,而无需为闲置 CPU 周期付费。
在讨论最近的一些变化之前,让我们快速看一下基本知识。
Cloudflare 沙盒是一个由 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 绑定集成——请阅读我们近期关于Sandbox 认证的博客文章。
早期的智能体系统通常将 Shell 访问建模为请求-响应循环:执行命令、等待输出、将执行记录回填至提示信息中,循环往复。该方案虽可运行,却并非开发人员实际使用终端的方式。
人类用户执行操作、实时查看输出流、中断进程,后续重新连接并继续运行。智能体同样受益于这种反馈循环。
今年 2 月,我们推出了 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 笔记本中一样:
// 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) 并期待有效。
现代开发流程采用事件驱动模式。保存文件,重新执行构建。编辑配置,然后重启服务器。更改测试,重新运行套件。
我们在 3 月份发布了 sandbox.watch()。它返回一个由原生 inotify 支持的 SSE 流,这是 Linux 用于文件系统事件的内核机制。
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 的分层缓存系统可在全球任何地区实现快速恢复。
在未来版本中,实时内存状态也将被捕获,从而允许正在运行的进程从其中断的地方准确恢复。终端和编辑器将重新打开,并恢复到上次关闭时的状态。
若您希望在快照功能正式上线前恢复会话状态,现在可使用备份与恢复方法。该方法同样借助 R2 对目录进行持久化存储与恢复,但性能不及真正的虚拟机级快照。不过相较于简单重新创建会话状态,这些方法仍可带来相当可观的性能提升。
启动沙盒,克隆“axios”并安装 npm 需要 30 秒。从备份恢复只需两秒钟。
敬请关注快照功能的正式发布。
自最初推出以来,我们一直在稳步增加容量。使用标准价格计划的用户现在可运行 15000 个并发的轻量实例类型实例,6000 个基本实例类型实例,以及 1000 多个并发的大型实例。如需运行更多实例,请联系我们。
我们还更改了定价模型,使其在大规模部署时更具成本效益。Sandboxes 现在仅对实际使用的 CPU 周期收费。这意味着,在智能体等待 LLM 响应时,您无需为空闲 CPU 付费。
九个月前,我们推出了可运行命令并访问文件系统的沙盒功能。那已足以验证该技术方案的可行性。
如今我们所拥有的一切本质上已经不同。今天的沙盒是一个完整的开发环境:一个可以连接浏览器的终端,一个具有持久状态的代码解释器,一个具有实时预览 URL 的后台进程,一个实时发出更改事件的文件系统,用于安全凭据注入的出口代理,以及可实现近乎瞬时热启动的快照机制。
基于此进行开发时,您会体验到一种理想的开发模式:能够执行实际工程任务的智能体。克隆一个存储库,安装、运行测试,读取故障,编辑代码,再次运行测试。这种紧密的反馈回路,提升了人类工程师的效率,现在智能体也能获得。
当前 SDK 版本为 0.8.9。您今天即可开始使用。
npm i @cloudflare/sandbox@latest