
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Wed, 15 Apr 2026 17:43:02 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Agents have their own computers with Sandboxes GA]]></title>
            <link>https://blog.cloudflare.com/sandbox-ga/</link>
            <pubDate>Mon, 13 Apr 2026 13:08:35 GMT</pubDate>
            <description><![CDATA[ Cloudflare Sandboxes give AI agents a persistent, isolated environment: a real computer with a shell, a filesystem, and background processes that starts on demand and picks up exactly where it left off. ]]></description>
            <content:encoded><![CDATA[ <p>When we launched <a href="https://github.com/cloudflare/sandbox-sdk"><u>Cloudflare Sandboxes</u></a> last June, the premise was simple: <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/"><u>AI agents</u></a> need to develop and run code, and they need to do it somewhere safe.</p><p>If an agent is acting like a developer, this means cloning repositories, building code in many languages, running development servers, etc. To do these things effectively, they will often need a full computer (and if they don’t, they can <a href="https://blog.cloudflare.com/dynamic-workers/"><u>reach for something lightweight</u></a>!).</p><p>Many developers are stitching together solutions using VMs or existing container solutions, but there are lots of hard problems to solve:</p><ul><li><p><b>Burstiness -</b> With each session needing its own sandbox, you often need to spin up many sandboxes quickly, but you don’t want to pay for idle compute on standby.</p></li><li><p><b>Quick state restoration</b> - Each session should start quickly and re-start quickly, resuming past state.</p></li><li><p><b>Security</b> - Agents need to access services securely, but can’t be trusted with credentials.</p></li><li><p><b>Control</b> - It needs to be simple to programmatically control sandbox lifecycle, execute commands, handle files, and more.</p></li><li><p><b>Ergonomics</b> - You need to give a simple interface for both humans and agents to do common operations.</p></li></ul><p>We’ve spent time solving these issues so you don’t have to. Since our initial launch we’ve made Sandboxes an even better place to run agents at scale. We’ve worked with our initial partners such as Figma, who run agents in containers with <a href="https://www.figma.com/make/"><u>Figma Make</u></a>:</p><blockquote><p><i>“Figma Make is built to help builders and makers of all backgrounds go from idea to production, faster. To deliver on that goal, we needed an infrastructure solution that could provide reliable, highly-scalable sandboxes where we could run untrusted agent- and user-authored code. Cloudflare Containers is that solution.”</i></p><p><i>- </i><b><i>Alex Mullans</i></b><i>, AI and Developer Platforms at Figma</i></p></blockquote><p>We want to bring Sandboxes to even more great organizations, so today we are excited to announce that <b>Sandboxes and Cloudflare Containers are both generally available.</b></p><p>Let’s take a look at some of the recent changes to Sandboxes:</p><ul><li><p><b>Secure credential injection </b>lets you make authenticated calls without the agent ever having credential access  </p></li><li><p><b>PTY support</b> gives you and your agent a real terminal</p></li><li><p><b>Persistent code interpreters</b> give your agent a place to execute stateful Python, JavaScript, and TypeScript out of the box</p></li><li><p><b>Background processes and live preview URLs</b> provide a simple way to interact with development servers and verify in-flight changes</p></li><li><p><b>Filesystem watching</b> improves iteration speed as agents make changes</p></li><li><p><b>Snapshots</b> let you quickly recover an agent's coding session</p></li><li><p><b>Higher limits and Active CPU Pricing</b> let you deploy a fleet of agents at scale without paying for unused CPU cycles </p></li></ul>
    <div>
      <h2>Sandboxes 101</h2>
      <a href="#sandboxes-101">
        
      </a>
    </div>
    <p>Before getting into some of the recent changes, let’s quickly look at the basics.</p><p>A Cloudflare Sandbox is a persistent, isolated environment powered by <a href="https://blog.cloudflare.com/containers-are-available-in-public-beta-for-simple-global-and-programmable/"><u>Cloudflare Containers</u></a>. You ask for a sandbox by name. If it's running, you get it. If it's not, it starts. When it's idle, it sleeps automatically and wakes when it receives a request. It’s easy to programmatically interact with the sandbox using methods like <code>exec</code>, <code>gitClone</code>, <code>writeFile</code> and <a href="https://developers.cloudflare.com/sandbox/api/"><u>more</u></a>.</p>
            <pre><code>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 });
  },
};
</code></pre>
            <p>As long as you provide the same ID, subsequent requests can get to this same sandbox from anywhere in the world.</p>
    <div>
      <h2>Secure credential injection</h2>
      <a href="#secure-credential-injection">
        
      </a>
    </div>
    <p>One of the hardest problems in agentic workloads is authentication. You often need agents to access private services, but you can't fully trust them with raw credentials. </p><p>Sandboxes solve this by injecting credentials at the network layer using a programmable egress proxy. This means that sandbox agents never have access to credentials and you can fully customize auth logic as you see fit:</p>
            <pre><code>class OpenCodeInABox extends Sandbox {
  static outboundByHost = {
    "my-internal-vcs.dev": (request, env, ctx) =&gt; {
      const headersWithAuth = new Headers(request.headers);
      headersWithAuth.set("x-auth-token", env.SECRET);
      return fetch(request, { headers: headersWithAuth });
    }
  }
}
</code></pre>
            <p>For a deep dive into how this works — including identity-aware credential injection, dynamically modifying rules, and integrating with <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/"><u>Workers bindings</u></a> — read our recent blog post on <a href="https://blog.cloudflare.com/sandbox-auth"><u>Sandbox auth</u></a>.</p>
    <div>
      <h2>A real terminal, not a simulation</h2>
      <a href="#a-real-terminal-not-a-simulation">
        
      </a>
    </div>
    <p>Early agent systems often modeled shell access as a request-response loop: run a command, wait for output, stuff the transcript back into the prompt, repeat. It works, but it is not how developers actually use a terminal. </p><p>Humans run something, watch output stream in, interrupt it, reconnect later, and keep going. Agents benefit from that same feedback loop.</p><p>In February, we shipped PTY support. A pseudo-terminal session in a Sandbox, proxied over WebSocket, compatible with <a href="https://xtermjs.org/"><u>xterm.js</u></a>.</p><p>Just call <code>sandbox.terminal</code> to serve the backend:</p>
            <pre><code>// 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 });
  },
};

</code></pre>
            <p>And use <code>xterm addon</code> to call it from the client:</p>
            <pre><code>// 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 }) =&gt; `${origin}/terminal`,
});

term.loadAddon(addon);
term.open(document.getElementById("terminal-container")!);
addon.connect({ sandboxId: "my-session" });
</code></pre>
            <p>This allows agents and developers to use a full PTY to debug those sessions live.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3bgyxh8kg3MPfij2v1XXLE/9cff50318ad306b20c3346c3bd3554d9/BLOG-3264_2.gif" />
          </figure><p>Each terminal session gets its own isolated shell, its own working directory, its own environment. Open as many as you need, just like you would on your own machine. Output is buffered server-side, so reconnecting replays what you missed.</p>
    <div>
      <h2>A code interpreter that remembers</h2>
      <a href="#a-code-interpreter-that-remembers">
        
      </a>
    </div>
    <p>For data analysis, scripting, and exploratory workflows, we also ship a higher-level abstraction: a persistent code execution context.</p><p>The key word is “persistent.” Many code interpreter implementations run each snippet in isolation, so state disappears between calls. You can't set a variable in one step and read it in the next.</p><p>Sandboxes allow you to create “contexts” that persist state. Variables and imports persist across calls the same way they would in a Jupyter notebook:</p>
            <pre><code>// 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) =&gt; console.log(line.text) });

// result contains matplotlib charts, structured json output, and Pandas tables in HTML
</code></pre>
            
    <div>
      <h2>Start a server. Get a URL. Ship it.</h2>
      <a href="#start-a-server-get-a-url-ship-it">
        
      </a>
    </div>
    <p>Agents are more useful when they can build something and show it to the user immediately. Sandboxes support background processes, readiness checks, and <a href="https://developers.cloudflare.com/sandbox/concepts/preview-urls/"><u>preview URLs</u></a>. This lets an agent start a development server and share a live link without leaving the conversation.</p>
            <pre><code>// 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}`);
</code></pre>
            <p>With <code><i>waitForPort()</i></code> and <code><i>waitForLog()</i></code>, agents can sequence work based on real signals from the running program instead of guesswork. This is much nicer than a common alternative, which is usually some version of <code>sleep(2000)</code> followed by hope.</p>
    <div>
      <h2>Watch the file system and react immediately</h2>
      <a href="#watch-the-file-system-and-react-immediately">
        
      </a>
    </div>
    <p>Modern development loops are event-driven. Save a file, rerun the build. Edit a config, restart the server. Change a test, rerun the suite.</p><p>We shipped <i>sandbox.watch()</i> in March. It returns an SSE stream backed by native <a href="https://man7.org/linux/man-pages/man7/inotify.7.html"><u>inotify</u></a>, the kernel mechanism Linux uses for filesystem events.</p>
            <pre><code>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&lt;FileWatchSSEEvent&gt;(stream)) {
  if (event.type === 'modify' &amp;&amp; event.path.endsWith('.ts')) {
    await sandbox.exec('npx tsc --noEmit', { cwd: '/workspace' });
  }
}
</code></pre>
            <p>This is one of those primitives that quietly changes what agents can do. An agent that can observe the filesystem in real time can participate in the same feedback loops as a human developer.</p>
    <div>
      <h2>Waking up quickly with snapshots</h2>
      <a href="#waking-up-quickly-with-snapshots">
        
      </a>
    </div>
    <p>Imagine a (human) developer working on their laptop. They <code>git clone</code> a repo, run <code>npm install</code>, write code, push a PR, then close their laptop while waiting for code review. When it’s time to resume work, they just re-open the laptop and continue where they left off.</p><p>If an agent wants to replicate this workflow on a naive container platform, you run into a snag. How do you resume where you left off quickly? You could keep a sandbox running, but then you pay for idle compute. You could start fresh from the container image, but then you have to wait for a long <code>git clone</code> and <code>npm install</code>.</p><p>Our answer is snapshots, which will be rolling out in the coming weeks.</p><p>A snapshot preserves a container's full disk state, OS config, installed dependencies, modified files, data files and more. Then it lets you quickly restore it later.</p><p>You can configure a Sandbox to automatically snapshot when it goes to sleep.</p>
            <pre><code>class AgentDevEnvironment extends Sandbox {
  sleepAfter = "5m";
  persistAcrossSessions = {type: "disk"}; // you can also specify individual directories
}
</code></pre>
            <p>You can also programmatically take a snapshot and manually restore it. This is useful for checkpointing work or forking sessions. For instance, if you wanted to run four instances of an agent in parallel, you could easily boot four sandboxes from the same state.</p>
            <pre><code>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) =&gt; {
    const newInstance = await getSandbox(`${baseId}-fork-${i}`);
    return newInstance.start({ snapshot: snapshotId });
  });

  await Promise.all(forks);
}
</code></pre>
            <p>Snapshots are stored in <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a> within your account, giving you durability and location-independence. R2's <a href="https://developers.cloudflare.com/cache/how-to/tiered-cache/"><u>tiered caching</u></a> system allows for fast restores across all of Region: Earth.</p><p>In future releases, live memory state will also be captured, allowing running processes to resume exactly where they left off. A terminal and an editor will reopen in the exact state they were in when last closed.</p><p>If you are interested in restoring session state before snapshots go live, you can use the <a href="https://developers.cloudflare.com/sandbox/guides/backup-restore/"><code><u>backup and restore</u></code></a> methods today. These also persist and restore directories using R2, but are not as performant as true VM-level snapshots. Though they still can lead to considerable speed improvements over naively recreating session state.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/LzVucBiNvxOh3NFn0ukxj/3b8e6cd9a5ca241b6c6a7c8556c0a529/BLOG-3264_3.gif" />
          </figure><p><sup><i>Booting a sandbox, cloning  ‘axios’, and npm installing takes 30 seconds. Restoring from a backup takes two seconds.</i></sup></p><p>Stay tuned for the official snapshot release.</p>
    <div>
      <h2>Higher limits and Active CPU Pricing</h2>
      <a href="#higher-limits-and-active-cpu-pricing">
        
      </a>
    </div>
    <p>Since our initial launch, we’ve been steadily increasing capacity. Users on our standard pricing plan can now run 15,000 concurrent instances of the lite instance type, 6,000 instances of basic, and over 1,000 concurrent larger instances. <a href="https://forms.gle/3vvDvXPECjy6F8v56"><u>Reach out</u></a> to run even more!</p><p>We also changed our pricing model to be more cost effective running at scale. Sandboxes now <a href="https://developers.cloudflare.com/changelog/post/2025-11-21-new-cpu-pricing/"><u>only charge for actively used CPU cycles</u></a>. This means that you aren’t paying for idle CPU while your agent is waiting for an LLM to respond.</p>
    <div>
      <h2>This is what a computer looks like </h2>
      <a href="#this-is-what-a-computer-looks-like">
        
      </a>
    </div>
    <p>Nine months ago, we shipped a sandbox that could run commands and access a filesystem. That was enough to prove the concept.</p><p>What we have now is different in kind. A Sandbox today is a full development environment: a terminal you can connect a browser to, a code interpreter with persistent state, background processes with live preview URLs, a filesystem that emits change events in real time, egress proxies for secure credential injection, and a snapshot mechanism that makes warm starts nearly instant. </p><p>When you build on this, a satisfying pattern emerges: agents that do real engineering work. Clone a repo, install it, run the tests, read the failures, edit the code, run the tests again. The kind of tight feedback loop that makes a human engineer effective — now the agent gets it too.</p><p>We're at version 0.8.9 of the SDK. You can get started today:</p><p><code>npm i @cloudflare/sandbox@latest</code></p><div>
  
