Cloudflare 发布 AI 智能体沙盒,启动快 100 倍

去年九月,我们推出了代码模式(Code Mode),主张智能体不应通过工具调用(Tool Use)来执行任务,而是编写调用 API 的代码。我们曾演示过,将 MCP 服务器转换为 TypeScript API 就能将 token 使用量减少 81%。我们还展示了代码模式可以在 MCP 服务器后端运行,从而创建出仅用两个工具、不到 1000 个 token 就能暴露整个 Cloudflare API 的 Cloudflare MCP 服务器。
但如果一个智能体(或 MCP 服务器)要执行 AI 实时生成的代码来完成任务,这些代码就需要在某个地方运行,而这个地方必须是安全的。你不能直接在应用中 eval() AI 生成的代码:恶意用户可以轻易地提示 AI 注入漏洞。
你需要一个沙盒:一个与你的应用及外部世界隔离的代码执行环境,只允许访问代码所需的特定能力。
沙盒化是 AI 行业的热门话题。对于这项任务,大多数人会选用容器。使用基于 Linux 的容器,你可以启动任何你想要的代码执行环境。Cloudflare 甚至为此提供了我们的容器运行时和沙盒 SDK。
但容器启动成本高且速度慢,需要数百毫秒才能启动,并占用数百兆内存。你可能需要保持它们的热状态以避免延迟,并且可能倾向于复用现有容器来处理多个任务,这会损害安全性。
如果我们想要支持消费级规模的智能体,让每个终端用户都拥有一个(或多个!)智能体,并且每个智能体都编写代码,那么容器是不够的。我们需要更轻量的方案。
我们有了。
Dynamic Worker Loader:一个轻量级沙盒
在我们九月的代码模式文章中,悄悄宣布了一个新的实验性功能:Dynamic Worker Loader API。这个 API 允许一个 Cloudflare Worker 在运行时动态实例化一个新的 Worker,在其自己的沙盒中,使用运行时指定的代码。
Dynamic Worker Loader 现已进入公开测试版,对所有付费 Workers 用户开放。
阅读文档了解完整细节,但基本用法如下:
// 让你的 LLM 生成类似这样的代码。
let agentCode: string = `
export default {
async myAgent(param, env, ctx) {
// ...
}
}
`;
// 获取代表智能体应能访问的 API 的 RPC 存根。(这可以是任何你定义的 Workers RPC API。)
let chatRoomRpcStub = ...;
// 使用 worker loader 绑定加载一个 Worker 来运行代码。
let worker = env.LOADER.load({
// 指定代码。
compatibilityDate: "2026-03-01",
mainModule: "agent.js",
modules: { "agent.js": agentCode },
// 给予智能体访问聊天室 API 的权限。
env: { CHAT_ROOM: chatRoomRpcStub },
// 阻止互联网访问。(你也可以拦截它。)
globalOutbound: null,
});
// 调用智能体代码导出的 RPC 方法。
await worker.getEntrypoint().myAgent(param);
就这么简单。
快 100 倍
Dynamic Workers 使用了与整个 Cloudflare Workers 平台自八年前推出以来所基于的相同底层沙盒机制:隔离(Isolates)。一个隔离是 V8 JavaScript 执行引擎的一个实例,与 Google Chrome 使用的引擎相同。它们是 Workers 的工作原理。
一个隔离只需几毫秒就能启动,并占用几兆内存。这比典型容器快约 100 倍,内存效率高 10 到 100 倍。
这意味着,如果你想为每个用户请求按需启动一个新的隔离来运行一段代码,然后丢弃它,你可以做到。
无限制的扩展能力
许多基于容器的沙盒提供商会对全局并发沙盒数量和沙盒创建速率施加限制。Dynamic Worker Loader 没有这样的限制。它不需要,因为它只是对我们平台一直依赖的相同技术的 API 访问,该技术始终允许 Workers 无缝扩展到每秒数百万次请求。
想要处理每秒一百万次请求,其中每个请求都加载一个独立的 Dynamic Worker 沙盒,并且全部并发运行?没问题!
零延迟
一次性的 Dynamic Workers 通常在与创建它们的 Worker 相同的机器——甚至是同一个线程上运行。无需在全球范围内通信来寻找一个热沙盒。隔离是如此轻量,我们可以在请求到达的任何地方运行它们。Dynamic Workers 在 Cloudflare 全球数百个地点都得到支持。
全是 JavaScript
与容器相比,唯一的限制是你的智能体需要编写 JavaScript。
从技术上讲,Workers(包括动态的)可以使用 Python 和 WebAssembly,但对于小段代码——比如智能体按需编写的代码——JavaScript 的加载和运行速度会快得多。
我们人类往往对编程语言有强烈的偏好,虽然很多人喜欢 JavaScript,但其他人可能更喜欢 Python、Rust 或无数其他语言。
但我们这里讨论的不是人类。我们讨论的是 AI。AI 会编写你想要的任何语言。LLM 精通所有主要语言。它们在 JavaScript 上的训练数据是巨大的。
JavaScript 因其在 Web 上的特性,天生就被设计为可沙盒化。它是适合这项工作的语言。
用 TypeScript 定义工具
如果我们希望智能体能够做任何有用的事情,它需要与外部 API 通信。我们如何告诉它它可以访问哪些 API?
MCP 为扁平的工具调用定义了模式,但没有定义编程 API。OpenAPI 提供了一种表达 REST API 的方式,但它很冗长,无论是模式本身还是调用它所需编写的代码。
对于暴露给 JavaScript 的 API,有一个单一且明显的答案:TypeScript。
智能体懂 TypeScript。TypeScript 设计得简洁。用很少的 token,你就能让你的智能体精确理解你的 API。
// 与聊天室交互的接口。
interface ChatRoom {
// 获取聊天日志的最后 `limit` 条消息。
getHistory(limit: number): Promise<Message[]>;
// 订阅新消息。处理返回的对象以取消订阅。
subscribe(callback: (msg: Message) => void): Promise<Disposable>;
// 向聊天室发布消息。
post(text: string): Promise<void>;
}
type Message = {
author: string;
time: Date;
text: string;
}
与等效的 OpenAPI 规范(长得需要滚动才能看完)相比:
openapi: 3.1.0
info:
title: ChatRoom API
description: >
Interface to interact with a chat room.
version: 1.0.0
paths:
/messages:
get:
operationId: getHistory
summary: Get recent chat history
description: Returns the last \`limit\` messages from the chat log, newest first.
parameters:
- name: limit
in: query
required: true
schema:
type: integer
minimum: 1
responses:
"200":
description: A list of messages.
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Message"
post:
operationId: postMessage
summary: Post a message to the chat room
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- text
properties:
text:
type: string
responses:
"204":
description: Message posted successfully.
/messages/stream:
get:
operationId: subscribeMessages
summary: Subscribe to new messages via SSE
description: >
Opens a Server-Sent Events stream. Each event carries a JSON-encoded
Message object. The client unsubscribes by closing the connection.
responses:
"200":
description: An SSE stream of new messages.
content:
text/event-stream:
schema:
description: >
Each SSE \`data\` field contains a JSON-encoded Message object.
$ref: "#/components/schemas/Message"
components:
schemas:
Message:
type: object
required:
- author
- time
- text
properties:
author:
type: string
time:
type: string
format: date-time
text:
type: string
我们认为 TypeScript API 更好。它使用更少的 token,并且更容易理解(无论对智能体还是人类)。
Dynamic Worker Loader 使得在你自己的 Worker 中实现这样的 TypeScript API 变得容易,然后将其作为方法参数或 env 对象传递给 Dynamic Worker。Workers 运行时会自动在沙盒和执行框架(Harness)代码之间建立一个 Cap'n Web RPC 桥接,这样智能体就可以跨安全边界调用你的 API,而无需意识到它使用的不是本地库。
这意味着你的智能体可以编写这样的代码:
// 思考:用户要求我总结 Alice 最近的聊天消息。
// 我将在代码中过滤最近的消息历史,这样我只需要阅读相关消息。
let history = await env.CHAT_ROOM.getHistory(1000);
return history.filter(msg => msg.author == "alice");
HTTP 过滤和凭证注入
如果你更愿意给你的智能体 HTTP API,这完全支持。使用 worker loader API 的 globalOutbound 选项,你可以注册一个回调函数,在每个 HTTP 请求上被调用,在其中你可以检查请求、重写它、注入认证密钥、直接响应它、阻止它,或任何你可能想做的事情。
例如,你可以用它来实现凭证注入:当智能体向需要授权的服务发出 HTTP 请求时,你在请求发出时添加凭证。这样,智能体本身永远不会知道秘密凭证,因此无法泄露它们。
当智能体与其训练集中已知的 API 通信,或者当你希望智能体使用基于 REST API 构建的库时(该库可以在智能体的沙盒内运行),使用纯 HTTP 接口可能是可取的。
尽管如此,在没有兼容性要求的情况下,TypeScript RPC 接口比 HTTP 更好:
- 如上所示,描述 TypeScript 接口所需的 token 远少于 HTTP 接口。
- 智能体编写代码调用 TypeScript 接口所需的 token 远少于等效的 HTTP 调用。
- 使用 TypeScript 接口时,由于你无论如何都在定义自己的包装接口,因此更容易缩小接口,仅暴露你希望提供给智能体的确切能力,这既是为了简化也是为了安全。使用 HTTP 时,你更可能是在实现对某个现有 API 的请求过滤。这很困难,因为你的代理必须完全解释每个 API 调用的含义,才能正确决定是否允许它,而 HTTP 请求很复杂,有许多可能都有意义的头部和其他参数。最终,更容易的做法是只编写一个仅实现你想要允许的功能的 TypeScript 包装器。
久经考验的安全性
强化基于隔离的沙盒很棘手,因为它比硬件虚拟机具有更复杂的攻击面。尽管所有沙盒机制都有漏洞,但 V8 中的安全漏洞比典型虚拟机管理程序中的更常见。当使用隔离来沙盒化可能恶意的代码时,拥有额外的深度防御层很重要。例如,Google Chrome 为此实现了严格的进程隔离,但这并不是唯一的解决方案。
我们拥有近十年的保护基于隔离的平台的经验。我们的系统会在几小时内自动将 V8 安全补丁部署到生产环境——比 Chrome 本身更快。我们的安全架构具有自定义的第二层沙盒,可根据风险评估动态隔离租户。我们扩展了 V8 沙盒本身,以利用 MPK 等硬件功能。我们与(并聘请了)领先的研究人员合作,开发了针对 Spectre 的新颖防御措施。我们还有系统可以扫描代码中的恶意模式,并自动阻止它们或应用额外的沙盒层。等等。
当你在 Cloudflare 上使用 Dynamic Workers 时,你会自动获得所有这些。
辅助工具库
我们开发了几个工具库,用 Dynamic Workers 时可能会派上用场。
Code Mode
@cloudflare/codemode 简化了在 Dynamic Workers 中运行 AI 模型生成代码的过程。它的核心是 DynamicWorkerExecutor(),它会构建一个专门定制的沙箱,对代码进行标准化处理以应对常见格式错误,并提供对 globalOutbound fetcher 的直接访问,用于控制沙箱内的 fetch() 行为——设置为 null 可实现完全隔离,或者传入一个 Fetcher 绑定来路由、拦截或丰富沙箱发出的出站请求。
const executor = new DynamicWorkerExecutor({
loader: env.LOADER,
globalOutbound: null, // 完全隔离
});
const codemode = createCodeTool({
tools: myTools,
executor,
});
return generateText({
model,
messages,
tools: { codemode },
});
Code Mode SDK 还提供了两个服务端实用函数。codeMcpServer({ server, executor }) 包装一个现有的 MCP Server,用一个 code() 工具替换其工具接口。openApiMcpServer({ spec, executor, request }) 更进一步:给定一个 OpenAPI 规范和一个执行器(executor),它会构建一个完整的 MCP Server,包含 Cloudflare MCP Server 使用的 search() 和 execute() 工具,更适合大型 API。
在这两种情况下,模型生成的代码都在 Dynamic Workers 内运行,对外部服务的调用通过传递给执行器的 RPC 绑定进行。
打包工具
Dynamic Workers 需要预打包的模块。@cloudflare/worker-bundler 帮你搞定:给它源文件和一个 package.json,它会从 npm 仓库解析依赖,用 esbuild 打包所有内容,并返回 Worker Loader 期望的模块映射。
import { createWorker } from "@cloudflare/worker-bundler";
const worker = env.LOADER.get("my-worker", async () => {
const { mainModule, modules } = await createWorker({
files: {
"src/index.ts": `
import { Hono } from 'hono';
import { cors } from 'hono/cors';
const app = new Hono();
app.use('*', cors());
app.get('/', (c) => c.text('Hello from Hono!'));
app.get('/json', (c) => c.json({ message: 'It works!' }));
export default app;
`,
"package.json": JSON.stringify({
dependencies: { hono: "^4.0.0" }
})
}
});
return { mainModule, modules, compatibilityDate: "2026-01-01" };
});
await worker.getEntrypoint().fetch(request);
它还通过 createApp 支持全栈应用——打包服务端 Worker、客户端 JavaScript 和静态资源,内置的资产服务能处理内容类型、ETag 和 SPA 路由。
文件操作
@cloudflare/shell 为你的智能体在 Dynamic Worker 内提供一个虚拟文件系统。智能体代码调用 state 对象上的类型化方法——读取、写入、搜索、替换、差异比较、通配符匹配、JSON 查询/更新、归档——使用结构化输入输出,而不是解析字符串。
存储由持久的 Workspace(SQLite + R2)支持,因此文件在多次执行间保持持久。像 searchFiles、replaceInFiles 和 planEdits 这样的粗粒度操作能最小化 RPC 往返次数——智能体只需发起一次调用,而不是循环处理单个文件。批量写入默认是事务性的:如果任何写入失败,之前的写入会自动回滚。
import { Workspace } from "@cloudflare/shell";
import { stateTools } from "@cloudflare/shell/workers";
import { DynamicWorkerExecutor, resolveProvider } from "@cloudflare/codemode";
const workspace = new Workspace({
sql: this.ctx.storage.sql, // 可与任何 DO 的 SqlStorage、D1 或自定义 SQL 后端配合使用
r2: this.env.MY_BUCKET, // 大文件自动溢出到 R2
name: () => this.name // 惰性解析——需要时才解析,非构造时
});
// 代码在隔离的 Worker 沙箱中运行,无网络访问权限
const executor = new DynamicWorkerExecutor({ loader: env.LOADER });
// LLM 编写此代码;`state.*` 调用通过 RPC 分派回主机
const result = await executor.execute(
`async () => {
// 在所有 TypeScript 文件中搜索模式
const hits = await state.searchFiles("src/**/*.ts", "answer");
// 将多个编辑计划为单个事务
const plan = await state.planEdits([
{ kind: "replace", path: "/src/app.ts",
search: "42", replacement: "43" },
{ kind: "writeJson", path: "/src/config.json",
value: { version: 2 } }
]);
// 原子性应用——失败时回滚
return await state.applyEditPlan(plan);
}`,
[resolveProvider(stateTools(workspace))]
);
该包还提供了预构建的 TypeScript 类型声明和一个系统提示模板,这样你只需少量 token 就能将完整的 state API 放入 LLM 上下文。
实际应用场景
Code Mode
开发者希望他们的智能体能编写并执行针对工具 API 的代码,而不是逐个进行顺序工具调用。有了 Dynamic Workers,LLM 生成一个将多个 API 调用链接在一起的 TypeScript 函数,在 Dynamic Worker 中运行它,并将最终结果返回给智能体。这样一来,只有输出(而非每个中间步骤)会进入上下文窗口。这既降低了延迟和 token 使用量,又产生了更好的结果,尤其是在工具接口较大时。
我们自己的 Cloudflare MCP server 正是这样构建的:它通过仅两个工具——search 和 execute——在不到 1000 token 的情况下暴露了整个 Cloudflare API,因为智能体是针对类型化 API 编写代码,而不是导航数百个独立的工具定义。
构建自定义自动化
开发者正在使用 Dynamic Workers 让智能体动态构建自定义自动化。例如,Zite 正在构建一个应用平台,用户通过聊天界面交互——LLM 在幕后编写 TypeScript 来构建 CRUD 应用,连接到 Stripe、Airtable 和 Google Calendar 等服务,并运行后端逻辑,用户完全看不到一行代码。每个自动化都在自己的 Dynamic Worker 中运行,仅能访问端点所需的特定服务和库。
“为了实现 Zite 的 LLM 生成应用的服务器端代码,我们需要一个即时、隔离且安全的执行层。Cloudflare 的 Dynamic Workers 在这三点上都达标,并且在速度和库支持方面优于我们基准测试的所有其他平台。NodeJS 兼容的运行时支持 Zite 的所有工作流,允许数百个第三方集成,同时不牺牲启动时间。多亏了 Dynamic Workers,Zite 现在每天处理数百万次执行请求。”
— Antony Toron, CTO 兼联合创始人, Zite
运行 AI 生成的应用
开发者正在构建从 AI 生成完整应用的平台——无论是为客户还是为内部团队构建原型。有了 Dynamic Workers,每个应用都可以按需启动,然后在再次调用前放回冷存储。快速的启动时间使得在活跃开发期间预览变更变得容易。平台还可以阻止或拦截生成代码发出的任何网络请求,确保 AI 生成的应用安全运行。
定价
动态加载的 Worker 定价为每天每个加载的唯一 Worker 0.002 美元(截至本文发布时),此外还有常规 Worker 的 CPU 时间和调用定价。
对于 AI 生成的“code mode”用例,每个 Worker 都是唯一的一次性实例,这意味着价格是每个加载的 Worker 0.002 美元(加上 CPU 和调用)。与生成代码的推理成本相比,这笔费用通常可以忽略不计。
在测试期间,0.002 美元的费用被免除。由于定价可能变动,请始终查看我们的 Dynamic Workers 定价页面 获取最新信息。
开始使用
如果你使用的是 Workers 付费计划,今天就可以开始使用 Dynamic Workers。
Dynamic Workers 入门模板
使用这个“hello world”入门模板 部署一个能够加载和执行 Dynamic Workers 的 Worker。
Dynamic Workers 游乐场
你也可以部署 Dynamic Workers 游乐场,在那里你可以编写或导入代码,用 @cloudflare/worker-bundler 在运行时打包,通过 Dynamic Worker 执行,查看实时响应和执行日志。

Dynamic Workers 快速、可扩展且轻量级。在 Discord 上找到我们 如果你有任何问题。我们很期待看到你构建的东西!

Cloudflare 的连接云保护整个企业网络,帮助客户高效构建互联网规模的应用,加速任何网站或互联网应用,抵御 DDoS 攻击,将黑客拒之门外,并能在你的零信任之旅中提供帮助。
从任何设备访问 1.1.1.1 开始使用我们的免费应用,让你的互联网更快更安全。
觉得有用?分享给更多人