2026-03-24
阅读时间 9 分钟

去年9月我们介绍了代码模式,这种想法是代理不应通过调用工具来执行任务,而应通过编写调用 API 的代码来执行任务。我们已经证明,只需将 MCP 服务器转换为 TypeScript API 就可以代币使用量减少 81%。我们演示了代码模式也可以运行后面MCP 服务器而不是在它前面,创建新的Cloudflare MCP 服务器仅使用两个工具和不到 1,000 个令牌即可公开整个 Cloudflare API。
但是,如果代理(或 MCP 服务器)要执行 AI 即时生成的代码来执行任务,则该代码需要在某个地方运行,并且该某个地方需要安全。你不能只是评估()人工智能直接在您的应用程序中生成代码:恶意用户可能会轻易提示人工智能注入漏洞。
你需要一个沙箱:执行代码的地方,除了代码要访问的特定功能之外,与应用程序和世界其他地方隔离。
沙盒是人工智能行业的热门话题。对于这项任务,大多数人都会使用容器。使用基于 Linux 的容器,您可以启动您想要的任何类型的代码执行环境。Cloudflare 甚至提供我们的容器运行时和我们的沙箱 SDK为此目的。
但容器成本昂贵且启动缓慢,启动需要数百毫秒,运行需要数百兆字节的内存。您可能需要让它们保持温暖以避免延迟,并且您可能会想重复使用现有容器来执行多个任务,从而损害安全性。
如果我们想支持消费者规模的代理,其中每个最终用户都有一个代理(或多个!)并且每个代理都编写代码,那么容器是不够的。我们需要一些更轻的东西。
我们有它。
Dynamic Worker Loader:精益沙箱
我们在 9 月份的代码模式帖子中宣布了一项新的实验性功能:动态工作加载器 API。此 API 允许 Cloudflare Worker 在其自己的沙箱中实例化一个新的 Worker,并使用运行时指定的代码,一切都是动态的。
Dynamic Worker Loader 现已处于公开测试阶段,所有付费 Workers 用户均可使用。
阅读文档了解完整详细信息,但它看起来是这样的:
// 让你的 LLM 生成这样的代码。让代理代码:字符串=`导出默认值{异步 myAgent(param, env, ctx) {// ...}}`;// 获取表示代理应该能够使用的 API 的 RPC 存根// 访问。(这可以是您定义的任何 Workers RPC API。)让 chatRoomRpcStub = ...;// 使用worker loader加载一个worker来运行代码// 绑定。让worker = env.LOADER.load({// 指定代码。兼容性日期:“2026-03-01”,主模块:“agent.js”,模块:{“agent.js”:agentCode},// 授予代理访问聊天室 API 的权限。env: { CHAT_ROOM: chatRoomRpcStub },// 阻止互联网访问。(您也可以拦截它。)全局出站:空,});// 调用代理代码导出的RPC方法。等待worker.getEntrypoint().myAgent(param);
就是这样。
Dynamic Workers 使用与整个 Cloudflare Workers 平台自八年前推出以来构建的相同的底层沙箱机制:隔离。隔离是 V8 JavaScript 执行引擎的实例,与 Google Chrome 使用的引擎相同。他们是工人如何工作。
隔离需要几毫秒才能启动并使用几兆字节的内存。与典型容器相比,速度提高了约 100 倍,内存效率提高了 10-100 倍。
这意味着,如果您想按需为每个用户请求启动一个新的隔离以运行一小段代码,然后将其丢弃,您可以。
许多基于容器的沙箱提供商对全局并发沙箱和沙箱创建速率施加限制。Dynamic Worker Loader 没有这样的限制。它不需要,因为它只是一个 API,它是一直为我们的平台提供支持的同一技术的 API,该技术始终允许 Workers 无缝扩展到每秒数百万个请求。
想要每秒处理一百万个请求,其中每一个请求加载一个单独的动态工作沙箱,所有沙箱同时运行?没问题!
一次性动态工作人员通常在同一台机器上运行 - 相同的线程,甚至与创建它们的工作人员运行。无需奔波于世界各地寻找温暖的沙箱。隔离非常轻量级,我们可以在请求到达的任何地方运行它们。Cloudflare 全球数百个地点均支持 Dynamic Workers。
与容器相比,唯一的问题是您的代理需要编写 JavaScript。
从技术上讲,Workers(包括动态的)可以使用 Python 和 WebAssembly,但对于小代码片段(例如代理按需编写的代码),JavaScript 的加载和运行速度会更快。
我们人类往往对编程语言有强烈的偏好,虽然许多人喜欢 JavaScript,但其他人可能更喜欢 Python、Rust 或无数其他语言。
但我们这里讨论的不是人类。我们正在谈论人工智能。人工智能会编写你想要的任何语言。法学硕士是每种主要语言的专家。他们的 JavaScript 训练数据非常庞大。
JavaScript 就其在网络上的本质而言,被设计为沙盒化。这是适合该工作的正确语言。
TypeScript 中定义的工具
如果我们希望我们的代理能够做任何有用的事情,它需要与外部 API 进行通信。我们如何告诉它它可以访问的 API?
MCP 定义了平面工具调用的模式,但没有定义编程 API。OpenAPI 提供了一种表达 REST API 的方法,但它很冗长,无论是架构本身还是您必须编写的调用它的代码。
对于暴露给 JavaScript 的 API,有一个显而易见的答案:TypeScript。
代理了解 TypeScript。TypeScript 被设计得简洁。只需很少的令牌,您就可以让您的代理准确了解您的 API。
// 与聊天室交互的接口。界面聊天室{// 获取聊天记录的最后一条“limit”消息。getHistory(limit: number): Promise<Message[]>;// 订阅新消息。处理返回的对象// 取消订阅。订阅(回调:(msg:消息)=> void):Promise <Disposable>;// 发布消息进行聊天。帖子(文本:字符串):Promise <void>;}类型消息 = {作者:字符串;时间:日期;文本:字符串;}
将其与等效的 OpenAPI 规范进行比较(该规范太长,您必须滚动才能看到全部内容):
开放API:3.1.0信息:标题:聊天室 API描述:>与聊天室交互的界面。版本:1.0.0路径:/消息:得到:操作Id:获取历史记录摘要:获取最近的聊天记录描述:返回聊天日志中最后一条“limit”消息,最新的在前。参数:- 名称:限制在:查询必填:真实架构:类型:整数最小值:1回应:“200”:描述:消息列表。内容:应用程序/json:架构:类型:数组项目:$ref: "#/components/schemas/Message"帖子:操作 ID:postMessage摘要: 向聊天室发布消息请求正文:必填:真实内容:应用程序/json:架构:类型:对象需要:- 文字属性:文字:类型:字符串回应:“204”:描述:留言成功。/消息/流:得到:操作Id:订阅消息摘要:通过SSE订阅新消息描述:>打开服务器发送的事件流。每个事件都带有一个 JSON 编码的消息对象。客户端通过关闭连接来取消订阅。回应:“200”:描述:新消息的 SSE 流。内容:文本/事件流:架构:描述:>每个 SSE“数据”字段都包含一个 JSON 编码的消息对象。$ref: "#/components/schemas/Message"组件:模式:留言:类型:对象需要:- 作者- 时间- 文字属性:作者:类型:字符串时间:类型:字符串格式:日期-时间文字:类型:字符串
我们认为 TypeScript API 更好。它的标记更少,并且更容易理解(对于代理和人类来说)。
Dynamic Worker Loader 可以轻松地在您自己的 Worker 中实现这样的 TypeScript API,然后将其作为方法参数或在 env 对象中传递到 Dynamic Worker。Workers Runtime 会自动设置一个Cap'n Web RPC在沙箱和您的工具代码之间建立桥梁,以便代理可以跨安全边界调用您的 API,而无需意识到它没有使用本地库。
这意味着您的代理可以编写如下代码:
// 思考:用户让我总结一下 Alice 最近的聊天消息。// 我将在代码中过滤最近的消息历史记录,这样我只需要// 读取相关消息。让历史=等待env.CHAT_ROOM.getHistory(1000);返回历史记录.filter(msg => msg.author == "alice");
HTTP 过滤和凭据注入
如果您希望为代理提供 HTTP API,我们完全支持。使用全球出站通过工作加载器 API 的选项,您可以注册一个在每个 HTTP 请求上调用的回调,您可以在其中检查请求、重写请求、注入身份验证密钥、直接响应它、阻止它或您可能喜欢的任何其他内容。
例如,您可以使用它来实现凭证注入(令牌注入):当代理向需要授权的服务发出 HTTP 请求时,您可以在发出时向请求添加凭据。这样,代理本身永远不会知道秘密凭证,因此无法泄露它们。
当代理与其训练集中的众所周知的 API 进行通信时,或者当您希望代理使用基于 REST API 构建的库(该库可以在代理的沙箱内运行)时,可能需要使用纯 HTTP 接口。
话虽如此,在没有兼容性要求的情况下,TypeScript RPC 接口比 HTTP 更好:
如上所示,TypeScript 接口需要描述的标记比 HTTP 接口少得多。
代理可以使用比同等 HTTP 少得多的令牌编写代码来调用 TypeScript 接口。
使用 TypeScript 接口,由于您无论如何都在定义自己的包装器接口,因此更容易缩小接口范围以准确地公开您想要提供给代理的功能,既简单又安全。使用 HTTP,您更有可能实现过滤针对某些现有 API 发出的请求。这很困难,因为您的代理必须完全解释每个 API 调用的含义,以便正确决定是否允许它,并且 HTTP 请求很复杂,具有许多可能都有意义的标头和其他参数。最终,编写一个仅实现您想要允许的功能的 TypeScript 包装器会更容易。
强化基于隔离的沙箱非常棘手,因为它是比硬件虚拟机更复杂的攻击面。尽管所有沙箱机制都存在错误,但 V8 中的安全错误比典型虚拟机管理程序中的安全错误更常见。当使用隔离来沙箱可能的恶意代码时,拥有额外的深度防御层非常重要。例如,Google Chrome 为此实施了严格的进程隔离,但这并不是唯一可能的解决方案。
我们拥有近十年的保护基于隔离的平台的经验。我们的系统会在数小时内自动将 V8 安全补丁部署到生产环境 - 比 Chrome 本身还要快。我们的安全架构具有定制的第二层沙箱,可根据风险评估对租户进行动态封锁。我们扩展了 V8 沙箱本身利用 MPK 等硬件功能。我们与(并聘请)领先的研究人员合作开发针对幽灵的新颖防御。我们还拥有扫描代码中是否存在恶意模式并自动阻止它们或应用额外沙箱层的系统。还有更多。
当您在 Cloudflare 上使用 Dynamic Workers 时,您会自动获得所有这些。
我们构建了许多库,您在使用动态工作人员时可能会发现它们很有用:
@cloudflare/codemode使用 Dynamic Workers 简化针对 AI 工具运行模型生成的代码。其核心是动态工作执行器(),它构建了一个具有代码规范化功能的专用沙箱,以处理常见的格式错误,并直接访问全球出站用于控制的获取器获取()沙箱内的行为 - 将其设置为空完全隔离,或通过抓取器绑定到路由、拦截或丰富来自沙箱的出站请求。
const 执行器 = new DynamicWorkerExecutor({加载器:env.LOADER,globalOutbound: null, // 完全隔离});const codemode = createCodeTool({工具:我的工具,执行人,});返回生成文本({模型,消息,工具:{代码模式},});
代码模式 SDK 还提供两个服务器端实用函数。codeMcpServer({ 服务器, 执行器 })包装现有的 MCP 服务器,用单个工具替换其工具表面代码()工具。openApiMcpServer({ 规范、执行器、请求 })更进一步:给定 OpenAPI 规范和执行器,它构建一个完整的 MCP 服务器搜索()和执行()Cloudflare MCP 服务器使用的工具,更适合更大的 API。
在这两种情况下,模型生成的代码在 Dynamic Workers 内部运行,并通过传递给执行器的 RPC 绑定对外部服务进行调用。
动态工作者期望预先捆绑的模块。@cloudflare/worker-bundler为您处理这个问题:给它源文件和包.json,它解决了注册表中的 npm 依赖关系,将所有内容与esbuild,并返回 Worker Loader 期望的模块映射。
从“@cloudflare/worker-bundler”导入{createWorker};const worker = env.LOADER.get("my-worker", async () => {const { mainModule, 模块 } = 等待 createWorker({文件:{“src/index.ts”:`从'hono'导入{Hono};从'hono/cors'导入{cors};const app = new Hono();app.use('*', cors());app.get('/', (c) => c.text('来自霍诺的你好!'));app.get('/json', (c) => c.json({ message: '它有效!' }));导出默认应用程序;`,"package.json": JSON.stringify({依赖项:{ 荣誉:“^4.0.0” }})}});返回 { mainModule、模块、compatibilityDate: "2026-01-01" };});等待worker.getEntrypoint().fetch(请求);
它还支持全栈应用程序创建应用程序- 将服务器 Worker、客户端 JavaScript 和静态资产捆绑在一起,并提供处理内容类型、ETag 和 SPA 路由的内置资产服务。
@cloudflare/shell为您的代理提供动态工作器内的虚拟文件系统。代理代码调用类型化方法状态对象 - 读取、写入、搜索、替换、差异、glob、JSON 查询/更新、存档 - 使用结构化输入和输出而不是字符串解析。
存储有耐用的支持工作空间(SQLite + R2),因此文件在执行过程中保持不变。粗操作如搜索文件,替换文件, 和计划编辑最大限度地减少 RPC 往返次数 - 代理发出一次调用,而不是循环访问各个文件。默认情况下,批量写入是事务性的:如果任何写入失败,较早的写入会自动回滚。
从“@cloudflare/shell”导入{工作区};从“@cloudflare/shell/workers”导入{stateTools};从“@cloudflare/codemode”导入{DynamicWorkerExecutor,resolveProvider};常量工作空间 = 新工作空间({sql: this.ctx.storage.sql, // 适用于任何 DO 的 SqlStorage、D1 或自定义 SQL 后端r2: this.env.MY_BUCKET, // 大文件自动溢出到R2name: () => this.name // 惰性 - 在需要时解决,而不是在构造时解决});// 代码在没有网络访问权限的隔离 Worker 沙箱中运行const executor = new DynamicWorkerExecutor({ loader: env.LOADER });// LLM 编写此代码;`state.*` 通过 RPC 调用调度回主机const 结果 = 等待执行器.execute(`异步()=> {// 在所有 TypeScript 文件中搜索模式const hits = wait state.searchFiles("src/**/*.ts", "answer");// 将多个编辑计划为单个事务const plan =等待状态.planEdits([{ 种类:“替换”,路径:“/src/app.ts”,搜索:“42”,替换:“43”},{ 种类:“writeJson”,路径:“/src/config.json”,值:{ 版本:2 } }]);// 原子应用 - 失败时回滚返回等待状态.applyEditPlan(计划);}`,[resolveProvider(stateTools(工作空间))]);
该软件包还附带了预构建的 TypeScript 类型声明和系统提示模板,因此您可以删除完整的状态通过少量令牌将 API 接入您的 LLM 环境。
开发人员希望他们的代理针对工具 API 编写和执行代码,而不是一次顺序调用一个工具。借助 Dynamic Workers,LLM 生成单个 TypeScript 函数,该函数将多个 API 调用链接在一起,在 Dynamic Worker 中运行它,并将最终结果返回给代理。因此,只有输出(而不是每个中间步骤)最终出现在上下文窗口中。这可以减少延迟和令牌使用,并产生更好的结果,特别是当工具表面很大时。
我们自己的Cloudflare MCP 服务器正是这样构建的:它仅通过两个工具(搜索和执行)公开整个 Cloudflare API,用不到 1,000 个令牌,因为代理根据类型化 API 编写代码,而不是导航数百个单独的工具定义。
构建自定义自动化
开发人员正在使用 Dynamic Workers 让代理动态构建自定义自动化。泽特例如,正在构建一个应用程序平台,用户可以通过聊天界面进行交互 - 法学硕士在幕后编写 TypeScript 来构建 CRUD 应用程序,连接到 Stripe、Airtable 和 Google Calendar 等服务,并运行后端逻辑,所有这些都不需要用户看到一行代码。每个自动化都在自己的动态工作线程中运行,只能访问端点所需的特定服务和库。
- 为了为 Zite 的 LLM 生成的应用程序启用服务器端代码,我们需要一个即时、隔离且安全的执行层。Cloudflare 的 Dynamic Workers 在这三个方面均达到了标准,并且优于我们在速度和库支持方面进行基准测试的所有其他平台。NodeJS 兼容运行时支持所有 Zite 工作流程,允许数百个第三方集成,而无需牺牲启动时间。借助 Dynamic Workers,Zite 现在每天可以处理数百万个执行请求。
�安东尼·托伦,Zite 首席技术官兼联合创始人
运行人工智能生成的应用程序
开发人员正在构建平台,为他们的客户或构建原型的内部团队从人工智能生成完整的应用程序。借助 Dynamic Workers,每个应用程序都可以按需启动,然后放回到冷存储中,直到再次调用。快速启动时间可以轻松预览活跃开发期间的更改。平台还可以阻止或拦截生成的代码发出的任何网络请求,从而确保人工智能生成的应用程序安全运行。
除了常规 Workers 的通常 CPU 时间和调用定价之外,动态加载的 Workers 的定价为每天加载的每个唯一 Worker 0.002 美元(截至本文发布)。
对于 AI 生成的“代码模式”用例,每个 Worker 都是唯一的一次性产品,这意味着每个加载的 Worker 的价格为 0.002 美元(加上 CPU 和调用)。与生成代码的推理成本相比,此成本通常可以忽略不计。
在测试期间,免除 0.002 美元的费用。由于价格可能会发生变化,请随时查看我们的动态员工定价了解最新信息。� 如果您使用的是 Workers Paid 计划,则可以开始使用
充满活力的员工今天。 使用这个“你好世界”
开胃菜部署一个可以加载和执行动态工作人员的工作人员。 充满活力的工人游乐场
您还可以部署充满活力的工人游乐场
,您可以在其中编写或导入代码,并在运行时将其与@cloudflare/worker-bundler,通过 Dynamic Worker 执行它,查看实时响应和执行日志。动态工作人员快速、可扩展且轻量级。在 Discord 上找到我们
如果您有任何疑问。我们很想看看您建造了什么!Cloudflare 的连接云保护
整个企业网络,帮助客户构建高效的互联网规模应用,加速任何网站或互联网应用程序,抵御 DDoS 攻击, 保持黑客陷入困境,并且可以帮助您您的零信任之旅。参观1.1.1.1
从任何设备开始使用我们的免费应用程序,让您的互联网更快、更安全。要详细了解我们帮助建立更好的互联网的使命,从这里开始。