</div>
<p></p> ]]></content:encoded>
            <category><![CDATA[Agents Week]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Containers]]></category>
            <category><![CDATA[Sandbox]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">7jXMXMjQUIpjGzJdPadO4a</guid>
            <dc:creator>Kate Reznykova</dc:creator>
            <dc:creator>Mike Nomitch</dc:creator>
            <dc:creator>Naresh Ramesh</dc:creator>
        </item>
        <item>
            <title><![CDATA[Dynamic, identity-aware, and secure Sandbox auth]]></title>
            <link>https://blog.cloudflare.com/sandbox-auth/</link>
            <pubDate>Mon, 13 Apr 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Outbound Workers for Sandboxes provide a programmable, zero-trust egress proxy for AI agents. This allows developers to inject credentials and enforce dynamic security policies without exposing sensitive tokens to untrusted code.
 ]]></description>
            <content:encoded><![CDATA[ <p>As <a href="https://www.cloudflare.com/learning/ai/what-is-large-language-model/"><u>AI Large Language Models</u></a> and harnesses like OpenCode and Claude Code become increasingly capable, we see more users kicking off sandboxed agents in response to chat messages, Kanban updates, <a href="https://www.cloudflare.com/learning/ai/ai-vibe-coding/"><u>vibe coding</u></a> UIs, terminal sessions, GitHub comments, and more.</p><p>The sandbox is an important step beyond simple containers, because it gives you a few things:</p><ul><li><p><b>Security</b>: Any untrusted end user (or a rogue LLM) can run in the sandbox and not compromise the host machine or other sandboxes running alongside it. This is traditionally (<a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>but not always</u></a>) accomplished with a microVM.</p></li><li><p><b>Speed</b>: An end user should be able to pick up a new sandbox quickly <i>and</i> restore the state from a previously used one quickly.</p></li><li><p><b>Control</b>: The <i>trusted</i> platform needs to be able to take actions within the <i>untrusted</i> domain of the sandbox. This might mean mounting files in the sandbox, or controlling which requests access it, or executing specific commands.</p></li></ul><p>Today, we’re excited to add another key component of control to our <a href="https://developers.cloudflare.com/sandbox/"><u>Sandboxes</u></a> and all <a href="https://developers.cloudflare.com/containers/"><u>Containers</u></a>: outbound Workers. These are programmatic egress proxies that allow users running sandboxes to easily connect to different services, add <a href="https://www.cloudflare.com/learning/performance/what-is-observability/"><u>observability</u></a>, and, importantly for agents, add flexible and safe authentication.</p>
    <div>
      <h2>How it works</h2>
      <a href="#how-it-works">
        
      </a>
    </div>
    <p>Here’s a quick look at adding a secret key to a header using an outbound Worker:</p>
            <pre><code>class OpenCodeInABox extends Sandbox {
  static outboundByHost = {
    "github.com": (request, env, ctx) =&gt; {
      const headersWithAuth = new Headers(request.headers);
      headersWithAuth.set("x-auth-token", env.SECRET);
      return fetch(request, { headers: headersWithAuth });
    }
  }
}
</code></pre>
            <p>Any time code running in the sandbox makes a request to <code>“github.com”</code>, the request is proxied through the handler. This allows you to do anything you want on each request, including logging, modifying, or cancelling it. In this case, we’re safely injecting a secret (more on this later). The proxy runs on the same machine as any sandbox, has access to distributed state, and can be easily modified with simple JavaScript.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/RSbCJMOoqz8xLWMnPyijV/520addf1676d195be6258b427881cdde/BLOG-3199_2.png" />
          </figure><p>We’re excited about all the possibilities this adds to Sandboxes, especially around authentication for agents. Before going into details, let’s back up and take a quick tour of traditional forms of auth, and why we think there’s something better.</p>
    <div>
      <h2>Common auth for agentic workloads</h2>
      <a href="#common-auth-for-agentic-workloads">
        
      </a>
    </div>
    <p>The core issue with agentic auth is that we can’t fully trust the workload. While our LLMs aren’t nefarious (at least not yet), we still need to be able to apply protections to ensure they don’t use data inappropriately or take actions they shouldn’t.</p><p>A few common methods exist to provide auth to agents, and each has downsides:</p><p><b>Standard API tokens</b> are the most basic method of authentication, typically injected into applications via environment variables or in mounted secrets files. This is the arguably simplest method, but least secure. You have to trust that the sandbox won’t somehow be compromised or accidentally exfiltrate the token while making a request. Since you can’t fully trust the agent, you’ll need to set up token expiry and rotation, which can be a hassle.</p><p><b>Workload identity tokens</b>, such as OIDC tokens, can solve some of this pain. Rather than granting the agent a token with general permissions, you can grant it a token that attests its identity. Now, rather than the agent having direct access to some service with a token, it can exchange an identity token for a very short-lived access token. The OIDC token can be invalidated after a specific agent’s workflow completes, and expiry is easier to manage. One of the biggest downsides of workload identity tokens is the potential inflexibility of integrations. Many services don’t have first-class support for OIDC, so in order to get working integrations with upstream services, platforms will need to roll their own token-exchanging services. This makes adoption difficult.</p><p><b>Custom proxies </b>provide maximum flexibility, and can be paired with workload identity tokens. If you can pass some or all of your sandbox egress through a trusted piece of code, you can insert whatever rules you need. Maybe the upstream service your agent is communicating with has a bad RBAC story, and it can’t provide granular permissions. No problem, just write the controls and permissions yourself! This is a great option for agents that you need to lock down with granular controls. However, how do you intercept all of a sandbox’s traffic? How do you set up a proxy that is dynamic and easily programmable? How do you proxy traffic efficiently? These aren’t easy problems to solve.</p><p>With those imperfect methods in mind, what does an ideal auth mechanism look like?</p><p>Ideally, it is:</p><ul><li><p><b>Zero trust.</b> No token is ever granted to an untrusted user for any amount of time.</p></li><li><p><b>Simple. </b>Easy to author. Doesn’t involve a complex system of minting, rotating, and decrypting tokens.</p></li><li><p><b>Flexible.</b> We don’t rely on the upstream system to provide the granular access we need. We can apply whatever rules we want.</p></li><li><p><b>Identity-aware.</b> We can identify the sandbox making the call and apply specific rules for it.</p></li><li><p><b>Observable.</b> We can easily gather information about what calls are being made.</p></li><li><p><b>Performant.</b> We aren’t round-tripping to a centralized or slow source of truth.</p></li><li><p><b>Transparent.</b> The sandboxed workload doesn’t have to know about it. Things just work.</p></li><li><p><b>Dynamic.</b> We can change rules on the fly.</p></li></ul><p>We believe outbound Workers for Sandboxes fit the bill on all of these. Let’s see how.</p>
    <div>
      <h2>Outbound Workers in practice</h2>
      <a href="#outbound-workers-in-practice">
        
      </a>
    </div>
    
    <div>
      <h3>Basics: restriction and observability</h3>
      <a href="#basics-restriction-and-observability">
        
      </a>
    </div>
    <p>First, we’ll look at a very basic example: logging requests and denying specific actions.</p><p>In this case, we’ll use the outbound function, which intercepts all outgoing HTTP requests from the sandbox. With a few lines of JavaScript, it’s easy to ensure only GETs are made and log then deny any disallowed methods.</p>
            <pre><code>class MySandboxedApp extends Sandbox {
  static outbound = (req, env, ctx) =&gt; {
    // Deny any non-GET action and log
    if (req.method !== 'GET') {
      console.log(`Container making ${req.method} request to: ${req.url}`);
      return new Response('Not Allowed', { status: 405, statusText: 'Method Not Allowed'});
    }

    // Proceed if it is a GET request
    return fetch(req);
  };
}
</code></pre>
            <p>This proxy runs on Workers and runs on the same machine as the sandboxed VM. Workers were built for quick response times, often sitting in front of cached CDN traffic, so additional latency is extremely minimal.</p><p>Because this is running on Workers, we get observability out of the box. You can view logs and outbound requests <a href="https://developers.cloudflare.com/workers/observability/logs/workers-logs/"><u>in the Workers dashboard</u></a> or <a href="https://developers.cloudflare.com/workers/observability/logs/logpush/"><u>export them</u></a> to your application performance monitoring tool of choice.</p>
    <div>
      <h3>Zero trust credential injection</h3>
      <a href="#zero-trust-credential-injection">
        
      </a>
    </div>
    <p>How would we use this to enforce a <a href="https://www.cloudflare.com/learning/security/glossary/what-is-zero-trust/"><u>zero trust environment</u></a> for our agent? Let’s imagine we want to make a request to a private GitHub instance, but we never want our LLM to access a private token.</p><p>We can use <code>outboundByHost</code> to define functions for specific domains or IPs. In this case, we’ll inject a protected credential if the domain is “my-internal-vcs.dev”. The sandboxed agent <i>never has access</i> to these credentials.</p>
            <pre><code>class OpenCodeInABox extends Sandbox {
  static outboundByHost = {
    "my-internal-vcs.dev": (request, env, ctx) =&gt; {
      const headersWithAuth = new Headers(request.headers);
      headersWithAuth.set("x-auth-token", env.SECRET);
      return fetch(request, { headers: headersWithAuth });
    }
  }
}
</code></pre>
            <p>It is also easy to conditionalize the response based on the identity of the container. You don’t have to inject the same tokens for every sandbox instance.</p>
            <pre><code> static outboundByHost = {
  "my-internal-vcs.dev": (request, env, ctx) =&gt; {
    // note: KV is encrypted at rest and in transit
    const authKey = await env.KEYS.get(ctx.containerId);

    const requestWithAuth = new Request(request);
    requestWithAuth.headers.set("x-auth-token", authKey);
    return fetch(requestWithAuth);
  }
}
</code></pre>
            
    <div>
      <h3>Using the Cloudflare Developer Platform</h3>
      <a href="#using-the-cloudflare-developer-platform">
        
      </a>
    </div>
    <p>As you may have noticed in the last example, another major advantage of using outbound Workers is that it makes integration into the Workers ecosystem easier. Previously, if a user wanted to access <a href="https://www.cloudflare.com/developer-platform/products/r2/"><u>R2</u></a>, they would have to inject an R2 credential, then make a call from their container to the public R2 API. Same for <a href="https://developers.cloudflare.com/kv/"><u>KV</u></a>, <a href="https://developers.cloudflare.com/agents/"><u>Agents</u></a>, other <a href="https://developers.cloudflare.com/containers/"><u>Containers</u></a>, other <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/"><u>Worker services</u></a>, <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/"><u>etc</u></a>.</p><p>Now, you just call <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/"><u>any binding</u></a> from your outbound Workers.</p>
            <pre><code>class MySandboxedApp extends Sandbox {
  static outboundByHost = {
    "my.kv": async (req, env, ctx) =&gt; {
      const key = keyFromReq(req);
      const myResult = await env.KV.get(key);
      return new Response(myResult);
    },
    "objects.cf": async (req, env, ctx) =&gt; {
      const prefix = ctx.containerId
      const path = pathFromRequest(req);
      const object = await env.R2.get(`${prefix}/${path}`);
      const myResult = await env.KV.get(key);
      return new Response(myResult);
    },
  };
}
</code></pre>
            <p>Rather than parsing tokens and setting up policies, we can easily conditionalize access with code and whatever logic we want. In the R2 example, we also were able to use the sandbox’s ID to further scope access with ease.</p>
    <div>
      <h3>Making controls dynamic</h3>
      <a href="#making-controls-dynamic">
        
      </a>
    </div>
    <p>Networking control should also be dynamic. On many platforms, config for Container and VM networking is static, looking something like this:</p>
            <pre><code>{
  defaultEgress: "block",
  allowedDomains: ["github.com", "npmjs.org"]
}
</code></pre>
            <p>This is better than nothing, but we can do better. For many sandboxes, we might want to apply a policy on start, but then override it with another once specific operations have been performed.</p><p>For instance, we can boot a sandbox, grab our dependencies via NPM and Github, and then lock down egress after that. This ensures that we open up the network for as little time as possible.</p><p>To achieve this, we can use <code>outboundHandlers</code>, which allows us to define arbitrary outbound handlers that can be applied programmatically using the <code>setOutboundHandler</code> method. Each of these also takes params, allowing you to customize behavior from code. In this case, we will allow some hostnames with the custom “<code>allowHosts</code>” policy, then turn off HTTP. </p>
            <pre><code>class MySandboxedApp extends Sandbox {
  static outboundHandlers = {
    async allowHosts(req, env, { params }) {
     const url = new URL(request.url);
     const allowedHostname = params.allowedHostnames.includes(url.hostname);

      if (allowedHostname) {
        return await fetch(newRequest);
      } else {
        return new Response(null, { status: 403, statusText: "Forbidden" });
      }
    }
    
    async noHttp(req) {
      return new Response(null, { status: 403, statusText: "Forbidden" });
    }
  }
}

async setUpSandboxes(req, env) {
  const sandbox = await env.SANDBOX.getByName(userId);
  await sandbox.setOutboundHandler("allowHosts", {
    allowedHostnames: ["github.com", "npmjs.org"]
  });
  await sandbox.gitClone(userRepoURL)
  await sandbox.exec("npm install")
  await sandbox.setOutboundHandler("noHttp");
}
</code></pre>
            <p>This could be extended even further. Your agent might ask the end user a question like “Do you want to allow POST requests to <code>cloudflare.com</code>?” based on whatever tools it needs at that time. With dynamic outbound Workers, you can easily modify the sandbox rules on the fly to provide this level of control.</p>
    <div>
      <h2>TLS support with MITM Proxying</h2>
      <a href="#tls-support-with-mitm-proxying">
        
      </a>
    </div>
    <p>To do anything useful with requests beyond allowing or denying them, you need to have access to the content. This means that if you’re making HTTPS requests, they need to be decrypted by the Workers proxy.</p><p>To achieve this, a unique ephemeral certificate authority (CA) and private key are created for each Sandbox instance, and the CA is placed into the sandbox. By default, sandbox instances will trust this CA, while standard container instances can opt into trusting it, for instance by calling <code>sudo update-ca-certificates</code>.</p>
            <pre><code>export class MyContainer extends Container {
  interceptHttps = true;
}

MyContainer.outbound = (req, env, ctx) =&gt; {
  // All HTTP(S) requests will trigger this hook.
  return fetch(req);
};

</code></pre>
            <p>TLS traffic is proxied by a Cloudflare isolated network process by performing a TLS handshake. It creates a leaf CA from an ephemeral and unique private key and uses the SNI extracted in the ClientHello. It will then invoke in the same machine the  configured Worker to handle the HTTPS request.</p><p>Our ephemeral private key and CA will never leave our container runtime sidecar process, and is never shared across other container sidecar processes.</p><p>With this in place, outbound Workers act as a truly transparent proxy. The sandbox doesn't need any awareness of specific protocols or domains — all HTTP and HTTPS traffic flows through the outbound handler for filtering or modification.</p>
    <div>
      <h2>Under the hood</h2>
      <a href="#under-the-hood">
        
      </a>
    </div>
    <p>To enable the functionality shown above in both <a href="https://github.com/cloudflare/containers"><code><u>Container</u></code></a> and <a href="https://github.com/cloudflare/sandbox-sdk"><code><u>Sandbox</u></code></a>, we added new methods to the <a href="https://developers.cloudflare.com/durable-objects/api/container/"><code><u>ctx.container</u></code></a> object: <code>interceptOutboundHttp and interceptOutboundHttps</code>, which intercept outgoing requests on specific hostnames (with basic glob matching), IP ranges, and it can be used to intercept all outbound requests. These methods are called with a <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/rpc/"><u>WorkerEntrypoint</u></a>, which gets set up as the front door to the outbound Worker.</p>
            <pre><code>export class MyWorker extends WorkerEntrypoint {
 fetch() {
   return new Response(this.ctx.props.message);
 }
}

// ... inside your container DurableObject ...
this.ctx.container.start({ enableInternet: false });
const outboundWorker = this.ctx.exports.MyWorker({ props: { message: 'hello' } });
await this.ctx.container.interceptOutboundHttp('15.0.0.1:80', outboundWorker);

// From now on, all HTTP requests to 15.0.0.1:80 return "hello"
await this.waitForContainerToBeHealthy();

// You can decide to return another message now...
const secondOutboundWorker = this.ctx.exports.MyWorker({ props: { message: 'switcheroo' } });
await this.ctx.container.interceptOutboundHttp('15.0.0.1:80', secondOutboundWorker);
// all HTTP requests to 15.0.0.1 now show "switcheroo", even on connections that were
// open before this interceptOutboundHttp

// You can even set hostnames, CIDRs, for both IPv4 and IPv6
await this.ctx.container.interceptOutboundHttp('example.com', secondOutboundWorker);
await this.ctx.container.interceptOutboundHttp('*.example.com', secondOutboundWorker);
await this.ctx.container.interceptOutboundHttp('123.123.123.123/23', secoundOutboundWorker);</code></pre>
            <p>All proxying to Workers happens locally on the same machine that runs the sandbox VM. Even though communication between container and Worker is “authless”, it is secure.</p><p>These methods can be called at any time, before or after starting the container, even while connections are still open. Connections that send multiple HTTP requests will automatically pick up a new entrypoint, so updating outbound Workers will not break existing TCP connections or interrupt HTTP requests.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/21utJcR5UpS7c0YNj8Y385/4a47d83acad42c5708ca23a7b04342f3/BLOG-3199_3.png" />
          </figure><p>Local development with <a href="https://developers.cloudflare.com/workers/wrangler/commands/#dev"><u>wrangler dev</u></a> also has support for egress interception. To make it possible, we automatically spawn a sidecar process inside the local container’s network namespace. We called this sidecar component <a href="https://github.com/cloudflare/proxy-everything"><i><u>proxy-everything</u></i></a>. Once <i>proxy-everything </i>is attached, it applies the appropriate TPROXY nftable rules, routing matching traffic from the local Container to <a href="https://github.com/cloudflare/workerd"><u>workerd</u></a>, Cloudflare’s open source JavaScript runtime, which runs the outbound Worker. This allows the local development experience to mirror what happens in prod, so testing and development remain simple.</p>
    <div>
      <h2>Giving outbound Workers a try</h2>
      <a href="#giving-outbound-workers-a-try">
        
      </a>
    </div>
    <p>If you haven’t tried Cloudflare Sandboxes, check out the <a href="https://developers.cloudflare.com/sandbox/get-started/"><u>Getting Started guide</u></a>. If you are a current user of <a href="https://developers.cloudflare.com/containers/"><u>Containers</u></a> or <a href="https://developers.cloudflare.com/sandbox/"><u>Sandboxes</u></a>, start using outbound Workers now by <a href="https://developers.cloudflare.com/containers/platform-details/outbound-traffic/"><u>reading the documentation</u></a> and upgrading to <code>@cloudflare/containers@0.3.0</code> or <code>@cloudflare/sandbox@0.8.9</code>.</p>
    <div>
      <h4>Watch on Cloudflare TV</h4>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div>  </div><p></p> ]]></content:encoded>
            <category><![CDATA[Containers]]></category>
            <category><![CDATA[Sandbox]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <guid isPermaLink="false">3j8ROSAUomMNPrmru3f2U9</guid>
            <dc:creator>Mike Nomitch</dc:creator>
            <dc:creator>Gabi Villalonga Simón</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Moltworker: a self-hosted personal AI agent, minus the minis]]></title>
            <link>https://blog.cloudflare.com/moltworker-self-hosted-ai-agent/</link>
            <pubDate>Thu, 29 Jan 2026 14:00:00 GMT</pubDate>
            <description><![CDATA[ Moltworker is a middleware Worker and adapted scripts that allows running OpenClaw (formerly Moltbot, formerly Clawdbot) on Cloudflare's Sandbox SDK and our Developer Platform APIs. So you can self-host an AI personal assistant — without any new hardware. ]]></description>
            <content:encoded><![CDATA[ <p><i></i></p><p><i>Editorial note: As of January 30, 2026, Moltbot has been </i><a href="https://openclaw.ai/blog/introducing-openclaw"><i><u>renamed</u></i></a><i> to OpenClaw.</i></p><p>The Internet woke up this week to a flood of people <a href="https://x.com/AlexFinn/status/2015133627043270750"><u>buying Mac minis</u></a> to run <a href="https://github.com/moltbot/moltbot"><u>Moltbot</u></a> (formerly Clawdbot), an open-source, self-hosted AI agent designed to act as a personal assistant. Moltbot runs in the background on a user's own hardware, has a sizable and growing list of integrations for chat applications, AI models, and other popular tools, and can be controlled remotely. Moltbot can help you with your finances, social media, organize your day — all through your favorite messaging app.</p><p>But what if you don’t want to buy new dedicated hardware? And what if you could still run your Moltbot efficiently and securely online? Meet <a href="https://github.com/cloudflare/moltworker"><u>Moltworker</u></a>, a middleware Worker and adapted scripts that allows running Moltbot on Cloudflare's Sandbox SDK and our Developer Platform APIs.</p>
    <div>
      <h2>A personal assistant on Cloudflare — how does that work? </h2>
      <a href="#a-personal-assistant-on-cloudflare-how-does-that-work">
        
      </a>
    </div>
    <p>Cloudflare Workers has never been <a href="https://developers.cloudflare.com/workers/runtime-apis/nodejs/"><u>as compatible</u></a> with Node.js as it is now. Where in the past we had to mock APIs to get some packages running, now those APIs are supported natively by the Workers Runtime.</p><p>This has changed how we can build tools on Cloudflare Workers. When we first implemented <a href="https://developers.cloudflare.com/browser-rendering/playwright/"><u>Playwright</u></a>, a popular framework for web testing and automation that runs on <a href="https://developers.cloudflare.com/browser-rendering/"><u>Browser Rendering</u></a>, we had to rely on <a href="https://www.npmjs.com/package/memfs"><u>memfs</u></a>. This was bad because not only is memfs a hack and an external dependency, but it also forced us to drift away from the official Playwright codebase. Thankfully, with more Node.js compatibility, we were able to start using <a href="https://github.com/cloudflare/playwright/pull/62/changes"><u>node:fs natively</u></a>, reducing complexity and maintainability, which makes upgrades to the latest versions of Playwright easy to do.</p><p>The list of Node.js APIs we support natively keeps growing. The blog post “<a href="https://blog.cloudflare.com/nodejs-workers-2025/"><u>A year of improving Node.js compatibility in Cloudflare Workers</u></a>” provides an overview of where we are and what we’re doing.</p><p>We measure this progress, too. We recently ran an experiment where we took the 1,000 most popular NPM packages, installed and let AI loose, to try to run them in Cloudflare Workers, <a href="https://ghuntley.com/ralph/"><u>Ralph Wiggum as a "software engineer"</u></a> style, and the results were surprisingly good. Excluding the packages that are build tools, CLI tools or browser-only and don’t apply, only 15 packages genuinely didn’t work. <b>That's 1.5%</b>.</p><p>Here’s a graphic of our Node.js API support over time:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5GhwKJq2A2wG79I3NdhhDl/e462c30daf46b1b36d3f06bff479596b/image9.png" />
          </figure><p>We put together a page with the results of our internal experiment on npm packages support <a href="https://worksonworkers.southpolesteve.workers.dev/"><u>here</u></a>, so you can check for yourself.</p><p>Moltbot doesn’t necessarily require a lot of Workers Node.js compatibility because most of the code runs in a container anyway, but we thought it would be important to highlight how far we got supporting so many packages using native APIs. This is because when starting a new AI agent application from scratch, we can actually run a lot of the logic in Workers, closer to the user.</p><p>The other important part of the story is that the list of <a href="https://developers.cloudflare.com/directory/?product-group=Developer+platform"><u>products and APIs</u></a> on our Developer Platform has grown to the point where anyone can <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">build and run any kind of application</a> — even the most complex and demanding ones — on Cloudflare. And once launched, every application running on our Developer Platform immediately benefits from our secure and scalable global network.</p><p>Those products and services gave us the ingredients we needed to get started. First, we now have <a href="https://sandbox.cloudflare.com/"><u>Sandboxes</u></a>, where you can run untrusted code securely in isolated environments, providing a place to run the service. Next, we now have <a href="https://developers.cloudflare.com/browser-rendering/"><u>Browser Rendering</u></a>, where you can programmatically control and interact with headless browser instances. And finally, <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a>, where you can store objects persistently. With those building blocks available, we could begin work on adapting Moltbot.</p>
    <div>
      <h2>How we adapted Moltbot to run on us</h2>
      <a href="#how-we-adapted-moltbot-to-run-on-us">
        
      </a>
    </div>
    <p>Moltbot on Workers, or Moltworker, is a combination of an entrypoint Worker that acts as an API router and a proxy between our APIs and the isolated environment, both protected by Cloudflare Access. It also provides an administration UI and connects to the Sandbox container where the standard Moltbot Gateway runtime and its integrations are running, using R2 for persistent storage.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3OD2oHgy5ilHpQO2GJvcLU/836a55b67a626d2cd378a654ad47901d/newdiagram.png" />
          </figure><p><sup>High-level architecture diagram of Moltworker.</sup></p><p>Let's dive in more.</p>
    <div>
      <h3>AI Gateway</h3>
      <a href="#ai-gateway">
        
      </a>
    </div>
    <p>Cloudflare AI Gateway acts as a proxy between your AI applications and any popular <a href="https://developers.cloudflare.com/ai-gateway/usage/providers/"><u>AI provider</u></a>, and gives our customers centralized visibility and control over the requests going through.</p><p>Recently we announced support for <a href="https://developers.cloudflare.com/changelog/2025-08-25-secrets-store-ai-gateway/"><u>Bring Your Own Key (BYOK)</u></a>, where instead of passing your provider secrets in plain text with every request, we centrally manage the secrets for you and can use them with your gateway configuration.</p><p>An even better option where you don’t have to manage AI providers' secrets at all end-to-end is to use <a href="https://developers.cloudflare.com/ai-gateway/features/unified-billing/"><u>Unified Billing</u></a>. In this case you top up your account with credits and use AI Gateway with any of the supported providers directly, Cloudflare gets charged, and we will deduct credits from your account.</p><p>To make Moltbot use AI Gateway, first we create a new gateway instance, then we enable the Anthropic provider for it, then we either add our Claude key or purchase credits to use Unified Billing, and then all we need to do is set the ANTHROPIC_BASE_URL environment variable so Moltbot uses the AI Gateway endpoint. That’s it, no code changes necessary.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/cMWRXgHR0mFLc5kp74nYk/a47fa09bdbb6acb3deb60fb16537945d/image11.png" />
          </figure><p>Once Moltbot starts using AI Gateway, you’ll have full visibility on costs and have access to logs and analytics that will help you understand how your AI agent is using the AI providers.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5GOrNdgtdwMcU4bE8oLE19/6bc29bcac643125f5332a8ffba9d1322/image1.png" />
          </figure><p>Note that Anthropic is one option; Moltbot supports <a href="https://www.molt.bot/integrations"><u>other</u></a> AI providers and so does <a href="https://developers.cloudflare.com/ai-gateway/usage/providers/"><u>AI Gateway</u></a>. The advantage of using AI Gateway is that if a better model comes along from any provider, you don’t have to swap keys in your AI Agent configuration and redeploy — you can simply switch the model in your gateway configuration. And more, you specify model or provider <a href="https://developers.cloudflare.com/ai-gateway/configuration/fallbacks/"><u>fallbacks</u></a> to handle request failures and ensure reliability.</p>
    <div>
      <h3>Sandboxes</h3>
      <a href="#sandboxes">
        
      </a>
    </div>
    <p>Last year we anticipated the growing need for AI agents to run untrusted code securely in isolated environments, and we <a href="https://developers.cloudflare.com/changelog/2025-06-24-announcing-sandboxes/"><u>announced</u></a> the <a href="https://developers.cloudflare.com/sandbox/"><u>Sandbox SDK</u></a>. This SDK is built on top of <a href="https://developers.cloudflare.com/containers/"><u>Cloudflare Containers</u></a>, but it provides a simple API for executing commands, managing files, running background processes, and exposing services — all from your Workers applications.</p><p>In short, instead of having to deal with the lower-level Container APIs, the Sandbox SDK gives you developer-friendly APIs for secure code execution and handles the complexity of container lifecycle, networking, file systems, and process management — letting you focus on building your application logic with just a few lines of TypeScript. Here’s an example:</p>
            <pre><code>import { getSandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';

export default {
  async fetch(request: Request, env: Env): Promise&lt;Response&gt; {
    const sandbox = getSandbox(env.Sandbox, 'user-123');

    // Create a project structure
    await sandbox.mkdir('/workspace/project/src', { recursive: true });

    // Check node version
    const version = await sandbox.exec('node -v');

    // Run some python code
    const ctx = await sandbox.createCodeContext({ language: 'python' });
    await sandbox.runCode('import math; radius = 5', { context: ctx });
    const result = await sandbox.runCode('math.pi * radius ** 2', { context: ctx });

    return Response.json({ version, result });
  }
};</code></pre>
            <p>This fits like a glove for Moltbot. Instead of running Docker in your local Mac mini, we run Docker on Containers, use the Sandbox SDK to issue commands into the isolated environment and use callbacks to our entrypoint Worker, effectively establishing a two-way communication channel between the two systems.</p>
    <div>
      <h3>R2 for persistent storage</h3>
      <a href="#r2-for-persistent-storage">
        
      </a>
    </div>
    <p>The good thing about running things in your local computer or VPS is you get persistent storage for free. Containers, however, are inherently <a href="https://developers.cloudflare.com/containers/platform-details/architecture/"><u>ephemeral</u></a>, meaning data generated within them is lost upon deletion. Fear not, though — the Sandbox SDK provides the sandbox.mountBucket() that you can use to automatically, well, mount your R2 bucket as a filesystem partition when the container starts.</p><p>Once we have a local directory that is guaranteed to survive the container lifecycle, we can use that for Moltbot to store session memory files, conversations and other assets that are required to persist.</p>
    <div>
      <h3>Browser Rendering for browser automation</h3>
      <a href="#browser-rendering-for-browser-automation">
        
      </a>
    </div>
    <p>AI agents rely heavily on browsing the sometimes not-so-structured web. Moltbot utilizes dedicated Chromium instances to perform actions, navigate the web, fill out forms, take snapshots, and handle tasks that require a web browser. Sure, we can run Chromium on Sandboxes too, but what if we could simplify and use an API instead?</p><p>With Cloudflare’s <a href="https://developers.cloudflare.com/browser-rendering/"><u>Browser Rendering</u></a>, you can programmatically control and interact with headless browser instances running at scale in our edge network. We support <a href="https://developers.cloudflare.com/browser-rendering/puppeteer/"><u>Puppeteer</u></a>, <a href="https://developers.cloudflare.com/browser-rendering/stagehand/"><u>Stagehand</u></a>, <a href="https://developers.cloudflare.com/browser-rendering/playwright/"><u>Playwright</u></a> and other popular packages so that developers can onboard with minimal code changes. We even support <a href="https://developers.cloudflare.com/browser-rendering/playwright/playwright-mcp/"><u>MCP</u></a> for AI.</p><p>In order to get Browser Rendering to work with Moltbot we do two things:</p><ul><li><p>First we create a <a href="https://github.com/cloudflare/moltworker/blob/main/src/routes/cdp.ts"><u>thin CDP proxy</u></a> (<a href="https://chromedevtools.github.io/devtools-protocol/"><u>CDP</u></a> is the protocol that allows instrumenting Chromium-based browsers) from the Sandbox container to the Moltbot Worker, back to Browser Rendering using the Puppeteer APIs.</p></li><li><p>Then we inject a <a href="https://github.com/cloudflare/moltworker/pull/20"><u>Browser Rendering skill</u></a> into the runtime when the Sandbox starts.</p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1ZvQa7vS1T9Mm3nywqarQZ/9dec3d8d06870ee575a519440d34c499/image12.png" />
          </figure><p>From the Moltbot runtime perspective, it has a local CDP port it can connect to and perform browser tasks.</p>
    <div>
      <h3>Zero Trust Access for authentication policies</h3>
      <a href="#zero-trust-access-for-authentication-policies">
        
      </a>
    </div>
    <p>Next up we want to protect our APIs and Admin UI from unauthorized access. Doing authentication from scratch is hard, and is typically the kind of wheel you don’t want to reinvent or have to deal with. Zero Trust Access makes it incredibly easy to protect your application by defining specific policies and login methods for the endpoints. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1MDXXjbMs4PViN3kp9iFBY/a3095f07c986594d0c07d0276dbf22cc/image3.png" />
          </figure><p><sup>Zero Trust Access Login methods configuration for the Moltworker application.</sup></p><p>Once the endpoints are protected, Cloudflare will handle authentication for you and automatically include a <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/application-token/"><u>JWT token</u></a> with every request to your origin endpoints. You can then <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/validating-json/"><u>validate</u></a> that JWT for extra protection, to ensure that the request came from Access and not a malicious third party.</p><p>Like with AI Gateway, once all your APIs are behind Access you get great observability on who the users are and what they are doing with your Moltbot instance.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3BV4eqxKPXTiq18vvVpmZh/e034b7e7ea637a00c73c2ebe4d1400aa/image8.png" />
          </figure>
    <div>
      <h2>Moltworker in action</h2>
      <a href="#moltworker-in-action">
        
      </a>
    </div>
    <p>Demo time. We’ve put up a Slack instance where we could play with our own instance of Moltbot on Workers. Here are some of the fun things we’ve done with it.</p><p>We hate bad news.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4FxN935AgINZ8953WSswKB/e52d3eb268aa0732c5e6aa64a8e2adba/image6.png" />
          </figure><p>Here’s a chat session where we ask Moltbot to find the shortest route between Cloudflare in London and Cloudflare in Lisbon using Google Maps and take a screenshot in a Slack channel. It goes through a sequence of steps using Browser Rendering to navigate Google Maps and does a pretty good job at it. Also look at Moltbot’s memory in action when we ask him the second time.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1phWt3cVUwxe9tvCYpuAW3/97f456094ede6ca8fb55bf0dddf65d5b/image10.png" />
          </figure><p>We’re in the mood for some Asian food today, let’s get Moltbot to work for help.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6nJY7GOCopGnMy4IY7KMcf/0d57794df524780c3f4b27e65c968e19/image5.png" />
          </figure><p>We eat with our eyes too.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5BzB9pqJhuevRbOSJloeG0/23c2905f0c12c1e7f104aa28fcc1f595/image7.png" />
          </figure><p>Let’s get more creative and ask Moltbot to create a video where it browses our developer documentation. As you can see, it downloads and runs ffmpeg to generate the video out of the frames it captured in the browser.</p><div>
  
</div>
    <div>
      <h2>Run your own Moltworker</h2>
      <a href="#run-your-own-moltworker">
        
      </a>
    </div>
    <p>We open-sourced our implementation and made it available at<a href="https://github.com/cloudflare/moltworker"> <u>https://github.com/cloudflare/moltworker</u></a>, so you can deploy and run your own Moltbot on top of Workers today.</p><p>The <a href="https://github.com/cloudflare/moltworker/blob/main/README.md">README</a> guides you through the necessary setup steps. You will need a Cloudflare account and a <a href="https://developers.cloudflare.com/workers/platform/pricing/"><u>Workers Paid plan</u></a> to access Sandbox Containers; however, all other products are either entirely free (like <a href="https://developers.cloudflare.com/ai-gateway/reference/pricing/"><u>AI Gateway</u></a>) or include generous <a href="https://developers.cloudflare.com/r2/pricing/#free-tier"><u>free tiers </u></a>that allow you to get started and scale under reasonable limits.</p><p><b>Note that Moltworker is a proof of concept, not a Cloudflare product</b>. Our goal is to showcase some of the most exciting features of our <a href="https://developers.cloudflare.com/learning-paths/workers/devplat/intro-to-devplat/">Developer Platform</a> that can be used to run AI agents and unsupervised code efficiently and securely, and get great observability while taking advantage of our global network.</p><p>Feel free to contribute to or fork our <a href="https://github.com/cloudflare/moltworker"><u>GitHub</u></a> repository; we will keep an eye on it for a while for support. We are also considering contributing upstream to the official project with Cloudflare skills in parallel.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We hope you enjoyed this experiment, and we were able to convince you that Cloudflare is the perfect place to run your AI applications and agents. We’ve been working relentlessly trying to anticipate the future and release features like the <a href="https://developers.cloudflare.com/agents/"><u>Agents SDK</u></a> that you can use to build your first agent <a href="https://developers.cloudflare.com/agents/guides/slack-agent/"><u>in minutes</u></a>, <a href="https://developers.cloudflare.com/sandbox/"><u>Sandboxes</u></a> where you can run arbitrary code in an isolated environment without the complications of the lifecycle of a container, and <a href="https://developers.cloudflare.com/ai-search/"><u>AI Search</u></a>, Cloudflare’s managed vector-based search service, to name a few.</p><p>Cloudflare now offers a complete toolkit for AI development: inference, storage APIs, databases, durable execution for stateful workflows, and built-in AI capabilities. Together, these building blocks make it possible to build and run even the most demanding AI applications on our global edge network.</p><p>If you're excited about AI and want to help us build the next generation of products and APIs, we're <a href="https://www.cloudflare.com/en-gb/careers/jobs/?department=Engineering"><u>hiring</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Containers]]></category>
            <category><![CDATA[Sandbox]]></category>
            <guid isPermaLink="false">45LuZGCXAcs7EMnB64zTQm</guid>
            <dc:creator>Celso Martinho</dc:creator>
            <dc:creator>Brian Brunner</dc:creator>
            <dc:creator>Sid Chatterjee</dc:creator>
            <dc:creator>Andreas Jansson</dc:creator>
        </item>
        <item>
            <title><![CDATA[Deploy your own AI vibe coding platform — in one click! ]]></title>
            <link>https://blog.cloudflare.com/deploy-your-own-ai-vibe-coding-platform/</link>
            <pubDate>Tue, 23 Sep 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Introducing VibeSDK, an open-source AI "vibe coding" platform that anyone can deploy to build their own custom platform. Comes ready with code generation, sandbox environment, and project deployment.  ]]></description>
            <content:encoded><![CDATA[ <p>It’s an exciting time to build applications. With the recent AI-powered <a href="https://www.cloudflare.com/learning/ai/ai-vibe-coding/"><u>"vibe coding"</u></a> boom, anyone can build a website or application by simply describing what they want in a few sentences. We’re already seeing organizations expose this functionality to both their users and internal employees, empowering anyone to build out what they need.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/40Jzjser2hE91b1y3p80pm/7bc1a7f0ee4cfaeb7a39bb413969b189/1.png" />
          </figure><p>Today, we’re excited to open-source an AI vibe coding platform, VibeSDK, to enable anyone to run an entire vibe coding platform themselves, end-to-end, with just one click.</p><p>Want to see it for yourself? Check out our <a href="https://build.cloudflare.dev/"><u>demo platform</u></a> that you can use to create and deploy applications. Or better yet, click the button below to deploy your own AI-powered platform, and dive into the repo to learn about how it’s built.</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/vibesdk"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Deploying VibeSDK sets up everything you need to run your own AI-powered development platform:</p><ul><li><p><b>Integration with LLM models</b> to generate code, build applications, debug errors, and iterate in real-time, powered by <a href="https://developers.cloudflare.com/agents/"><u>Agents SDK</u></a>. </p></li><li><p><b>Isolated development environments </b>that allow users to safely build and preview their applications in secure sandboxes.</p></li><li><p><b>Infinite scale</b> that allows you to deploy thousands or even millions of applications that end users deploy, all served on Cloudflare’s global network</p></li><li><p><b>Observability and caching</b> across multiple AI providers, giving you <a href="https://www.cloudflare.com/learning/performance/what-is-observability/">insight into costs and performance</a> with built-in caching for popular responses. </p></li><li><p><b>Project templates</b> that the LLM can use as a starting point to build common applications and speed up development.</p></li><li><p><b>One-click project export</b> to the user’s Cloudflare account or GitHub repo, so users can take their code and continue development on their own.</p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3jsExecZKmgJHARsxDsMkM/60803b1ba2c68514a053f4d000bf8576/2.png" />
          </figure><p><b>Building an AI vibe coding platform from start to finish</b></p><p><b>Step 0: Get started immediately with VibeSDK</b></p><p>We’re seeing companies build their own AI vibe coding platforms to enable both internal and external users. With a vibe coding platform, internal teams like marketing, product, and support can build their own landing pages, prototypes, or internal tools without having to rely on the engineering team. Similarly, SaaS companies can embed this capability into their product to allow users to build their own customizations. </p><p>Every platform has unique requirements and specializations. By <a href="https://www.cloudflare.com/learning/ai/how-to-get-started-with-vibe-coding/">building your own</a>, you can write custom logic to prompt LLMs for your specific needs, giving your users more relevant results. This also grants you complete control over the development environment and <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">application hosting</a>, giving you a secure platform that keeps your data private and within your control. </p><p>We wanted to make it easy for anyone to build this themselves, which is why we built a complete platform that comes with project templates, previews, and project deployment. Developers can repurpose the whole platform, or simply take the components they need and customize them to fit their needs.</p><p><b>Step 1: Finding a safe, isolated environment for running untrusted, AI generated code</b></p><p>AI can now build entire applications, but there's a catch: you need somewhere safe to run this untrusted, AI-generated code. Imagine if an <a href="https://www.cloudflare.com/learning/ai/what-is-large-language-model/"><u>LLM</u></a> writes an application that needs to install packages, run build commands, and start a development server — you can't just run this directly on your infrastructure where it might affect other users or systems.</p><p>With <a href="https://developers.cloudflare.com/changelog/2025-06-24-announcing-sandboxes/"><u>Cloudflare Sandboxes</u></a>, you don't have to worry about this. Every user gets their own isolated environment where the AI-generated code can do anything a normal development environment can do: install npm packages, run builds, start servers, but it's fully contained in a secure, container-based environment that can't affect anything outside its sandbox. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1AVtsIotiISgrjspHaRLsg/6cd2e56d5edb7021d63c01183362aafe/3.png" />
          </figure><p>The platform assigns each user to their own sandbox based on their session, so that if a user comes back, they can continue to access the same container with their files intact:</p>
            <pre><code>// Creating a sandbox client for a user session
const sandbox = getSandbox(env.Sandbox, sandboxId);

// Now AI can safely write and execute code in this isolated environment
await sandbox.writeFile('app.js', aiGeneratedCode);
await sandbox.exec('npm install express');
await sandbox.exec('node app.js');</code></pre>
            <p><b>Step 2: Generating the code</b></p><p>Once the sandbox is created, you have a development environment that can bring the code to life. VibeSDK orchestrates the whole workflow from writing the code, installing the necessary packages, and starting the development server. If you ask it to build a to-do app, it will generate the React application, write the component files, run <code>bun install</code> to get the dependencies, and start the server, so you can see the end result. </p><p>Once the user submits their request, the AI will generate all the necessary files, whether it's a React app, Node.js API, or full-stack application, and write them directly to the sandbox:</p>
            <pre><code>async function generateAndWriteCode(instanceId: string) {
    // AI generates the application structure
    const aiGeneratedFiles = await callAIModel("Create a React todo app");
    
    // Write all generated files to the sandbox
    for (const file of aiGeneratedFiles) {
        await sandbox.writeFile(
            `${instanceId}/${file.path}`,
            file.content
        );
        // User sees: "✓ Created src/App.tsx"
        notifyUser(`✓ Created ${file.path}`);
    }
}</code></pre>
            <p>To speed this up even more, we’ve provided a set of templates, stored in an <a href="https://www.cloudflare.com/developer-platform/products/r2/"><u>R2 bucket</u></a>, that the platform can use and quickly customize, instead of generating every file from scratch. This is just an initial set, but you can expand it and add more examples. </p><p><b>Step 3: Getting a preview of your deployment</b></p><p>Once everything is ready, the platform starts the development server and uses the Sandbox SDK to expose it to the internet with a public preview URL which allows users to instantly see their AI-generated application running live:</p>
            <pre><code>// Start the development server in the sandbox
const processId = await sandbox.startProcess(
    `bun run dev`, 
    { cwd: instanceId }
);

// Create a public preview URL 
const preview = await sandbox.exposePort(3000, { 
    hostname: 'preview.example.com' 
});

// User instantly gets: "https://my-app-xyz.preview.example.com"
notifyUser(`✓ Preview ready at: ${preview.url}`);</code></pre>
            <p><b>Step 4: Test, log, fix, repeat</b></p><p>But that’s not all! Throughout this process, the platform will capture console output, build logs, and error messages and feed them back to the LLM for automatic fixes. As the platform makes any updates or fixes, the user can see it all happening live — the file editing, installation progress, and error resolution. </p><p>Deploying applications: From Sandbox to Region Earth</p><p>Once the application is developed, it needs to be deployed. The platform packages everything in the sandbox and then uses a separate specialized "deployment sandbox" to deploy the application to <a href="https://www.cloudflare.com/developer-platform/products/workers/"><u>Cloudflare Workers</u></a>. This deployment sandbox runs <code>wrangler deploy</code> inside the secure environment to publish the application to Cloudflare's global network. </p><p>Since the platform may deploy up to thousands or millions of applications, Workers for Platforms is used to deploy the Workers at scale. Although all the Workers are deployed to the same Namespace, they are all isolated from one another by default, ensuring there’s no cross-tenant access. Once deployed, each application receives its own isolated Worker instance with a unique public URL like <code>my-app.vibe-build.example.com</code>. </p>
            <pre><code>async function deployToWorkersForPlatforms(instanceId: string) {
    // 1. Package the app from development sandbox
    const devSandbox = getSandbox(env.Sandbox, instanceId);
    const packagedApp = await devSandbox.exec('zip -r app.zip .');
    
    // 2. Transfer to specialized deployment sandbox
    const deploymentSandbox = getSandbox(env.DeployerServiceObject, 'deployer');
    await deploymentSandbox.writeFile('app.zip', packagedApp);
    await deploymentSandbox.exec('unzip app.zip');
    
    // 3. Deploy using Workers for Platforms dispatch namespace
    const deployResult = await deploymentSandbox.exec(`
        bunx wrangler deploy \\\\
        --dispatch-namespace vibe-sdk-build-default-namespace
    `);
    
    // Each app gets its own isolated Worker and unique URL
    // e.g., https://my-app.example.com
    return `https://${instanceId}.example.com`;
}</code></pre>
            <p><b>Exportable Applications </b></p><p>The platform also allows users to export their application to their own Cloudflare account and GitHub repo, so they can continue the development on their own. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3itKLSmnTzk2NapoaDQG6e/a0aba26f83cb01db5bd7957a8dfe18f4/Screenshot_2025-09-23_at_9.22.28%C3%A2__AM.png" />
          </figure><p>Observability, caching, and multi-model support built in! </p><p>It's no secret that LLM models have their specialties, which means that when building an AI-powered platform, you may end up using a few different models for different operations. By default, VibeSDK leverages Google’s Gemini models (gemini-2.5-pro, gemini-2.5-flash-lite, gemini-2.5-flash) for project planning, code generation, and debugging. </p><p>VibeSDK is automatically set up with <a href="https://www.cloudflare.com/developer-platform/products/ai-gateway/"><u>AI Gateway</u></a>, so that by default, the platform is able to:</p><ul><li><p>Use a unified access point to <a href="https://blog.cloudflare.com/ai-gateway-aug-2025-refresh/"><u>route requests across LLM providers</u></a>, allowing you to use models from a range of providers (OpenAI, Anthropic, Google, and others)</p></li><li><p>Cache popular responses, so when someone asks to "build a to-do list app", the gateway can serve a cached response instead of going to the provider (saving inference costs)</p></li><li><p>Get observability into the requests, tokens used, and response times across all providers in one place</p></li><li><p>Track costs across models and integrations</p></li></ul><p>Open sourced, so you can build your own Platform! </p><p>We're open-sourcing VibeSDK for the same reason Cloudflare open-sourced the Workers runtime — we believe the best development happens in the open. That's why we wanted to make it as easy as possible for anyone to build their own AI coding platform, whether it's for internal company use, for your website builder, or for the next big vibe coding platform. We tied all the pieces together for you, so you can get started with the click of a button instead of spending months figuring out how to connect everything yourself. To learn more, check out our <a href="https://developers.cloudflare.com/reference-architecture/diagrams/ai/ai-vibe-coding-platform/"><u>reference architecture</u></a> for vibe coding platforms. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/vibesdk"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2sjy1OUciwTKnKmhXJfbLQ/d0e01bee3867d639077f134fc6374948/5.png" />
          </figure><div>
  
</div><p></p> ]]></content:encoded>
            <category><![CDATA[AI Week]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Containers]]></category>
            <category><![CDATA[Cloudflare for SaaS]]></category>
            <guid isPermaLink="false">6hS4bQv1FRDVwOoB1HrU3u</guid>
            <dc:creator>Ashish Kumar Singh</dc:creator>
            <dc:creator>Abhishek Kankani</dc:creator>
            <dc:creator>Dina Kozlov</dc:creator>
        </item>
        <item>
            <title><![CDATA[Partnering with OpenAI to bring their new open models onto Cloudflare Workers AI]]></title>
            <link>https://blog.cloudflare.com/openai-gpt-oss-on-workers-ai/</link>
            <pubDate>Tue, 05 Aug 2025 21:05:00 GMT</pubDate>
            <description><![CDATA[ OpenAI’s newest open-source models are now available on Cloudflare Workers AI on Day 0, with support for Responses API, Code Interpreter and Web Search (coming soon). ]]></description>
            <content:encoded><![CDATA[ <p>OpenAI has just <a href="http://openai.com/index/introducing-gpt-oss"><u>announced their latest open-weight models</u></a> — and we are excited to share that we are working with them as a Day 0 launch partner to make these models available in Cloudflare's <a href="https://www.cloudflare.com/developer-platform/products/workers-ai/">Workers AI</a>. Cloudflare developers can now access OpenAI's first open model, leveraging these powerful new capabilities on our platform. The new models are available starting today at <code>@cf/openai/gpt-oss-120b</code> and <code>@cf/openai/gpt-oss-20b</code>.</p><p>Workers AI has always been a champion for open models and we’re thrilled to bring OpenAI's new open models to our platform today. Developers who want transparency, customizability, and deployment flexibility can rely on Workers AI as a place to deliver AI services. Enterprises that need the ability to run open models to ensure complete data security and privacy can also deploy with Workers AI. We are excited to join OpenAI in fulfilling their mission of making the benefits of AI broadly accessible to builders of any size.</p>
    <div>
      <h3>The technical model specs</h3>
      <a href="#the-technical-model-specs">
        
      </a>
    </div>
    <p>The <a href="https://openai.com/index/gpt-oss-model-card/"><u>OpenAI models</u></a> have been released in two sizes: a 120 billion parameter model and a 20 billion parameter model. Both of them are Mixture-of-Experts models – a popular architecture for recent model releases – that allow relevant experts to be called for a query instead of running through all the parameters of the model. Interestingly, these models run natively at an FP4 quantization, which means that they have a smaller GPU memory footprint than a 120 billion parameter model at FP16. Given the <a href="https://www.cloudflare.com/learning/ai/what-is-quantization/">quantization</a> and the MoE architecture, the new models are able to run faster and more efficiently than more traditional dense models of that size.</p><p>These models are text-only; however, they have reasoning capabilities, tool calling, and two new exciting features with Code Interpreter and Web Search (support coming soon). We’ve implemented Code Interpreter on top of <a href="https://blog.cloudflare.com/containers-are-available-in-public-beta-for-simple-global-and-programmable/"><u>Cloudflare Containers</u></a> in a novel way that allows for stateful code execution (read on below).</p>
    <div>
      <h3>The model on Workers AI</h3>
      <a href="#the-model-on-workers-ai">
        
      </a>
    </div>
    <p>We’re landing these new models with a few tweaks: supporting the new <a href="https://platform.openai.com/docs/api-reference/responses"><u>Responses API</u></a> format as well as the historical <a href="https://platform.openai.com/docs/guides/text?api-mode=chat"><u>Chat Completions API</u></a> format (coming soon). The Responses API format is recommended by OpenAI to interact with their models, and we’re excited to support that on Workers AI.</p><p>If you call the model through:</p><ul><li><p>Workers Binding, it will accept/return Responses API – <code>env.AI.run(“@cf/openai/gpt-oss-120b”)</code></p></li><li><p>REST API on /run endpoint, it will accept/return Responses API – <code>https://api.cloudflare.com/client/v4/accounts/&lt;account_id&gt;/ai/run/@cf/openai/gpt-oss-120b</code></p></li><li><p>REST API on new /responses endpoint, it will accept/return Responses API – <code>https://api.cloudflare.com/client/v4/accounts/&lt;account_id&gt;/ai/v1</code><code><b>/responses</b></code></p></li><li><p>REST API for OpenAI Compatible endpoint, it will return Chat Completions (coming soon)– <code>https://api.cloudflare.com/client/v4/accounts/&lt;account_id&gt;/ai/v1/chat/completions</code></p></li></ul>
            <pre><code>curl https://api.cloudflare.com/client/v4/accounts/&lt;account_id&gt;/ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $CLOUDFLARE_API_KEY" \
  -d '{
    "model": "@cf/openai/gpt-oss-120b",
    "reasoning": {"effort": "medium"},
    "input": [
      {
        "role": "user",
        "content": "What are the benefits of open-source models?"
      }
    ]
  }'
</code></pre>
            
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6eUpzGy6RKcoPXd9MPBFSk/89d18f2535427cdb564426a4b33f9d4d/image1.png" />
          </figure>
    <div>
      <h3>Code Interpreter + Cloudflare Sandboxes = the perfect fit</h3>
      <a href="#code-interpreter-cloudflare-sandboxes-the-perfect-fit">
        
      </a>
    </div>
    <p>To effectively answer user queries, <a href="https://www.cloudflare.com/learning/ai/what-is-large-language-model/">Large Language Models (LLMs)</a> often struggle with logical tasks such as mathematics or coding. Instead of attempting to reason through these problems, LLMs typically utilize a tool call to execute AI-generated code that solves these problems. OpenAI's new models are specifically trained for stateful Python code execution and include a built-in feature called Code Interpreter, designed to address this challenge.</p><p>We’re particularly excited about this. Cloudflare not only has an inference platform (<a href="https://developers.cloudflare.com/workers-ai"><u>Workers AI</u></a>), but we also have an ecosystem of compute and storage products that allow people to build full applications on top of our <a href="https://www.cloudflare.com/developer-platform/">Developer Platform</a>. This means that we are uniquely suited to support the model’s Code Interpreter capabilities, not only for one-time code execution, but for <i>stateful </i>code execution as well.</p><p>We’ve built support for Code Interpreter on top of Cloudflare’s <a href="https://developers.cloudflare.com/changelog/2025-06-24-announcing-sandboxes/"><u>Sandbox</u></a> product that allows for a secure environment to run AI-generated code. The <a href="https://github.com/cloudflare/sandbox-sdk"><u>Sandbox SDK</u></a> is built on our latest <a href="https://blog.cloudflare.com/containers-are-available-in-public-beta-for-simple-global-and-programmable/"><u>Containers</u></a> product and Code Interpreter is the perfect use case to bring all these products together. When you use Code Interpreter, we spin up a Sandbox container scoped to your session that stays alive for 20 minutes, so the code can be edited for subsequent queries to the model. We’ve also pre-warmed Sandboxes for Code Interpreter to ensure the fastest start up times.</p><p>We’ll be publishing an example of how you can use the gpt-oss model on Workers AI and Sandboxes with the OpenAI SDK to make calls to Code Interpreter on our <a href="https://developers.cloudflare.com/workers-ai/guides/demos-architectures/"><u>Developer Docs</u></a>.</p>
    <div>
      <h3>Give it a try!</h3>
      <a href="#give-it-a-try">
        
      </a>
    </div>
    <p>We’re beyond excited for OpenAI’s new open models, and we hope you are too. Super grateful to our friends from <a href="https://docs.vllm.ai/en/latest/index.html"><u>vLLM</u></a> and <a href="https://huggingface.co/"><u>HuggingFace</u></a> for supporting efficient model serving on launch day. Read up on the <a href="https://developers.cloudflare.com/workers-ai/models/gpt-oss-120b"><u>Developer Docs</u></a> to learn more about the details and how to get started on building with these new models and capabilities.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4D11uWyDAooDrElGBVcL8f/568d689efc4e9ef56fe7c0eff0dc9d17/image3.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Containers]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">1VV6tpMJn0Te7WEzn2BjSR</guid>
            <dc:creator>Michelle Chen</dc:creator>
            <dc:creator>Ashish Datta</dc:creator>
        </item>
        <item>
            <title><![CDATA[Containers are available in public beta for simple, global, and programmable compute]]></title>
            <link>https://blog.cloudflare.com/containers-are-available-in-public-beta-for-simple-global-and-programmable/</link>
            <pubDate>Tue, 24 Jun 2025 16:00:22 GMT</pubDate>
            <description><![CDATA[ Cloudflare Containers are now available in public beta. Deploy simple, global, and programmable containers alongside your Workers.  ]]></description>
            <content:encoded><![CDATA[ <p>We’re excited to announce that <a href="https://blog.cloudflare.com/cloudflare-containers-coming-2025/"><u>Cloudflare Containers</u></a> are now available in beta for all users on paid plans.</p><p>You can now run new kinds of applications alongside your Workers. From media and data processing at the edge, to backend services in any language, to CLI tools in batch workloads — Containers open up a world of possibilities.</p><p>Containers are tightly integrated with Workers and the rest of the developer platform, which means that:</p><ul><li><p>Your workflow stays <b>simple</b>: just define a Container in a few lines of code, and run<code> wrangler deploy</code>, just like you would with a Worker.</p></li><li><p>Containers are <b>global: </b>as with Workers, you just deploy to Region:Earth. No need to manage configs across 5 different regions for a global app.</p></li><li><p>You can <b>use the right tool for the job</b>: routing requests between Workers and Containers is easy. Use a Worker when you need to be ultra light-weight and scalable. Use a Container when you need more power and flexibility.</p></li><li><p>Containers are <b>programmable</b>: container instances are spun up on-demand and controlled by Workers code. If you need custom logic, just write some JavaScript instead of spending time chaining together API calls or writing Kubernetes operators.</p></li></ul><p>Want to try it today? Deploy your first Container-enabled Worker:</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/containers-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
    <div>
      <h2>A tour of Containers</h2>
      <a href="#a-tour-of-containers">
        
      </a>
    </div>
    <p>Let’s take a deeper look at Containers, using an example use case: code sandboxing.</p><p>Let’s imagine that you want to run user-generated (or AI-generated) code as part of a platform you’re building. To do this, you want to spin up containers on demand. Each user needs their own isolated container, the users are distributed globally, and you need to start each container quickly so the users aren’t waiting.</p><p>You can set this up easily on Cloudflare Containers.</p>
    <div>
      <h4>Configuring a Container</h4>
      <a href="#configuring-a-container">
        
      </a>
    </div>
    <p>In your Worker, use the <a href="https://github.com/cloudflare/containers"><u>Container class</u></a> and <a href="https://developers.cloudflare.com//workers/wrangler/configuration/#containers"><u>wrangler.jsonc</u></a> to declare some basic configuration, such as your Container’s default port, a sleep timeout, and which image to use, then route to it via the Worker.</p><p>For each unique ID passed to the Container’s binding, Cloudflare will spin up a new Container instance and route requests to it. When a new instance is requested, Cloudflare picks the best location across our global network where we’ve pre-provisioned a ready-to-go container. This means that you can deploy a container close to an end user no matter where they are. And the initial container start takes just a few seconds. You don’t have to worry about routing, provisioning, or scaling.</p><p>This example Worker will route requests to a unique container instance for each sandbox ID given at the path <code>/sandbox/ID</code> and will be handled by standard Worker JavaScript otherwise:</p>
            <pre><code>export class MyContainer extends Container {
  defaultPort = 8080; // The default port for the container to listen on
  sleepAfter = '5m'; // Sleep the container if no requests are made in this timeframe
}

export default {
  async fetch(request, env) {
    const pathname = new URL(request.url).pathname;

    // handle request with an on-demand container instance
    if (pathname.startsWith('/sandbox/')) {
      const sessionId = pathname.split("/")[2]
      const containerInstance = getContainer(env.CONTAINER_SANDBOX, sessionId)
      return await containerInstance.fetch(request);
    }

    // handle request with my Worker code otherwise
    return myWorkerRequestHandler(request);
  },
};</code></pre>
            
    <div>
      <h4>Familiar and easy development workflow with <code>wrangler dev</code></h4>
      <a href="#familiar-and-easy-development-workflow-with-wrangler-dev">
        
      </a>
    </div>
    <p>To configure which container image to use, you can provide an image URL in wrangler config or a path to a local Dockerfile. </p><p>This config tells wrangler to use a locally defined image:</p>
            <pre><code>"containers": [
  {
    "class_name": "ContainerSandbox",
    "image": "./Dockerfile",
    "max_instances": 80,
    "instance_type": "basic"
  }
]</code></pre>
            <p>When developing your application, you just run <code>wrangler dev</code> and the container image will be automatically built and routable via your local Worker. This makes it easy to iterate on container code while making changes to your Worker at the same time. When you want to rebuild your image, just press “R” on your keyboard from your terminal running <code>wrangler dev</code>, and the Container is rebuilt and restarted.</p>
    <div>
      <h4>Shipping your Container-enabled Worker to production with <code>wrangler deploy</code></h4>
      <a href="#shipping-your-container-enabled-worker-to-production-with-wrangler-deploy">
        
      </a>
    </div>
    <p>When it’s time to deploy, just run <code>wrangler deploy</code>. Wrangler will push your image to your account, then it will be provisioned in various locations across Cloudflare’s global network.</p><p>You don’t have to worry about “artifact management”, or distribution, or auth, or jump through hoops to integrate your container with Workers. You just write your code and deploy it.</p>
    <div>
      <h4>Observability is built-in</h4>
      <a href="#observability-is-built-in">
        
      </a>
    </div>
    <p>Once your Container is in production, you have the visibility you need into how things are going, with end-to-end <a href="https://www.cloudflare.com/developer-platform/products/workers-observability/">observability</a>. </p><p>From the Cloudflare dashboard, you can easily track status and resource usage across Container instances with built-in metrics:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1cMDL8qejpD9TnaVYgKeLD/cf42573c1315f0364c0d225bb77a76af/image4.png" />
          </figure><p>
And if you need to dive deeper, you can dig into logs, which will be retained in the Cloudflare UI for seven days or <a href="https://developers.cloudflare.com/logs/about/"><u>pushed to an external sink</u></a> of your choice:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2AusbmokynDaErssVFyu4A/3bb617ff9c2e488cdaee20612cb6bd15/image3.png" />
          </figure>
    <div>
      <h4>Try it yourself</h4>
      <a href="#try-it-yourself">
        
      </a>
    </div>
    <p>Want to give it a shot? Check out <a href="https://github.com/craigsdennis/sandboxing-day-containers"><u>this example Worker for running sandboxed code</u></a> in a Container, and deploy it with one click.</p><p>Or better yet, if you have an image sitting around that you’ve been dying to deploy to Cloudflare, you can get started with <a href="https://developers.cloudflare.com//containers/get-started/"><u>our docs here</u></a>. </p>
    <div>
      <h2>A world of possibilities</h2>
      <a href="#a-world-of-possibilities">
        
      </a>
    </div>
    <p>We’re excited about all the new types of applications that are now possible to build on Workers. We’ve heard many of you tell us over the years that you would love to run your entire application on Cloudflare, if only you could deploy this one piece that needs to run in a container.</p><p>Today, you can run libraries that you couldn't run in Workers before. For instance, try <a href="https://github.com/megaconfidence/wifski/"><u>this Worker that uses FFmpeg to convert video to a GIF</u></a>. </p><p>Or you can <a href="https://github.com/mikenomitch/cron-container"><u>run a container as part of a cron job</u></a>. Or deploy a <a href="https://github.com/mikenomitch/static-frontend-container-backend"><u>static frontend with a containerized backend</u></a>. Or even run a <a href="https://github.com/ghostwriternr/claude-code-containers"><u>Cloudflare Agent that uses a Container to run Claude Code</u></a> on your behalf.</p><p>The <a href="https://blog.cloudflare.com/cloudflare-containers-coming-2025/#integrating-with-more-of-cloudflares-developer-platform"><u>integration with the rest of the Developer Platform</u></a> makes Containers even more powerful: <a href="https://blog.cloudflare.com/cloudflare-containers-coming-2025/#durable-objects-as-programmable-sidecars"><u>use Durable Objects</u></a> for state management, <a href="https://developers.cloudflare.com/workflows/"><u>Workflows</u></a>, <a href="https://developers.cloudflare.com/queues/"><u>Queues</u></a>, and <a href="https://agents.cloudflare.com/"><u>Agents</u></a> to compose complex behaviors, <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a> to store Container data or media, and more.</p>
    <div>
      <h2>Pricing and packaging</h2>
      <a href="#pricing-and-packaging">
        
      </a>
    </div>
    <p>As with the rest of our Cloudflare developer products, we wanted to apply the same principles to our developer platform with transparent pricing that scales up and down with your usage.</p><p>Today, you can select from the following instances at launch (and yes, we plan to add larger instances over time):  </p><table><tr><td><p><b>Name</b></p></td><td><p><b>Memory </b></p></td><td><p><b>CPU</b></p></td><td><p><b>Disk</b></p></td></tr><tr><td><p>dev</p></td><td><p>256 MiB</p></td><td><p>1/16 vCPU</p></td><td><p>2 GB</p></td></tr><tr><td><p>basic</p></td><td><p>1 GiB</p></td><td><p>1/4 vCPU</p></td><td><p>4 GB</p></td></tr><tr><td><p>standard</p></td><td><p>4 GiB</p></td><td><p>1/2 vCPU</p></td><td><p>4 GB</p></td></tr></table><p>You only pay for what you use — charges start when a request is sent to the container or when it is manually started. Charges stop after the container instance goes to sleep, which can happen automatically after a timeout. This makes it easy to scale to zero, and allows you to get high utilization even with bursty traffic.</p><p>Containers are billed for every 10ms that they are actively running at the following rates, with monthly amounts included in <i>Workers Standard</i>:</p><ul><li><p><b>Memory</b>: $0.0000025 per GiB-second, with 25 GiB-hours included</p></li><li><p><b>CPU</b>: $0.000020 per vCPU-second, with 375 vCPU-minutes included</p></li><li><p><b>Disk</b> $0.00000007 per GB-second, with 200 GB-hours included</p></li></ul><p>Egress from Containers is priced at the following rates, with monthly amounts included in <i>Workers Standard</i>:</p><ul><li><p>North America and Europe: $0.025 per GB with 1 TB included</p></li><li><p>Australia, New Zealand, Taiwan, and Korea: $0.050 per GB with 500 GB included</p></li><li><p>Everywhere else: $0.040 per GB with 500 GB included</p></li></ul><p>
See <a href="https://blog.cloudflare.com/cloudflare-containers-coming-2025/#pay-for-what-you-use-and-use-the-right-tool"><u>our previous blog post</u></a> for a more in-depth look into pricing with an example app.</p>
    <div>
      <h2>What’s coming next?</h2>
      <a href="#whats-coming-next">
        
      </a>
    </div>
    <p>With today’s release, we’ve only just begun to scratch the surface of what Containers will do on Workers. This is the first step of many towards our vision of a simple, global, and highly programmable Container platform.</p><p>We’re already thinking about what’s next, and wanted to give you a preview:</p><ul><li><p><b>Higher limits and larger instances</b> – We currently limit your concurrent instances to 40 total GiB of memory and 40 total vCPU. This is enough for some workloads, but many users will want to go higher —  a lot higher. Select customers are already scaling well into the thousands of concurrent containers, and we want to bring this ability to more users. We will be raising our limits over the coming months to allow for more total containers and larger instance sizes.</p></li><li><p><b>Global autoscaling and latency-aware routing</b> – Currently, containers are addressed by ID and started on-demand. For many use cases, users want to route to one of many stateless container instances deployed across the globe, then autoscale live instances automatically. Autoscaling will be activated with a single line of code, and will enable easy routing to the nearest ready instance.</p></li></ul>
            <pre><code>class MyBackend extends Container {
  defaultPort = 8080;
  autoscale = true; // global autoscaling on - new instances spin up when memory or CPU utilization is high
}

// routes requests to the nearest ready container and load balance globally
async fetch(request, env) {
  return getContainer(env.MY_BACKEND).fetch(request);
}</code></pre>
            <ul><li><p><b>More ways to communicate between Containers and Workers</b> – We will be adding more ways for your Worker to communicate with your container and vice versa. We will add an <code>exec</code> command to run shell commands in your instance and handlers for HTTP requests <i>from</i> the container to Workers. This will allow you to more easily extend your containers with functionality from the entire developer platform, reach out to other containers, and programmatically set up each container instance.</p></li></ul>
            <pre><code>class MyContainer extends Container {
  // sets up container-to-worker communication with handlers
  handlers = {
    "example.cf": "handleRequestFromContainer"
  };

  handleRequestFromContainer(req) {
    return new Response("You are responding from Workers to a Container request to a specific hostname")
  }

  // use exec to run commands in your container instance
  async cloneRepo(repoUrl) {
    let command = this.exec(`git clone ${repoUrl}`)
    await command.print()
  }  
}</code></pre>
            <ul><li><p><b>Further integrations with the Developer Platform</b> – We will continue to integrate with the developer platform with first-party APIs for our various services. We want it to be dead simple to mount <a href="https://developers.cloudflare.com/r2/"><u>R2 buckets</u></a>, reach <a href="https://developers.cloudflare.com/hyperdrive/"><u>Hyperdrive</u></a>, access <a href="https://developers.cloudflare.com/kv/"><u>KV</u></a>, and more.</p></li></ul><p>And we are just getting started. Stay tuned for more updates this summer and over the course of the entire year.</p>
    <div>
      <h2>Try Containers today</h2>
      <a href="#try-containers-today">
        
      </a>
    </div>
    <p>The first step is to deploy your own container. Run <code>npm create cloudflare@latest -- --template=cloudflare/templates/containers-template</code> or click the button below to deploy your first Container to Workers.</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/containers-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
<p>
We’re excited to see all the ways you will use Containers. From new languages and tools, to simplified Cloudflare-only architectures, to advanced programmatic control over container creation, you now have the ability to do even more on the Developer Platform. It is just a wrangler deploy away.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Containers]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[AI]]></category>
            <guid isPermaLink="false">5StUs8TMNjY9aDG2TzFJ06</guid>
            <dc:creator>Gabi Villalonga Simón</dc:creator>
            <dc:creator>Ivan Chernetsky</dc:creator>
            <dc:creator>Josh Seba</dc:creator>
            <dc:creator>Nafeez Nazer</dc:creator>
            <dc:creator>Thomas Lefebvre</dc:creator>
        </item>
        <item>
            <title><![CDATA[Simple, scalable, and global: Containers are coming to Cloudflare Workers in June 2025]]></title>
            <link>https://blog.cloudflare.com/cloudflare-containers-coming-2025/</link>
            <pubDate>Fri, 11 Apr 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare Containers are coming this June. Run new types of workloads on our network with an experience that is simple, scalable, global and deeply integrated with Workers. ]]></description>
            <content:encoded><![CDATA[ <p>It is almost the end of Developer Week and we haven’t talked about containers: until now. As some of you <a href="https://blog.cloudflare.com/container-platform-preview/"><u>may know</u></a>, we’ve been working on a container platform behind the scenes for some time.</p><p>In late June, we plan to release Containers in open beta, and today we’ll give you a sneak peek at what makes it unique.</p><p>Workers are the simplest way to ship software around the world with little overhead. But sometimes you need to do more. You might want to:</p><ul><li><p>Run user-generated code in any language</p></li><li><p>Execute a CLI tool that needs a full Linux environment</p></li><li><p>Use several gigabytes of memory or multiple CPU cores</p></li><li><p>Port an existing application from AWS, GCP, or Azure without a major rewrite</p></li></ul><p>Cloudflare Containers let you do all of that while being simple, scalable, and global.</p><p>Through a deep integration with <a href="https://www.cloudflare.com/developer-platform/products/workers/">Workers</a> and an architecture built on <a href="https://www.cloudflare.com/developer-platform/products/durable-objects/">Durable Objects</a>, Workers can be your:</p><ul><li><p><b>API Gateway</b>: Letting you control routing, authentication, caching, and rate-limiting before requests reach a container</p></li><li><p><b>Service Mesh</b>: Creating private connections between containers with a programmable routing layer</p></li><li><p><b>Orchestrator</b>: Allowing you to write custom scheduling, scaling, and health checking logic for your containers</p></li></ul><p>Instead of having to deploy new services, write custom Kubernetes operators, or wade through control plane configuration to extend the platform, you just write code.</p><p>Let’s see what it looks like.</p>
    <div>
      <h2>Deploying different application types</h2>
      <a href="#deploying-different-application-types">
        
      </a>
    </div>
    
    <div>
      <h3>A stateful workload: executing AI-generated code</h3>
      <a href="#a-stateful-workload-executing-ai-generated-code">
        
      </a>
    </div>
    <p>First, let’s take a look at a stateful example.</p><p>Imagine you are building a platform where end-users can run code generated by an <a href="https://www.cloudflare.com/learning/ai/what-is-large-language-model/">LLM</a>. This code is untrusted, so each user needs their own secure sandbox. Additionally, you want users to be able to run multiple requests in sequence, potentially writing to local files or saving in-memory state.</p><p>To do this, you need to create a container on-demand for each user session, then route subsequent requests to that container. Here’s how you can accomplish this:</p><p>First, you write some <a href="https://github.com/cloudflare/containers-demos/blob/main/ai/wrangler.jsonc#L6"><u>basic Wrangler config</u></a>, then you route requests to containers via your Worker:</p>
            <pre><code>import { Container } from "cloudflare:workers";

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.pathname.startsWith("/execute-code")) {
      const { sessionId, messages } = await request.json();
      // pass in prompt to get the code from Llama 4
      const codeToExecute = await env.AI.run("@cf/meta/llama-4-scout-17b-16e-instruct", { messages });

      // get a different container for each user session
      const id = env.CODE_EXECUTOR.idFromName(sessionId);
      const sandbox = env.CODE_EXECUTOR.get(id);

      // execute a request on the container
      return sandbox.fetch("/execute-code", { method: "POST", body: codeToExecute });
    }

    // ... rest of Worker ...
  },
};

// define your container using the Container class from cloudflare:workers
export class CodeExecutor extends Container {
  defaultPort = 8080;
  sleepAfter = "1m";
}</code></pre>
            <p>Then, deploy your code with a single command: <code>wrangler deploy</code>. This builds your container image, pushes it to Cloudflare’s registry, readies containers to boot quickly across the globe, and deploys your Worker.</p>
            <pre><code>$ wrangler deploy</code></pre>
            <p>That’s it.</p><p>How does it work?</p><p>Your Worker creates and starts up containers on-demand. Each time you call <code>env.CODE_EXECUTOR.get(id)</code> with a unique ID, it sends requests to a unique container instance. The container will automatically boot on the first <code>fetch</code>, then put itself to sleep after a configurable timeout, in this case 1 minute. You only pay for the time that the container is actively running.</p><p>When you request a new container, we boot one in a Cloudflare location near the incoming request. This means that low-latency workloads are well-served no matter the region. Cloudflare takes care of all the pre-warming and caching so you don’t have to think about it.</p><p>This allows each user to run code in their own secure environment.</p>
    <div>
      <h3>Stateless and global: FFmpeg everywhere</h3>
      <a href="#stateless-and-global-ffmpeg-everywhere">
        
      </a>
    </div>
    <p>Stateless and autoscaling applications work equally well on Cloudflare Containers.</p><p>Imagine you want to run a container that takes a video file and turns it into an animated GIF using <a href="https://www.ffmpeg.org/"><u>FFmpeg</u></a>. Unlike the previous example, any container can serve any request, but you still don’t want to send bytes across an ocean and back unnecessarily. So, ideally the app can be deployed everywhere.</p><p>To do this, you declare a container in Wrangler config and turn on <code>autoscaling</code>. This specific configuration ensures that one instance is always running and if CPU usage increases beyond 75% of capacity, additional instances are added:</p>
            <pre><code>"containers": [
  {
    "class_name": "GifMaker",
    "image": "./Dockerfile", // container source code can be alongside Worker code
    "instance_type": "basic",
    "autoscaling": {
      "minimum_instances": 1,
      "cpu_target": 75,
    }
  }
],
// ...rest of wrangler.jsonc...</code></pre>
            <p>To route requests, you just call <code>env.GIF_MAKER.fetch</code> and requests are automatically sent to the closest container:</p>
            <pre><code>import { Container } from "cloudflare:workers";

export class GifMaker extends Container {
  defaultPort: 1337,
}

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.pathname === "/make-gif") {
      return env.GIF_MAKER.fetch(request)
    }

    // ... rest of Worker ...
  },
};</code></pre>
            
    <div>
      <h3>Going beyond the basics</h3>
      <a href="#going-beyond-the-basics">
        
      </a>
    </div>
    <p>From the examples above, you can see that getting a basic container service running on Workers just takes a few lines of config and a little Workers code. There’s no need to worry about capacity, artifact registries, regions, or scaling.</p><p>For more advanced use, we’ve designed Cloudflare Containers to run on top of Durable Objects and work in tandem with Workers. Let’s take a look at the underlying architecture and see some of the advanced use cases it enables.</p>
    <div>
      <h2>Durable Objects as programmable sidecars</h2>
      <a href="#durable-objects-as-programmable-sidecars">
        
      </a>
    </div>
    <p>Routing to containers is enabled using <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> under the hood. In the examples above, the <code>Container</code> class from <code>cloudflare:workers</code> just wraps a container-enabled Durable Object and provides helper methods for common patterns. In the rest of this post, we’ll look at examples using Durable Objects directly, as this should shed light on the platform’s underlying design.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/tEAz34lNlHaJtLQVp1qia/734fc01c90e2aca8e5d75c060f09be9e/1.png" />
          </figure><p>Each Durable Object acts as a programmable sidecar that can proxy requests to the container and manages its lifecycle. This allows you to control and extend your containers in ways that are hard on other platforms. </p><p>You can manually start, stop, and execute commands on a specific container by calling RPC methods on its Durable Object, which now has a new object at <code>this.ctx.container</code>:</p>
            <pre><code>class MyContainer extends DurableObject {
  // these RPC methods are callable from a Worker
  async customBoot(entrypoint, envVars) {
    this.ctx.container.start({ entrypoint, env: envVars });
  }

  async stopContainer() {
    const SIGTERM = 15;
    this.ctx.container.signal(SIGTERM);
  }

  async startBackupScript() {
    await this.ctx.container.exec(["./backup"]);
  }
}</code></pre>
            <p>You can also monitor your container and run hooks in response to Container status changes.</p><p>For instance, say you have a CI job that runs builds in a Container. You want to post a message to a <a href="https://developers.cloudflare.com/queues/"><u>Queue</u></a> based on the exit status. You can easily program this behavior:</p>
            <pre><code>class BuilderContainer extends DurableObject {
  constructor(ctx, env) {
    super(ctx, env)
    async function onContainerExit() {
      await this.env.QUEUE.send({ status: "success", message: "Build Complete" });
    }

    async function onContainerError(err) {
      await this.env.QUEUE.send({ status: "error", message: err});
    }

    this.ctx.container.start();
    this.ctx.container.monitor().then(onContainerExit).catch(onContainerError); 
  }

  async isRunning() { return this.ctx.container.running; }
}</code></pre>
            <p>And lastly, if you have state that needs to be loaded into a container each time it runs, you can use status hooks to persist state from the container before it sleeps and to reload state into the container after it starts:</p>
            <pre><code>import { startAndWaitForPort } from "./helpers"

class MyContainer extends DurableObject {
  constructor(ctx, env) {
    super(ctx, env)
    this.ctx.blockConcurrencyWhile(async () =&gt; {
      this.ctx.storage.sql.exec('CREATE TABLE IF NOT EXISTS state (value TEXT)');
      this.ctx.storage.sql.exec("INSERT INTO state (value) SELECT '' WHERE NOT EXISTS 
(SELECT * FROM state)");
      await startAndWaitForPort(this.ctx.container, 8080);
      await this.setupContainer();
      this.ctx.container.monitor().then(this.onContainerExit); 
    });
  }

  async setupContainer() {
    const initialState = this.ctx.storage.sql.exec('SELECT * FROM state LIMIT 1').one().value;
    return this.ctx.container
      .getTcpPort(8080)
      .fetch("http://container/state", { body: initialState, method: 'POST' });
  }

  async onContainerExit() {
    const response = await this.ctx.container
      .getTcpPort(8080)
      .fetch('http://container/state');
    const newState = await response.text();
    this.ctx.storage.sql.exec('UPDATE state SET value = ?', newState);
  }
}</code></pre>
            
    <div>
      <h2>Building around your Containers with Workers</h2>
      <a href="#building-around-your-containers-with-workers">
        
      </a>
    </div>
    <p>Not only do Durable Objects allow you to have fine-grained control over the Container lifecycle, the whole Workers platform allows you to extend routing and scheduling behavior as you see fit.</p>
    <div>
      <h3>Using Workers as an API gateway</h3>
      <a href="#using-workers-as-an-api-gateway">
        
      </a>
    </div>
    <p>Workers provide programmable ingress logic from <a href="https://www.cloudflare.com/network/"><u>over 300 locations</u></a> around the world. In this sense, they provide similar functionality to an <a href="https://www.cloudflare.com/learning/security/api/what-is-an-api-gateway/">API gateway</a>.</p><p>For instance, let’s say you want to route requests to a different version of a container based on information in a header. This is accomplished in a few lines of code:</p>
            <pre><code>export default {
  async fetch(request, env) {
    const isExperimental = request.headers.get("x-version") === "experimental";
    
    if (isExperimental) {
      return env.MY_SERVICE_EXPERIMENTAL.fetch(request);
    } else {
      return env.MY_SERVICE_STANDARD.fetch(request);
    }
  },
};</code></pre>
            <p>Or you want to rate limit and authenticate requests to the container:</p>
            <pre><code>async fetch(request, env) {
  const url = new URL(request.url);

  if (url.pathname.startsWith('/api/')) {
    const token = request.headers.get("token");

    const isAuthenticated = await authenticateRequest(token);
    if (!isAuthenticated) {
      return new Response("Not authenticated", { status: 401 });
    }

    const { withinRateLimit } = await env.MY_RATE_LIMITER.limit({ key: token });
    if (!withinRateLimit) {
      return new Response("Rate limit exceeded for token", { status: 429 });
    }

    return env.MY_APP.fetch(request);
  }
  // ...
}</code></pre>
            
    <div>
      <h3>Using Workers as a service mesh</h3>
      <a href="#using-workers-as-a-service-mesh">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/56gJk7HEDJs4dsNXDkBX1x/7c9d6be661d0cd6baea13caeedf478c0/2.png" />
          </figure><p>By default, Containers are private and can only be accessed via Workers, which can connect to one of many container ports. From within the container, you can expose a plain HTTP port, but requests will still be encrypted from the end user to the moment we send the data to the container’s TCP port in the host. Due to the communication being relayed through the Cloudflare network, the container does not need to set up <a href="https://www.cloudflare.com/application-services/products/ssl/">TLS certificates</a> to have secure connections in its open ports.</p><p>You can connect to the container through a WebSocket from the client too. See <a href="https://github.com/cloudflare/containers-demos/tree/main/websockets"><u>this repository</u></a> for a full example of using Websockets.</p><p>Just as the Durable Object can act as proxy <i>to the container</i>, it can act as a proxy <i>from the container </i>as well. When setting up a container, you can toggle Internet access off and ensure that outgoing requests pass through Workers.</p>
            <pre><code>// ... when starting the container...
this.ctx.container.start({ 
  workersAddress: '10.0.0.2:8080',
  enableInternet: false, // 'enableInternet' is false by default
});

// ... container requests to '10.0.0.2:8080' securely route to a different service...
override async onContainerRequest(request: Request) {
  const containerId = this.env.SUB_SERVICE.idFromName(request.headers['X-Account-Id']);
  return this.env.SUB_SERVICE.get(containerId).fetch(request);
}</code></pre>
            <p>You can ensure all traffic in and out of your container is secured and encrypted end to end without having to deal with networking yourself.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/9PzlxveRZ6NNBiNeZTiWs/c70e5db9cc7d63c02a21f21769801bc4/3.png" />
          </figure><p>This allows you to protect and connect containers within Cloudflare’s network… or even when connecting to <a href="https://blog.cloudflare.com/workers-virtual-private-cloud"><u>external private networks</u></a>.</p>
    <div>
      <h3>Using Workers as an orchestrator</h3>
      <a href="#using-workers-as-an-orchestrator">
        
      </a>
    </div>
    <p>You might require custom scheduling and scaling logic that goes beyond what Cloudflare provides out of the box.</p><p>We don’t want you having to manage complex chains of API calls or writing an <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/"><u>operator</u></a> to get the logic you need. Just write some Worker code.</p><p>For instance, imagine your containers have a long startup period that involves loading data from an external source. You need to pre-warm containers manually, and need control over the specific region to prewarm. Additionally, you need to set up manual health checks that are accessible via Workers. You’re able to achieve this fairly simply with Workers and Durable Objects.</p>
            <pre><code>import { Container, DurableObject } from "cloudflare:workers";

// A singleton Durable Object to manage and scale containers

class ContainerManager extends DurableObject {
  scale(region, instanceCount) {
    for (let i = 0; i &lt; instanceCount; i++) {
      const containerId = env.CONTAINER.idFromName(`instance-${region}-${i}`);
      // spawns a new container with a location hint
      await env.CONTAINER.get(containerId, { locationHint: region }).start();
    }
  }

  async setHealthy(containerId, isHealthy) {
    await this.ctx.storage.put(containerId, isHealthy);
  }
}

// A Container class for the underlying compute

class MyContainer extends Container {
  defaultPort = 8080;

  async onContainerStart() {
    // run healthcheck every 500ms
    await this.scheduleEvery(0.5, 'healthcheck');
  }

  async healthcheck() {
    const manager = this.env.MANAGER.get(
      this.env.MANAGER.idFromName("manager")
    );
    const id = this.ctx.id.toString();

    await this.container.fetch("/_health")
      .then(() =&gt; manager.setHealthy(id, true))
      .catch(() =&gt; manager.setHealthy(id, false));
  }
}</code></pre>
            <p>The <code>ContainerManager </code>Durable Object exposes the <code>scale</code> RPC call, which you can call as needed with a <code>region</code> and <code>instanceCount</code> which scales up the number of active Container instances in a given region <a href="https://developers.cloudflare.com/durable-objects/reference/data-location/#provide-a-location-hint"><u>using a location hint</u></a>. The <code>this.schedule</code> code executes a manually defined <code>healthcheck</code> method on the Container and tracks its state in the Manager for use by other logic in your system.</p><p>These building blocks let users handle complex scheduling logic themselves. For a more detailed example using standard Durable Objects, see <a href="https://github.com/cloudflare/containers-demos/tree/main/load-balancer"><u>this repository</u></a>.</p><p>We are excited to see the patterns you come up with when orchestrating complex applications built with containers, and trust that between Workers and Durable Objects, you’ll have the tools you need.</p>
    <div>
      <h2>Integrating with more of Cloudflare’s Developer Platform</h2>
      <a href="#integrating-with-more-of-cloudflares-developer-platform">
        
      </a>
    </div>
    <p>Since it is <a href="https://blog.cloudflare.com/welcome-to-developer-week-2025/"><u>Developer Week 2025</u></a>, we would be remiss to not talk about <a href="https://developers.cloudflare.com/workflows/"><u>Workflows</u></a>, which <a href="https://blog.cloudflare.com/workflows-ga-production-ready-durable-execution/"><u>just went GA</u></a>, and <a href="https://agents.cloudflare.com/"><u>Agents</u></a>, which <a href="https://blog.cloudflare.com/building-ai-agents-with-mcp-authn-authz-and-durable-objects/"><u>just got even better</u></a>.</p><p>Let’s finish up by taking a quick look at how you can integrate Containers with these two tools.</p>
    <div>
      <h3>Running a short-lived job with Workflows &amp; R2</h3>
      <a href="#running-a-short-lived-job-with-workflows-r2">
        
      </a>
    </div>
    <p>You need to download a large file from <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a>, compress it, and upload it. You want to ensure that this succeeds, but don’t want to write retry logic and error handling yourself. Additionally, you don’t want to deal with rotating R2 API tokens or worry about network connections — it should be secure by default.</p><p>This is a perfect opportunity for a <a href="https://developers.cloudflare.com/workflows/"><u>Workflow</u></a> using Containers. The container can do the heavy lifting of compressing files, Workers can stream the data to and from R2, and the Workflow can ensure durable execution.</p>
            <pre><code>export class EncoderWorkflow extends WorkflowEntrypoint&lt;Env, Params&gt; {
  async run(event: WorkflowEvent&lt;Params&gt;, step: WorkflowStep) {
    const id = this.env.ENCODER.idFromName(event.instanceId);
    const container = this.env.ENCODER.get(id);

    await step.do('init container', async () =&gt; {
      await container.init();
    });

    await step.do('compress the object with zstd', async () =&gt; {
      await container.ensureHealthy();
      const object = await this.env.ARTIFACTS.get(event.payload.r2Path);
      const result = await container.fetch('http://encoder/zstd', {
        method: 'POST', body: object.body 
      });
      await this.env.ARTIFACTS.put(`results${event.payload.r2Path}`, result.body);
    });

    await step.do('cleanup container', async () =&gt; {
      await container.destroy();
    });
  }
}</code></pre>
            
    <div>
      <h3>Calling a Container from an Agent</h3>
      <a href="#calling-a-container-from-an-agent">
        
      </a>
    </div>
    <p>Lastly, imagine you have an AI agent that needs to spin up cloud infrastructure (you like to live dangerously). To do this, you want to use <a href="https://github.com/hashicorp/terraform"><u>Terraform</u></a>, but since it’s run from the command line, you can’t run it on Workers.</p><p>By defining a <a href="https://developers.cloudflare.com/agents/concepts/tools/"><u>tool</u></a>, you can enable your Agent to run the shell commands from a container:</p>
            <pre><code>// Make tools that call to a container from an agent

const createExternalResources = tool({
  description: "runs Terraform in a container to create resources",
  parameters: z.object({ sessionId: z.number(), config: z.string() }),
  execute: async ({ sessionId, config }) =&gt; {
    return this.env.TERRAFORM_RUNNER.get(sessionId).applyConfig(config);
  },
});

// Expose RPC Methods that call to the container

class TerraformRunner extends DurableObject {
  async applyConfig(config) {
    await this.ctx.container.getTcpPort(8080).fetch(APPLY_URL, {
      method: 'POST',
      body: JSON.stringify({ config }),
    });
  }

  // ...rest of DO...
}</code></pre>
            <p>Containers are so much more powerful when combined with other tools. Workers make it easy to do so in a secure and simple way.</p>
    <div>
      <h2>Pay for what you use and use the right tool</h2>
      <a href="#pay-for-what-you-use-and-use-the-right-tool">
        
      </a>
    </div>
    <p>The deep integration between Workers and Containers also makes it easy to pick the right tool for the job with regards to cost.</p><p>With Cloudflare Containers, you only pay for what you use. Charges start when a request is sent to the container or it is manually started. Charges stop after the container goes to sleep, which can happen automatically after a configurable timeout. This makes it easy to scale to zero, and allows you to get high utilization even with highly-variable traffic.</p><p>Containers are billed for every 10ms that they are actively running at the following rates:</p><ul><li><p>Memory: $0.0000025 per GB-second</p></li><li><p>CPU: $0.000020 per vCPU-second</p></li><li><p>Disk $0.00000007 per GB-second
</p></li></ul><p>After 1 TB of free data transfer per month, egress from a Container will be priced per-region. We'll be working out the details between now and the beta, and will be launching with clear, transparent pricing across all dimensions so you know where you stand.</p><p>Workers are lighter weight than containers and <a href="https://blog.cloudflare.com/workers-pricing-scale-to-zero"><u>save you money by not charging when waiting on I/O</u></a>. This means that if you can, running on a Worker helps you save on cost. Luckily, on Cloudflare it is easy to route requests to the right tool.</p>
    <div>
      <h3>Cost comparison</h3>
      <a href="#cost-comparison">
        
      </a>
    </div>
    <p>Comparing containers and functions services on paper is always going to be an apples to oranges exercise, and results can vary so much depending on use case. But to share a real example of our own, a year ago when Cloudflare acquired Baselime, Baselime was a heavy user of AWS Lambda. By moving to Cloudflare, <a href="https://blog.cloudflare.com/80-percent-lower-cloud-cost-how-baselime-moved-from-aws-to-cloudflare/"><u>they lowered their cloud compute bill by 80%</u></a>.</p><p>Below we wanted to share one representative example that compares costs for an application that uses both containers and serverless functions together. It’d be easy for us to come up with a contrived example that uses containers sub-optimally on another platform, for the wrong types of workloads. We won’t do that here. We know that navigating cloud costs can be challenging, and that cost is a critical part of deciding what type of compute to use for which pieces of your application.</p><p>In the example below, we’ll compare Cloudflare Containers + Workers against Google Cloud Run, a very well-regarded container platform that we’ve been impressed by.</p>
    <div>
      <h4>Example application</h4>
      <a href="#example-application">
        
      </a>
    </div>
    <p>Imagine that you run an application that serves 50 million requests per month, and each request consumes an average 500 ms of wall-time. Requests to this application are not all the same though — half the requests require a container, and the other half can be served just using serverless functions.</p><table><tr><td><p>Requests per month</p></td><td><p>Wall-time (duration)</p></td><td><p>Compute required</p></td><td><p>Cloudflare</p></td><td><p>Google Cloud</p></td></tr><tr><td><p>25 million</p></td><td><p>500ms</p></td><td><p>Container + serverless functions</p></td><td><p>Containers + Workers</p></td><td><p>Google Cloud Run + Google Cloud Run Functions</p></td></tr><tr><td><p>25 million</p></td><td><p>500ms</p></td><td><p>Serverless functions</p></td><td><p>Workers</p></td><td><p>Google Cloud Run Functions</p></td></tr></table>
    <div>
      <h4>Container pricing</h4>
      <a href="#container-pricing">
        
      </a>
    </div>
    <p>On both Cloud Run and Cloudflare Containers, a container can serve multiple requests. On some platforms, such as AWS Lambda, each container instance is limited to a single request, pushing cost up significantly as request count grows. In this scenario, 50 requests can run simultaneously on a container with 4 GB memory and half of a vCPU. This means that to serve 25 million requests of 500ms each, we need 625,000 seconds worth of compute</p><p>In this example, traffic is bursty and we want to avoid paying for idle-time, so we’ll use Cloud Run’s request-based pricing.</p><table><tr><td><p>
</p></td><td><p>Price per vCPU second</p></td><td><p>Price per GB-second of memory</p></td><td><p>Price per 1m requests</p></td><td><p>Monthly Price for Compute + Requests</p></td></tr><tr><td><p>Cloudflare Containers</p></td><td><p>$0.000020</p></td><td><p>$0.0000025</p></td><td><p>$0.30</p></td><td><p>$20.00</p></td></tr><tr><td><p>Google Cloud Run</p></td><td><p>$0.000024</p></td><td><p>$0.0000025</p></td><td><p>$0.40</p></td><td><p>$23.75</p></td></tr></table><p><sup><i>* Comparison does not include free tiers for either provider and uses a single Tier 1 GCP region</i></sup></p><p>Compute pricing for both platforms are comparable. But as we showed earlier in this post, Containers on Cloudflare run anywhere, on-demand, without configuring and managing regions. Each container has a programmable sidecar with its own database, backed by Durable Objects. It’s the depth of integration with the rest of the platform that makes containers on Cloudflare uniquely programmable.</p>
    <div>
      <h4>Function pricing</h4>
      <a href="#function-pricing">
        
      </a>
    </div>
    <p>The other requests can be served with less compute, and code written in <a href="https://developers.cloudflare.com/workers/languages/javascript/"><u>JavaScript</u></a>, <a href="https://developers.cloudflare.com/workers/languages/typescript/"><u>TypeScript</u></a>, <a href="https://developers.cloudflare.com/workers/languages/python/"><u>Python</u></a> or <a href="https://developers.cloudflare.com/workers/languages/rust/"><u>Rust</u></a>, so we’ll use Workers and Cloud Run Functions.</p><p>These 25 million requests also run for 500 ms each, and each request spends 480 ms waiting on I/O. This means that Workers will <a href="https://blog.cloudflare.com/workers-pricing-scale-to-zero/"><u>only charge for 20 ms of “CPU-time”</u></a>, the time that the Worker actually spends using compute. This ratio of low CPU time to high wall time is extremely common when building AI apps that make inference requests, or even when just building REST APIs and other business logic. Most time is spent waiting on I/O. Based on our data, we typically see Workers use less than 5 ms of CPU time per request vs seconds of wall time (waiting on APIs or I/O).</p><p>The Cloud Run Function will use an instance with 0.083 vCPU and 128 MB memory and charge on both CPU-s and GiB-s for the full 500 ms of wall-time.</p><table><tr><td><p>
</p></td><td><p>Total Price for “wall-time”</p></td><td><p>Total Price for “CPU-time”</p></td><td><p>Total Price for Compute + Requests</p></td></tr><tr><td><p>Cloudflare Workers</p></td><td><p>N/A</p></td><td><p>$0.83</p></td><td><p>$8.33</p></td></tr><tr><td><p>Google Cloud Run Functions</p></td><td><p>$1.44</p></td><td><p>N/A</p></td><td><p>$11.44</p></td></tr></table><p><sup><i>* Comparison does not include free tiers and uses a single Tier 1 GCP region.</i></sup></p><p>This comparison assumes you have configured Google Cloud Run Functions with a max of 20 concurrent requests per instance. On Google Cloud Run Functions, the maximum number of concurrent requests an instance can handle varies based on the efficiency of your function, and your own tolerance for tail latency that can be introduced by traffic spikes. </p><p>Workers automatically scale horizontally, don’t require you to configure concurrency settings (and hope to get it right), and can run in <a href="https://www.cloudflare.com/en-gb/network/"><u>over 300 locations</u></a>.</p>
    <div>
      <h4>A holistic view of costs</h4>
      <a href="#a-holistic-view-of-costs">
        
      </a>
    </div>
    <p>The most important cost metric is the total cost of developing and running an application. And the only way to get the best results is to use the right compute for the job. So the question boils down to friction and integration. How easily can you integrate the ideal building blocks together?</p><p>As more and more software makes use of <a href="https://www.cloudflare.com/learning/ai/what-is-generative-ai/">generative AI</a>, and makes inference requests to LLMs, modern applications must communicate and integrate with a myriad of services. Most systems are increasingly real-time and chatty, often holding open long-lived connections, performing tasks in parallel. Running an instance of an application in a VM or container and calling it a day might have worked 10 years ago, but when we talk to developers in 2025, they are most often bringing many forms of compute to the table for particular use cases.</p><p>This shows the importance of picking a platform where you can seamlessly shift traffic from one source of compute to another. If you want to <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/"><u>rate-limit</u></a>, <a href="https://blog.cloudflare.com/full-stack-development-on-cloudflare-workers/"><u>serve server-side rendered pages, API responses and static assets</u></a>, handle authentication and authorization, make<a href="https://developers.cloudflare.com/workers-ai/"><u> inference requests to AI models</u></a>, run core business logic via <a href="https://blog.cloudflare.com/workflows-ga-production-ready-durable-execution/"><u>Workflows</u></a>, or <a href="https://blog.cloudflare.com/cloudflare-acquires-arroyo-pipelines-streaming-ingestion-beta/"><u>ingest streaming data</u></a>, just handle the request in Workers. Save the heavier compute only for where it is actually the only option. With Cloudflare Workers and Containers, this is as simple as an if-else statement in your Worker. This makes it easy to pick the right tool for the job.</p>
    <div>
      <h2>Coming June 2025</h2>
      <a href="#coming-june-2025">
        
      </a>
    </div>
    <p>We are collecting feedback and putting the finishing touches on our APIs now, and will release the open beta to the public in late June 2025.</p><p>From day one of building Cloudflare Workers, it’s been our goal to build an integrated platform, where Cloudflare products work together as a system, rather than just as a collection of separate products. We’ve taken this same approach with Containers, and aim to make Cloudflare not only the best place to deploy containers across the globe, but the best place to deploy the types of complete applications that developers are building, that use containers in tandem with serverless functions, <a href="http://developers.cloudflare.com/workflows"><u>Workflows</u></a>, <a href="https://agents.cloudflare.com/"><u>Agents</u></a>, and <a href="https://developers.cloudflare.com/"><u>much more</u></a>.</p><p>We’re excited to get this into your hands soon. Stay on the lookout this summer.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6tb0K0eJoK6L4QrUCTWISx/4346edb7593b47768cebcb48369cfa35/4.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Containers]]></category>
            <guid isPermaLink="false">7yspClA37lzZVogRwQzn5F</guid>
            <dc:creator>Mike Nomitch</dc:creator>
            <dc:creator>Gabi Villalonga Simón</dc:creator>
        </item>
    </channel>
</rss>