
<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>Tue, 14 Apr 2026 00:50:56 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Sandboxing AI agents, 100x faster]]></title>
            <link>https://blog.cloudflare.com/dynamic-workers/</link>
            <pubDate>Tue, 24 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ We’re introducing Dynamic Workers, which allow you to execute AI-generated code in secure, lightweight isolates. This approach is 100 times faster than traditional containers, enabling millisecond startup times for AI agent sandboxing. ]]></description>
            <content:encoded><![CDATA[ <p>Last September we introduced <a href="https://blog.cloudflare.com/code-mode/"><u>Code Mode</u></a>, the idea that agents should perform tasks not by making tool calls, but instead by writing code that calls APIs. We've shown that simply converting an MCP server into a TypeScript API can <a href="https://www.youtube.com/watch?v=L2j3tYTtJwk"><u>cut token usage by 81%</u></a>. We demonstrated that Code Mode can also operate <i>behind</i> an MCP server instead of in front of it, creating the new <a href="https://blog.cloudflare.com/code-mode-mcp/"><u>Cloudflare MCP server that exposes the entire Cloudflare API with just two tools and under 1,000 tokens</u></a>.</p><p>But if an agent (or an MCP server) is going to execute code generated on-the-fly by AI to perform tasks, that code needs to run somewhere, and that somewhere needs to be secure. You can't just <code>eval() </code>AI-generated code directly in your app: a malicious user could trivially prompt the AI to inject vulnerabilities.</p><p>You need a <b>sandbox</b>: a place to execute code that is isolated from your application and from the rest of the world, except for the specific capabilities the code is meant to access.</p><p>Sandboxing is a hot topic in the AI industry. For this task, most people are reaching for containers. Using a Linux-based container, you can start up any sort of code execution environment you want. Cloudflare even offers <a href="https://developers.cloudflare.com/containers/"><u>our container runtime</u></a> and <a href="https://developers.cloudflare.com/sandbox/"><u>our Sandbox SDK</u></a> for this purpose.</p><p>But containers are expensive and slow to start, taking hundreds of milliseconds to boot and hundreds of megabytes of memory to run. You probably need to keep them warm to avoid delays, and you may be tempted to reuse existing containers for multiple tasks, compromising the security.</p><p><b>If we want to support consumer-scale agents, where every end user has an agent (or many!) and every agent writes code, containers are not enough. We need something lighter.</b></p><h6>And we have it.</h6>
    <div>
      <h2>Dynamic Worker Loader: a lean sandbox</h2>
      <a href="#dynamic-worker-loader-a-lean-sandbox">
        
      </a>
    </div>
    <p>Tucked into our Code Mode post in September was the announcement of a new, experimental feature: the Dynamic Worker Loader API. This API allows a Cloudflare Worker to instantiate a new Worker, in its own sandbox, with code specified at runtime, all on the fly.</p><p><b>Dynamic Worker Loader is now in open beta, available to all paid Workers users.</b></p><p><a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Read the docs for full details</u></a>, but here's what it looks like:</p>
            <pre><code>// Have your LLM generate code like this.
let agentCode: string = `
  export default {
    async myAgent(param, env, ctx) {
      // ...
    }
  }
`;

// Get RPC stubs representing APIs the agent should be able
// to access. (This can be any Workers RPC API you define.)
let chatRoomRpcStub = ...;

// Load a worker to run the code, using the worker loader
// binding.
let worker = env.LOADER.load({
  // Specify the code.
  compatibilityDate: "2026-03-01",
  mainModule: "agent.js",
  modules: { "agent.js": agentCode },

  // Give agent access to the chat room API.
  env: { CHAT_ROOM: chatRoomRpcStub },

  // Block internet access. (You can also intercept it.)
  globalOutbound: null,
});

// Call RPC methods exported by the agent code.
await worker.getEntrypoint().myAgent(param);
</code></pre>
            <p>That's it.</p>
    <div>
      <h3>100x faster</h3>
      <a href="#100x-faster">
        
      </a>
    </div>
    <p>Dynamic Workers use the same underlying sandboxing mechanism that the entire Cloudflare Workers platform has been built on since its launch, eight years ago: isolates. An isolate is an instance of the V8 JavaScript execution engine, the same engine used by Google Chrome. They are <a href="https://developers.cloudflare.com/workers/reference/how-workers-works/"><u>how Workers work</u></a>.</p><p>An isolate takes a few milliseconds to start and uses a few megabytes of memory. That's around 100x faster and 10x-100x more memory efficient than a typical container.</p><p><b>That means that if you want to start a new isolate for every user request, on-demand, to run one snippet of code, then throw it away, you can.</b></p>
    <div>
      <h3>Unlimited scalability</h3>
      <a href="#unlimited-scalability">
        
      </a>
    </div>
    <p>Many container-based sandbox providers impose limits on global concurrent sandboxes and rate of sandbox creation. Dynamic Worker Loader has no such limits. It doesn't need to, because it is simply an API to the same technology that has powered our platform all along, which has always allowed Workers to seamlessly scale to millions of requests per second.</p><p>Want to handle a million requests per second, where <i>every single request</i> loads a separate Dynamic Worker sandbox, all running concurrently? No problem!</p>
    <div>
      <h3>Zero latency</h3>
      <a href="#zero-latency">
        
      </a>
    </div>
    <p>One-off Dynamic Workers usually run on the same machine — the same thread, even — as the Worker that created them. No need to communicate around the world to find a warm sandbox. Isolates are so lightweight that we can just run them wherever the request landed. Dynamic Workers are supported in every one of Cloudflare's hundreds of locations around the world.</p>
    <div>
      <h3>It's all JavaScript</h3>
      <a href="#its-all-javascript">
        
      </a>
    </div>
    <p>The only catch, vs. containers, is that your agent needs to write JavaScript.</p><p>Technically, Workers (including dynamic ones) can use Python and WebAssembly, but for small snippets of code — like that written on-demand by an agent — JavaScript will load and run much faster.</p><p>We humans tend to have strong preferences on programming languages, and while many love JavaScript, others might prefer Python, Rust, or countless others.</p><p>But we aren't talking about humans here. We're talking about AI. AI will write any language you want it to. LLMs are experts in every major language. Their training data in JavaScript is immense.</p><p>JavaScript, by its nature on the web, is designed to be sandboxed. It is the correct language for the job.</p>
    <div>
      <h3>Tools defined in TypeScript</h3>
      <a href="#tools-defined-in-typescript">
        
      </a>
    </div>
    <p>If we want our agent to be able to do anything useful, it needs to talk to external APIs. How do we tell it about the APIs it has access to?</p><p>MCP defines schemas for flat tool calls, but not programming APIs. OpenAPI offers a way to express REST APIs, but it is verbose, both in the schema itself and the code you'd have to write to call it.</p><p>For APIs exposed to JavaScript, there is a single, obvious answer: TypeScript.</p><p>Agents know TypeScript. TypeScript is designed to be concise. With very few tokens, you can give your agent a precise understanding of your API.</p>
            <pre><code>// Interface to interact with a chat room.
interface ChatRoom {
  // Get the last `limit` messages of the chat log.
  getHistory(limit: number): Promise&lt;Message[]&gt;;

  // Subscribe to new messages. Dispose the returned object
  // to unsubscribe.
  subscribe(callback: (msg: Message) =&gt; void): Promise&lt;Disposable&gt;;

  // Post a message to chat.
  post(text: string): Promise&lt;void&gt;;
}

type Message = {
  author: string;
  time: Date;
  text: string;
}
</code></pre>
            <p>Compare this with the equivalent OpenAPI spec (which is so long you have to scroll to see it all):</p><pre>
openapi: 3.1.0
info:
  title: ChatRoom API
  description: &gt;
    Interface to interact with a chat room.
  version: 1.0.0

paths:
  /messages:
    get:
      operationId: getHistory
      summary: Get recent chat history
      description: Returns the last `limit` messages from the chat log, newest first.
      parameters:
        - name: limit
          in: query
          required: true
          schema:
            type: integer
            minimum: 1
      responses:
        "200":
          description: A list of messages.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Message"

    post:
      operationId: postMessage
      summary: Post a message to the chat room
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - text
              properties:
                text:
                  type: string
      responses:
        "204":
          description: Message posted successfully.

  /messages/stream:
    get:
      operationId: subscribeMessages
      summary: Subscribe to new messages via SSE
      description: &gt;
        Opens a Server-Sent Events stream. Each event carries a JSON-encoded
        Message object. The client unsubscribes by closing the connection.
      responses:
        "200":
          description: An SSE stream of new messages.
          content:
            text/event-stream:
              schema:
                description: &gt;
                  Each SSE `data` field contains a JSON-encoded Message object.
                $ref: "#/components/schemas/Message"

components:
  schemas:
    Message:
      type: object
      required:
        - author
        - time
        - text
      properties:
        author:
          type: string
        time:
          type: string
          format: date-time
        text:
          type: string
</pre><p>We think the TypeScript API is better. It's fewer tokens and much easier to understand (for both agents and humans).  </p><p>Dynamic Worker Loader makes it easy to implement a TypeScript API like this in your own Worker and then pass it in to the Dynamic Worker either as a method parameter or in the env object. The Workers Runtime will automatically set up a <a href="https://blog.cloudflare.com/capnweb-javascript-rpc-library/"><u>Cap'n Web RPC</u></a> bridge between the sandbox and your harness code, so that the agent can invoke your API across the security boundary without ever realizing that it isn't using a local library.</p><p>That means your agent can write code like this:</p>
            <pre><code>// Thinking: The user asked me to summarize recent chat messages from Alice.
// I will filter the recent message history in code so that I only have to
// read the relevant messages.
let history = await env.CHAT_ROOM.getHistory(1000);
return history.filter(msg =&gt; msg.author == "alice");
</code></pre>
            
    <div>
      <h3>HTTP filtering and credential injection</h3>
      <a href="#http-filtering-and-credential-injection">
        
      </a>
    </div>
    <p>If you prefer to give your agents HTTP APIs, that's fully supported. Using the <code>globalOutbound</code> option to the worker loader API, you can register a callback to be invoked on every HTTP request, in which you can inspect the request, rewrite it, inject auth keys, respond to it directly, block it, or anything else you might like.</p><p>For example, you can use this to implement <b>credential injection</b> (token injection): When the agent makes an HTTP request to a service that requires authorization, you add credentials to the request on the way out. This way, the agent itself never knows the secret credentials, and therefore cannot leak them.</p><p>Using a plain HTTP interface may be desirable when an agent is talking to a well-known API that is in its training set, or when you want your agent to use a library that is built on a REST API (the library can run inside the agent's sandbox).</p><p>With that said, <b>in the absence of a compatibility requirement, TypeScript RPC interfaces are better than HTTP:</b></p><ul><li><p>As shown above, a TypeScript interface requires far fewer tokens to describe than an HTTP interface.</p></li><li><p>The agent can write code to call TypeScript interfaces using far fewer tokens than equivalent HTTP.</p></li><li><p>With TypeScript interfaces, since you are defining your own wrapper interface anyway, it is easier to narrow the interface to expose exactly the capabilities that you want to provide to your agent, both for simplicity and security. With HTTP, you are more likely implementing <i>filtering</i> of requests made against some existing API. This is hard, because your proxy must fully interpret the meaning of every API call in order to properly decide whether to allow it, and HTTP requests are complicated, with many headers and other parameters that could all be meaningful. It ends up being easier to just write a TypeScript wrapper that only implements the functions you want to allow.</p></li></ul>
    <div>
      <h3>Battle-hardened security</h3>
      <a href="#battle-hardened-security">
        
      </a>
    </div>
    <p>Hardening an isolate-based sandbox is tricky, as it is a more complicated attack surface than hardware virtual machines. Although all sandboxing mechanisms have bugs, security bugs in V8 are more common than security bugs in typical hypervisors. When using isolates to sandbox possibly-malicious code, it's important to have additional layers of defense-in-depth. Google Chrome, for example, implemented strict process isolation for this reason, but it is not the only possible solution.</p><p>We have nearly a decade of experience securing our isolate-based platform. Our systems automatically deploy V8 security patches to production within hours — faster than Chrome itself. Our <a href="https://blog.cloudflare.com/mitigating-spectre-and-other-security-threats-the-cloudflare-workers-security-model/"><u>security architecture</u></a> features a custom second-layer sandbox with dynamic cordoning of tenants based on risk assessments. <a href="https://blog.cloudflare.com/safe-in-the-sandbox-security-hardening-for-cloudflare-workers/"><u>We've extended the V8 sandbox itself</u></a> to leverage hardware features like MPK. We've teamed up with (and hired) leading researchers to develop <a href="https://blog.cloudflare.com/spectre-research-with-tu-graz/"><u>novel defenses against Spectre</u></a>. We also have systems that scan code for malicious patterns and automatically block them or apply additional layers of sandboxing. And much more.</p><p>When you use Dynamic Workers on Cloudflare, you get all of this automatically.</p>
    <div>
      <h2>Helper libraries</h2>
      <a href="#helper-libraries">
        
      </a>
    </div>
    <p>We've built a number of libraries that you might find useful when working with Dynamic Workers: </p>
    <div>
      <h3>Code Mode</h3>
      <a href="#code-mode">
        
      </a>
    </div>
    <p><a href="https://www.npmjs.com/package/@cloudflare/codemode"><code>@cloudflare/codemode</code></a> simplifies running model-generated code against AI tools using Dynamic Workers. At its core is <code>DynamicWorkerExecutor()</code>, which constructs a purpose-built sandbox with code normalisation to handle common formatting errors, and direct access to a <code>globalOutbound</code> fetcher for controlling <code>fetch()</code> behaviour inside the sandbox — set it to <code>null</code> for full isolation, or pass a <code>Fetcher</code> binding to route, intercept or enrich outbound requests from the sandbox.</p>
            <pre><code>const executor = new DynamicWorkerExecutor({
  loader: env.LOADER,
  globalOutbound: null, // fully isolated 
});

const codemode = createCodeTool({
  tools: myTools,
  executor,
});

return generateText({
  model,
  messages,
  tools: { codemode },
});
</code></pre>
            <p>The Code Mode SDK also provides two server-side utility functions. <code>codeMcpServer({ server, executor })</code> wraps an existing MCP Server, replacing its tool surface with a single <code>code()</code> tool. <code>openApiMcpServer({ spec, executor, request })</code> goes further: given an OpenAPI spec and an executor, it builds a complete MCP Server with <code>search()</code> and <code>execute()</code> tools as used by the Cloudflare MCP Server, and better suited to larger APIs.</p><p>In both cases, the code generated by the model runs inside Dynamic Workers, with calls to external services made over RPC bindings passed to the executor.</p><p><a href="https://www.npmjs.com/package/@cloudflare/codemode"><u>Learn more about the library and how to use it.</u></a> </p>
    <div>
      <h3>Bundling</h3>
      <a href="#bundling">
        
      </a>
    </div>
    <p>Dynamic Workers expect pre-bundled modules. <a href="https://www.npmjs.com/package/@cloudflare/worker-bundler"><code>@cloudflare/worker-bundler</code></a> handles that for you: give it source files and a <code>package.json</code>, and it resolves npm dependencies from the registry, bundles everything with <code>esbuild</code>, and returns the module map the Worker Loader expects.</p>
            <pre><code>import { createWorker } from "@cloudflare/worker-bundler";

const worker = env.LOADER.get("my-worker", async () =&gt; {
  const { mainModule, modules } = await createWorker({
    files: {
      "src/index.ts": `
        import { Hono } from 'hono';
        import { cors } from 'hono/cors';

        const app = new Hono();
        app.use('*', cors());
        app.get('/', (c) =&gt; c.text('Hello from Hono!'));
        app.get('/json', (c) =&gt; c.json({ message: 'It works!' }));

        export default app;
      `,
      "package.json": JSON.stringify({
        dependencies: { hono: "^4.0.0" }
      })
    }
  });

  return { mainModule, modules, compatibilityDate: "2026-01-01" };
});

await worker.getEntrypoint().fetch(request);
</code></pre>
            <p>It also supports full-stack apps via <code>createApp</code> — bundle a server Worker, client-side JavaScript, and static assets together, with built-in asset serving that handles content types, ETags, and SPA routing.</p><p><a href="https://www.npmjs.com/package/@cloudflare/worker-bundler"><u>Learn more about the library and how to use it.</u></a></p>
    <div>
      <h3>File manipulation</h3>
      <a href="#file-manipulation">
        
      </a>
    </div>
    <p><a href="https://www.npmjs.com/package/@cloudflare/shell"><code>@cloudflare/shell</code></a> gives your agent a virtual filesystem inside a Dynamic Worker. Agent code calls typed methods on a <code>state</code> object — read, write, search, replace, diff, glob, JSON query/update, archive — with structured inputs and outputs instead of string parsing.</p><p>Storage is backed by a durable <code>Workspace</code> (SQLite + R2), so files persist across executions. Coarse operations like <code>searchFiles</code>, <code>replaceInFiles</code>, and <code>planEdits</code> minimize RPC round-trips — the agent issues one call instead of looping over individual files. Batch writes are transactional by default: if any write fails, earlier writes roll back automatically.</p>
            <pre><code>import { Workspace } from "@cloudflare/shell";
import { stateTools } from "@cloudflare/shell/workers";
import { DynamicWorkerExecutor, resolveProvider } from "@cloudflare/codemode";

const workspace = new Workspace({
  sql: this.ctx.storage.sql, // Works with any DO's SqlStorage, D1, or custom SQL backend
  r2: this.env.MY_BUCKET, // large files spill to R2 automatically
  name: () =&gt; this.name   // lazy — resolved when needed, not at construction
});

// Code runs in an isolated Worker sandbox with no network access
const executor = new DynamicWorkerExecutor({ loader: env.LOADER });

// The LLM writes this code; `state.*` calls dispatch back to the host via RPC
const result = await executor.execute(
  `async () =&gt; {
    // Search across all TypeScript files for a pattern
    const hits = await state.searchFiles("src/**/*.ts", "answer");
    // Plan multiple edits as a single transaction
    const plan = await state.planEdits([
      { kind: "replace", path: "/src/app.ts",
        search: "42", replacement: "43" },
      { kind: "writeJson", path: "/src/config.json",
        value: { version: 2 } }
    ]);
    // Apply atomically — rolls back on failure
    return await state.applyEditPlan(plan);
  }`,
  [resolveProvider(stateTools(workspace))]
);</code></pre>
            <p>The package also ships prebuilt TypeScript type declarations and a system prompt template, so you can drop the full <code>state</code> API into your LLM context in a handful of tokens.</p><p><a href="https://www.npmjs.com/package/@cloudflare/shell"><u>Learn more about the library and how to use it.</u></a></p>
    <div>
      <h2>How are people using it?</h2>
      <a href="#how-are-people-using-it">
        
      </a>
    </div>
    
    <div>
      <h4>Code Mode</h4>
      <a href="#code-mode">
        
      </a>
    </div>
    <p>Developers want their agents to write and execute code against tool APIs, rather than making sequential tool calls one at a time. With Dynamic Workers, the LLM generates a single TypeScript function that chains multiple API calls together, runs it in a Dynamic Worker, and returns the final result back to the agent. As a result, only the output, and not every intermediate step, ends up in the context window. This cuts both latency and token usage, and produces better results, especially when the tool surface is large.</p><p>Our own <a href="https://github.com/cloudflare/mcp-server-cloudflare">Cloudflare MCP server</a> is built exactly this way: it exposes the entire Cloudflare API through just two tools — search and execute — in under 1,000 tokens, because the agent writes code against a typed API instead of navigating hundreds of individual tool definitions.</p>
    <div>
      <h4>Building custom automations </h4>
      <a href="#building-custom-automations">
        
      </a>
    </div>
    <p>Developers are using Dynamic Workers to let agents build custom automations on the fly. <a href="https://www.zite.com/"><u>Zite</u></a>, for example, is building an app platform where users interact through a chat interface — the LLM writes TypeScript behind the scenes to build CRUD apps, connect to services like Stripe, Airtable, and Google Calendar, and run backend logic, all without the user ever seeing a line of code. Every automation runs in its own Dynamic Worker, with access to only the specific services and libraries that the endpoint needs.</p><blockquote><p><i>“To enable server-side code for Zite’s LLM-generated apps, we needed an execution layer that was instant, isolated, and secure. Cloudflare’s Dynamic Workers hit the mark on all three, and out-performed all of the other platforms we benchmarked for speed and library support. The NodeJS compatible runtime supported all of Zite’s workflows, allowing hundreds of third party integrations, without sacrificing on startup time. Zite now services millions of execution requests daily thanks to Dynamic Workers.” </i></p><p><i>— </i><b><i>Antony Toron</i></b><i>, CTO and Co-Founder, Zite </i></p></blockquote>
    <div>
      <h4>Running AI-generated applications</h4>
      <a href="#running-ai-generated-applications">
        
      </a>
    </div>
    <p>Developers are building platforms that generate full applications from AI — either for their customers or for internal teams building prototypes. With Dynamic Workers, each app can be spun up on demand, then put back into cold storage until it's invoked again. Fast startup times make it easy to preview changes during active development. Platforms can also block or intercept any network requests the generated code makes, keeping AI-generated apps safe to run.</p>
    <div>
      <h2>Pricing</h2>
      <a href="#pricing">
        
      </a>
    </div>
    <p>Dynamically-loaded Workers are priced at $0.002 per unique Worker loaded per day (as of this post’s publication), in addition to the usual CPU time and invocation pricing of regular Workers.</p><p>For AI-generated "code mode" use cases, where every Worker is a unique one-off, this means the price is $0.002 per Worker loaded (plus CPU and invocations). This cost is typically negligible compared to the inference costs to generate the code.</p><p>During the beta period, the $0.002 charge is waived. As pricing is subject to change, please always check our Dynamic Workers <a href="https://developers.cloudflare.com/dynamic-workers/pricing/"><u>pricing</u></a> for the most current information. </p>
    <div>
      <h2>Get Started</h2>
      <a href="#get-started">
        
      </a>
    </div>
    <p>If you’re on the Workers Paid plan, you can start using <a href="https://developers.cloudflare.com/dynamic-workers/">Dynamic Workers</a> today. </p>
    <div>
      <h4>Dynamic Workers Starter</h4>
      <a href="#dynamic-workers-starter">
        
      </a>
    </div>
    <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
<p>Use this “hello world” <a href="https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers">starter</a> to get a Worker deployed that can load and execute Dynamic Workers. </p>
    <div>
      <h4>Dynamic Workers Playground</h4>
      <a href="#dynamic-workers-playground">
        
      </a>
    </div>
    <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>You can also deploy the <a href="https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground">Dynamic Workers Playground</a>, where you’ll be able to write or import code, bundle it at runtime with <code>@cloudflare/worker-bundler</code>, execute it through a Dynamic Worker, see real-time responses and execution logs. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/32d0ficYALnSneKc4jZPja/0d4d07d747fc14936f16071714b7a8e5/BLOG-3243_2.png" />
          </figure><p>Dynamic Workers are fast, scalable, and lightweight. <a href="https://discord.com/channels/595317990191398933/1460655307255578695"><u>Find us on Discord</u></a> if you have any questions. We’d love to see what you build!</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/mQOJLnMtXULmj6l3DgKZg/ef2ee4cef616bc2d9a7caf35df5834f5/BLOG-3243_3.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Workers AI]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">1tc7f8AggVLw5D8OmaZri5</guid>
            <dc:creator>Kenton Varda</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
            <dc:creator>Ketan Gupta</dc:creator>
        </item>
        <item>
            <title><![CDATA[Code Mode: the better way to use MCP]]></title>
            <link>https://blog.cloudflare.com/code-mode/</link>
            <pubDate>Fri, 26 Sep 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ It turns out we've all been using MCP wrong. Most agents today use MCP by exposing the "tools" directly to the LLM. ]]></description>
            <content:encoded><![CDATA[ <p>It turns out we've all been using MCP wrong.</p><p>Most agents today use MCP by directly exposing the "tools" to the <a href="https://www.cloudflare.com/learning/ai/what-is-large-language-model/"><u>LLM</u></a>.</p><p>We tried something different: Convert the MCP tools into a TypeScript API, and then ask an LLM to write code that calls that API.</p><p>The results are striking:</p><ol><li><p>We found agents are able to handle many more tools, and more complex tools, when those tools are presented as a TypeScript API rather than directly. Perhaps this is because LLMs have an enormous amount of real-world TypeScript in their training set, but only a small set of contrived examples of tool calls.</p></li><li><p>The approach really shines when an agent needs to string together multiple calls. With the traditional approach, the output of each tool call must feed into the LLM's neural network, just to be copied over to the inputs of the next call, wasting time, energy, and tokens. When the LLM can write code, it can skip all that, and only read back the final results it needs.</p></li></ol><p>In short, LLMs are better at writing code to call MCP, than at calling MCP directly.</p>
    <div>
      <h2>What's MCP?</h2>
      <a href="#whats-mcp">
        
      </a>
    </div>
    <p>For those that aren't familiar: <a href="https://modelcontextprotocol.io/docs/getting-started/intro"><u>Model Context Protocol</u></a> is a standard protocol for giving AI agents access to external tools, so that they can directly perform work, rather than just chat with you.</p><p>Seen another way, MCP is a uniform way to:</p><ul><li><p>expose an API for doing something,</p></li><li><p>along with documentation needed for an LLM to understand it,</p></li><li><p>with authorization handled out-of-band.</p></li></ul><p>MCP has been making waves throughout 2025 as it has suddenly greatly expanded the capabilities of AI agents.</p><p>The "API" exposed by an MCP server is expressed as a set of "tools". Each tool is essentially a remote procedure call (RPC) function – it is called with some parameters and returns a response. Most modern LLMs have <a href="https://developers.cloudflare.com/workers-ai/features/function-calling/"><u>the capability to use "tools" (sometimes called "function calling")</u></a>, meaning they are trained to output text in a certain format when they want to invoke a tool. The program invoking the LLM sees this format and invokes the tool as specified, then feeds the results back into the LLM as input.</p>
    <div>
      <h3>Anatomy of a tool call</h3>
      <a href="#anatomy-of-a-tool-call">
        
      </a>
    </div>
    <p>Under the hood, an LLM generates a stream of "tokens" representing its output. A token might represent a word, a syllable, some sort of punctuation, or some other component of text.</p><p>A tool call, though, involves a token that does <i>not</i> have any textual equivalent. The LLM is trained (or, more often, fine-tuned) to understand a special token that it can output that means "the following should be interpreted as a tool call," and another special token that means "this is the end of the tool call." Between these two tokens, the LLM will typically write tokens corresponding to some sort of JSON message that describes the call.</p><p>For instance, imagine you have connected an agent to an MCP server that provides weather info, and you then ask the agent what the weather is like in Austin, TX. Under the hood, the LLM might generate output like the following. Note that here we've used words in <code>&lt;|</code> and <code>|&gt;</code> to represent our special tokens, but in fact, these tokens do not represent text at all; this is just for illustration.</p><p>I will use the Weather MCP server to find out the weather in Austin, TX.</p>
            <pre><code>I will use the Weather MCP server to find out the weather in Austin, TX.

&lt;|tool_call|&gt;
{
  "name": "get_current_weather",
  "arguments": {
    "location": "Austin, TX, USA"
  }
}
&lt;|end_tool_call|&gt;</code></pre>
            <p>Upon seeing these special tokens in the output, the LLM's harness will interpret the sequence as a tool call. After seeing the end token, the harness pauses execution of the LLM. It parses the JSON message and returns it as a separate component of the structured API result. The agent calling the LLM API sees the tool call, invokes the relevant MCP server, and then sends the results back to the LLM API. The LLM's harness will then use another set of special tokens to feed the result back into the LLM:</p>
            <pre><code>&lt;|tool_result|&gt;
{
  "location": "Austin, TX, USA",
  "temperature": 93,
  "unit": "fahrenheit",
  "conditions": "sunny"
}
&lt;|end_tool_result|&gt;</code></pre>
            <p>The LLM reads these tokens in exactly the same way it would read input from the user – except that the user cannot produce these special tokens, so the LLM knows it is the result of the tool call. The LLM then continues generating output like normal.</p><p>Different LLMs may use different formats for tool calling, but this is the basic idea.</p>
    <div>
      <h3>What's wrong with this?</h3>
      <a href="#whats-wrong-with-this">
        
      </a>
    </div>
    <p>The special tokens used in tool calls are things LLMs have never seen in the wild. They must be specially trained to use tools, based on synthetic training data. They aren't always that good at it. If you present an LLM with too many tools, or overly complex tools, it may struggle to choose the right one or to use it correctly. As a result, MCP server designers are encouraged to present greatly simplified APIs as compared to the more traditional API they might expose to developers.</p><p>Meanwhile, LLMs are getting really good at writing code. In fact, LLMs asked to write code against the full, complex APIs normally exposed to developers don't seem to have too much trouble with it. Why, then, do MCP interfaces have to "dumb it down"? Writing code and calling tools are almost the same thing, but it seems like LLMs can do one much better than the other?</p><p>The answer is simple: LLMs have seen a lot of code. They have not seen a lot of "tool calls". In fact, the tool calls they have seen are probably limited to a contrived training set constructed by the LLM's own developers, in order to try to train it. Whereas they have seen real-world code from millions of open source projects.</p><p><b><i>Making an LLM perform tasks with tool calling is like putting Shakespeare through a month-long class in Mandarin and then asking him to write a play in it. It's just not going to be his best work.</i></b></p>
    <div>
      <h3>But MCP is still useful, because it is uniform</h3>
      <a href="#but-mcp-is-still-useful-because-it-is-uniform">
        
      </a>
    </div>
    <p>MCP is designed for tool-calling, but it doesn't actually <i>have to</i> be used that way.</p><p>The "tools" that an MCP server exposes are really just an RPC interface with attached documentation. We don't really <i>have to</i> present them as tools. We can take the tools, and turn them into a programming language API instead.</p><p>But why would we do that, when the programming language APIs already exist independently? Almost every MCP server is just a wrapper around an existing traditional API – why not expose those APIs?</p><p>Well, it turns out MCP does something else that's really useful: <b>It provides a uniform way to connect to and learn about an API.</b></p><p>An AI agent can use an MCP server even if the agent's developers never heard of the particular MCP server, and the MCP server's developers never heard of the particular agent. This has rarely been true of traditional APIs in the past. Usually, the client developer always knows exactly what API they are coding for. As a result, every API is able to do things like basic connectivity, authorization, and documentation a little bit differently.</p><p>This uniformity is useful even when the AI agent is writing code. We'd like the AI agent to run in a sandbox such that it can only access the tools we give it. MCP makes it possible for the agentic framework to implement this, by handling connectivity and authorization in a standard way, independent of the AI code. We also don't want the AI to have to search the Internet for documentation; MCP provides it directly in the protocol.</p>
    <div>
      <h2>OK, how does it work?</h2>
      <a href="#ok-how-does-it-work">
        
      </a>
    </div>
    <p>We have already extended the <a href="https://developers.cloudflare.com/agents/"><u>Cloudflare Agents SDK</u></a> to support this new model!</p><p>For example, say you have an app built with ai-sdk that looks like this:</p>
            <pre><code>const stream = streamText({
  model: openai("gpt-5"),
  system: "You are a helpful assistant",
  messages: [
    { role: "user", content: "Write a function that adds two numbers" }
  ],
  tools: {
    // tool definitions 
  }
})</code></pre>
            <p>You can wrap the tools and prompt with the codemode helper, and use them in your app: </p>
            <pre><code>import { codemode } from "agents/codemode/ai";

const {system, tools} = codemode({
  system: "You are a helpful assistant",
  tools: {
    // tool definitions 
  },
  // ...config
})

const stream = streamText({
  model: openai("gpt-5"),
  system,
  tools,
  messages: [
    { role: "user", content: "Write a function that adds two numbers" }
  ]
})</code></pre>
            <p>With this change, your app will now start generating and running code that itself will make calls to the tools you defined, MCP servers included. We will introduce variants for other libraries in the very near future. <a href="https://github.com/cloudflare/agents/blob/main/docs/codemode.md"><u>Read the docs</u></a> for more details and examples. </p>
    <div>
      <h3>Converting MCP to TypeScript</h3>
      <a href="#converting-mcp-to-typescript">
        
      </a>
    </div>
    <p>When you connect to an MCP server in "code mode", the Agents SDK will fetch the MCP server's schema, and then convert it into a TypeScript API, complete with doc comments based on the schema.</p><p>For example, connecting to the MCP server at <a href="https://gitmcp.io/cloudflare/agents"><u>https://gitmcp.io/cloudflare/agents</u></a>, will generate a TypeScript definition like this:</p>
            <pre><code>interface FetchAgentsDocumentationInput {
  [k: string]: unknown;
}
interface FetchAgentsDocumentationOutput {
  [key: string]: any;
}

interface SearchAgentsDocumentationInput {
  /**
   * The search query to find relevant documentation
   */
  query: string;
}
interface SearchAgentsDocumentationOutput {
  [key: string]: any;
}

interface SearchAgentsCodeInput {
  /**
   * The search query to find relevant code files
   */
  query: string;
  /**
   * Page number to retrieve (starting from 1). Each page contains 30
   * results.
   */
  page?: number;
}
interface SearchAgentsCodeOutput {
  [key: string]: any;
}

interface FetchGenericUrlContentInput {
  /**
   * The URL of the document or page to fetch
   */
  url: string;
}
interface FetchGenericUrlContentOutput {
  [key: string]: any;
}

declare const codemode: {
  /**
   * Fetch entire documentation file from GitHub repository:
   * cloudflare/agents. Useful for general questions. Always call
   * this tool first if asked about cloudflare/agents.
   */
  fetch_agents_documentation: (
    input: FetchAgentsDocumentationInput
  ) =&gt; Promise&lt;FetchAgentsDocumentationOutput&gt;;

  /**
   * Semantically search within the fetched documentation from
   * GitHub repository: cloudflare/agents. Useful for specific queries.
   */
  search_agents_documentation: (
    input: SearchAgentsDocumentationInput
  ) =&gt; Promise&lt;SearchAgentsDocumentationOutput&gt;;

  /**
   * Search for code within the GitHub repository: "cloudflare/agents"
   * using the GitHub Search API (exact match). Returns matching files
   * for you to query further if relevant.
   */
  search_agents_code: (
    input: SearchAgentsCodeInput
  ) =&gt; Promise&lt;SearchAgentsCodeOutput&gt;;

  /**
   * Generic tool to fetch content from any absolute URL, respecting
   * robots.txt rules. Use this to retrieve referenced urls (absolute
   * urls) that were mentioned in previously fetched documentation.
   */
  fetch_generic_url_content: (
    input: FetchGenericUrlContentInput
  ) =&gt; Promise&lt;FetchGenericUrlContentOutput&gt;;
};</code></pre>
            <p>This TypeScript is then loaded into the agent's context. Currently, the entire API is loaded, but future improvements could allow an agent to search and browse the API more dynamically – much like an agentic coding assistant would.</p>
    <div>
      <h3>Running code in a sandbox</h3>
      <a href="#running-code-in-a-sandbox">
        
      </a>
    </div>
    <p>Instead of being presented with all the tools of all the connected MCP servers, our agent is presented with just one tool, which simply executes some TypeScript code.</p><p>The code is then executed in a secure sandbox. The sandbox is totally isolated from the Internet. Its only access to the outside world is through the TypeScript APIs representing its connected MCP servers.</p><p>These APIs are backed by RPC invocation which calls back to the agent loop. There, the Agents SDK dispatches the call to the appropriate MCP server.</p><p>The sandboxed code returns results to the agent in the obvious way: by invoking <code>console.log()</code>. When the script finishes, all the output logs are passed back to the agent.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6DRERHP138FSj3GG0QYj3M/99e8c09b352560b7d4547ca299482c27/image2.png" />
          </figure>
    <div>
      <h2>Dynamic Worker loading: no containers here</h2>
      <a href="#dynamic-worker-loading-no-containers-here">
        
      </a>
    </div>
    <p>This new approach requires access to a secure sandbox where arbitrary code can run. So where do we find one? Do we have to run containers? Is that expensive?</p><p>No. There are no containers. We have something much better: isolates.</p><p>The Cloudflare Workers platform has always been based on V8 isolates, that is, isolated JavaScript runtimes powered by the <a href="https://v8.dev/"><u>V8 JavaScript engine</u></a>.</p><p><b>Isolates are far more lightweight than containers.</b> An isolate can start in a handful of milliseconds using only a few megabytes of memory.</p><p>Isolates are so fast that we can just create a new one for every piece of code the agent runs. There's no need to reuse them. There's no need to prewarm them. Just create it, on demand, run the code, and throw it away. It all happens so fast that the overhead is negligible; it's almost as if you were just eval()ing the code directly. But with security.</p>
    <div>
      <h3>The Worker Loader API</h3>
      <a href="#the-worker-loader-api">
        
      </a>
    </div>
    <p>Until now, though, there was no way for a Worker to directly load an isolate containing arbitrary code. All Worker code instead had to be uploaded via the Cloudflare API, which would then deploy it globally, so that it could run anywhere. That's not what we want for Agents! We want the code to just run right where the agent is.</p><p>To that end, we've added a new API to the Workers platform: the <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Worker Loader API</u></a>. With it, you can load Worker code on-demand. Here's what it looks like:</p>
            <pre><code>// Gets the Worker with the given ID, creating it if no such Worker exists yet.
let worker = env.LOADER.get(id, async () =&gt; {
  // If the Worker does not already exist, this callback is invoked to fetch
  // its code.

  return {
    compatibilityDate: "2025-06-01",

    // Specify the worker's code (module files).
    mainModule: "foo.js",
    modules: {
      "foo.js":
        "export default {\n" +
        "  fetch(req, env, ctx) { return new Response('Hello'); }\n" +
        "}\n",
    },

    // Specify the dynamic Worker's environment (`env`).
    env: {
      // It can contain basic serializable data types...
      SOME_NUMBER: 123,

      // ... and bindings back to the parent worker's exported RPC
      // interfaces, using the new `ctx.exports` loopback bindings API.
      SOME_RPC_BINDING: ctx.exports.MyBindingImpl({props})
    },

    // Redirect the Worker's `fetch()` and `connect()` to proxy through
    // the parent worker, to monitor or filter all Internet access. You
    // can also block Internet access completely by passing `null`.
    globalOutbound: ctx.exports.OutboundProxy({props}),
  };
});

// Now you can get the Worker's entrypoint and send requests to it.
let defaultEntrypoint = worker.getEntrypoint();
await defaultEntrypoint.fetch("http://example.com");

// You can get non-default entrypoints as well, and specify the
// `ctx.props` value to be delivered to the entrypoint.
let someEntrypoint = worker.getEntrypoint("SomeEntrypointClass", {
  props: {someProp: 123}
});</code></pre>
            <p>You can start playing with this API right now when running <code>workerd</code> locally with Wrangler (<a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>check out the docs</u></a>), and you can <a href="https://forms.gle/MoeDxE9wNiqdf8ri9"><u>sign up for beta access</u></a> to use it in production.</p>
    <div>
      <h2>Workers are better sandboxes</h2>
      <a href="#workers-are-better-sandboxes">
        
      </a>
    </div>
    <p>The design of Workers makes it unusually good at sandboxing, especially for this use case, for a few reasons:</p>
    <div>
      <h3>Faster, cheaper, disposable sandboxes</h3>
      <a href="#faster-cheaper-disposable-sandboxes">
        
      </a>
    </div>
    <p><a href="https://developers.cloudflare.com/workers/reference/how-workers-works/"><u>The Workers platform uses isolates instead of containers.</u></a> Isolates are much lighter-weight and faster to start up. It takes mere milliseconds to start a fresh isolate, and it's so cheap we can just create a new one for every single code snippet the agent generates. There's no need to worry about pooling isolates for reuse, prewarming, etc.</p><p>We have not yet finalized pricing for the Worker Loader API, but because it is based on isolates, we will be able to offer it at a significantly lower cost than container-based solutions.</p>
    <div>
      <h3>Isolated by default, but connected with bindings</h3>
      <a href="#isolated-by-default-but-connected-with-bindings">
        
      </a>
    </div>
    <p>Workers are just better at handling isolation.</p><p>In Code Mode, we prohibit the sandboxed worker from talking to the Internet. The global <code>fetch()</code> and <code>connect()</code> functions throw errors.</p><p>But on most platforms, this would be a problem. On most platforms, the way you get access to private resources is, you <i>start</i> with general network access. Then, using that network access, you send requests to specific services, passing them some sort of API key to authorize private access.</p><p>But Workers has always had a better answer. In Workers, the "environment" (<code>env</code> object) doesn't just contain strings, <a href="https://blog.cloudflare.com/workers-environment-live-object-bindings/"><u>it contains live objects</u></a>, also known as "bindings". These objects can provide direct access to private resources without involving generic network requests.</p><p>In Code Mode, we give the sandbox access to bindings representing the MCP servers it is connected to. Thus, the agent can specifically access those MCP servers <i>without</i> having network access in general.</p><p>Limiting access via bindings is much cleaner than doing it via, say, network-level filtering or HTTP proxies. Filtering is hard on both the LLM and the supervisor, because the boundaries are often unclear: the supervisor may have a hard time identifying exactly what traffic is legitimately necessary to talk to an API. Meanwhile, the LLM may have difficulty guessing what kinds of requests will be blocked. With the bindings approach, it's well-defined: the binding provides a JavaScript interface, and that interface is allowed to be used. It's just better this way.</p>
    <div>
      <h3>No API keys to leak</h3>
      <a href="#no-api-keys-to-leak">
        
      </a>
    </div>
    <p>An additional benefit of bindings is that they hide API keys. The binding itself provides an already-authorized client interface to the MCP server. All calls made on it go to the agent supervisor first, which holds the access tokens and adds them into requests sent on to MCP.</p><p>This means that the AI cannot possibly write code that leaks any keys, solving a common security problem seen in AI-authored code today.</p>
    <div>
      <h2>Try it now!</h2>
      <a href="#try-it-now">
        
      </a>
    </div>
    
    <div>
      <h3>Sign up for the production beta</h3>
      <a href="#sign-up-for-the-production-beta">
        
      </a>
    </div>
    <p>The Dynamic Worker Loader API is in closed beta. To use it in production, <a href="https://forms.gle/MoeDxE9wNiqdf8ri9"><u>sign up today</u></a>.</p>
    <div>
      <h3>Or try it locally</h3>
      <a href="#or-try-it-locally">
        
      </a>
    </div>
    <p>If you just want to play around, though, Dynamic Worker Loading is fully available today when developing locally with Wrangler and <code>workerd</code> – check out the docs for <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Dynamic Worker Loading</u></a> and <a href="https://github.com/cloudflare/agents/blob/main/docs/codemode.md"><u>code mode in the Agents SDK</u></a> to get started.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[MCP]]></category>
            <guid isPermaLink="false">61nEdL3TSdS4diA4x21O5e</guid>
            <dc:creator>Kenton Varda</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
        <item>
            <title><![CDATA[Building agents with OpenAI and Cloudflare’s Agents SDK]]></title>
            <link>https://blog.cloudflare.com/building-agents-with-openai-and-cloudflares-agents-sdk/</link>
            <pubDate>Wed, 25 Jun 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ We’re building AI agents where logic and reasoning are handled by OpenAI’s Agents SDK, and execution happens across Cloudflare's global network via Cloudflare’s Agents SDK.  ]]></description>
            <content:encoded><![CDATA[ 
    <div>
      <h2>What even <i>is</i> an Agents SDK?</h2>
      <a href="#what-even-is-an-agents-sdk">
        
      </a>
    </div>
    <p>The AI landscape is evolving at an incredible pace, and with it, the tools and platforms available to developers are becoming more powerful and interconnected than ever. Here at Cloudflare, we're genuinely passionate about empowering you to build the next generation of applications, and that absolutely includes intelligent agents that can reason, act, and interact with the world.</p><p>When we talk about "<b>Agents SDKs</b>", it can sometimes feel a bit… fuzzy. Some SDKs (software development kits) <b>described as 'agent' SDKs</b> are really about providing frameworks for tool calling and interacting with models. They're fantastic for defining an agent's "brain" – its intelligence, its ability to reason, and how it uses external tools. Here’s the thing: all these agents need a place to actually run. Then there's what we offer at Cloudflare: <a href="https://developers.cloudflare.com/agents/"><u>an SDK purpose-built to provide a seamless execution layer for agents</u></a>. While orchestration frameworks define how agents think, our SDK focuses on where they run, abstracting away infrastructure to enable persistent, scalable execution across our global network.</p><p>Think of it as the ultimate shell, the place where any agent, defined by any agent SDK (like the powerful new OpenAI Agents SDK), can truly live, persist, and run at global scale.</p><p>We’ve chosen OpenAI’s Agents SDK for this example, but the infrastructure is not specific to it. The execution layer is designed to integrate with any agent runtime.</p><p>That’s what this post is about: what we built, what we learned, and the design patterns that emerged from fusing these two pieces together.</p>
    <div>
      <h2>Why use two SDKs?</h2>
      <a href="#why-use-two-sdks">
        
      </a>
    </div>
    <p><a href="https://openai.github.io/openai-agents-js/"><u>OpenAI’s Agents SDK</u></a> gives you the <i>agent</i>: a reasoning loop, tool definitions, and memory abstraction. But it assumes you bring your own runtime and state.</p><p><a href="https://developers.cloudflare.com/agents/"><u>Cloudflare’s Agents SDK</u></a> gives you the <i>environment</i>: a persistent object on our network with identity, state, and built-in concurrency control. But it doesn’t tell you how your agent should behave.</p><p>By combining them, we get a clear split:</p><ul><li><p><b>OpenAI</b>: cognition, planning, tool orchestration</p></li><li><p><b>Cloudflare</b>: location, identity, memory, execution</p></li></ul><p>This separation of concerns let us stay focused on logic, not glue code.</p>
    <div>
      <h2>What you can build with persistent agents</h2>
      <a href="#what-you-can-build-with-persistent-agents">
        
      </a>
    </div>
    <p>Cloudflare <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> let agents go beyond simple, stateless functions. They can persist memory, coordinate across workflows, and respond in real time. Combined with the OpenAI Agents SDK, this enables systems that reason, remember, and adapt over time.</p><p>Here are three architectural patterns that show how agents can be composed, guided, and connected:</p><p><b>Multi-agent systems: </b>Divide responsibilities across specialized agents that collaborate on tasks.</p><p><b>Human-in-the-loop: </b>Let agents plan independently but wait for human input at key decision points.</p><p><b>Addressable agents: </b>Make agents reachable through real-world interfaces like phone calls or WebSockets.</p>
    <div>
      <h3>Multi-agent systems </h3>
      <a href="#multi-agent-systems">
        
      </a>
    </div>
    <p>Multi-agent systems let you break down a task into specialized agents that handle distinct responsibilities. In the example below, a triage agent routes questions to either a history or math tutor based on the query. Each agent has its own memory, logic, and instructions. With Cloudflare <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a>, these agents persist across sessions and can coordinate responses, making it easy to build systems that feel modular but work together intelligently.</p>
            <pre><code>export class MyAgent extends Agent {
  async onRequest() {
    const historyTutorAgent = new Agent({
      instructions:
        "You provide assistance with historical queries. Explain important events and context clearly.",
      name: "History Tutor",
    });

    const mathTutorAgent = new Agent({
      instructions:
        "You provide help with math problems. Explain your reasoning at each step and include examples",
      name: "Math Tutor",
    });

    const triageAgent = new Agent({
      handoffs: [historyTutorAgent, mathTutorAgent],
      instructions:
        "You determine which agent to use based on the user's homework question",
      name: "Triage Agent",
    });

    const result = await run(triageAgent, "What is the capital of France?");
    return Response.json(result.finalOutput);
  }
}</code></pre>
            
    <div>
      <h3>Human-in-the-loop</h3>
      <a href="#human-in-the-loop">
        
      </a>
    </div>
    <p>We implemented a<a href="https://github.com/cloudflare/agents/tree/main/openai-sdk/human-in-the-loop"> <u>human-in-the-loop agent example</u></a> using these two SDKs together. The goal: run an OpenAI agent with a planning loop, allow human decisions to intercept the plan, and preserve state across invocations via Durable Objects.</p><p>The architecture looked like this:</p><ul><li><p>An OpenAI <code>Agent</code> instance runs inside a Durable Object</p></li><li><p>User submits a prompt</p></li><li><p>The agent plans multiple steps</p></li><li><p>After each step, it yields control and waits for a human to approve or intervene</p></li><li><p>State (including memory and intermediate steps) is persisted in <code>this.state</code></p></li></ul><p>It looks like this:</p>
            <pre><code>export class MyAgent extends Agent {
  // ...
  async onStart() {
    if (this.state.serialisedRunState) {
      const runState = await RunState.fromString(
        this.agent,
        this.state.serialisedRunState
      );
      this.result = await run(this.agent, runState);</code></pre>
            <p>This design lets us intercept the agent’s plan at every step and store it. The client could then:</p><ul><li><p>Fetch the pending step via another route</p></li><li><p>Review or modify it</p></li><li><p>Send approval or rejection back to the agent to resume execution</p></li></ul><p>This is only possible because the agent lives inside a Durable Object. It has persistent memory and identity, allowing multi-turn interaction even across sessions</p>
    <div>
      <h3>Addressable agents: “Call my Agent”</h3>
      <a href="#addressable-agents-call-my-agent">
        
      </a>
    </div>
    <p>One of the most interesting takeaways from this pattern is that agents are not just HTTP endpoints. Yes, you can <code>fetch() </code>them via Durable Objects, but conceptually, <b>agents are addressable entities</b> — and there's no reason those addresses have to be tied to URLs.</p><p>You could imagine agents reachable by phone call, by email, or via pub/sub systems. Durable Objects give each agent a global identity that can be referenced however you want.</p><p>In this design:</p><ul><li><p>External sources of input connect to the Cloudflare network; via email, HTTP, or any network interface. In this demo, we use Twilio to route a phone call to a WebSocket input on the Agent.</p></li><li><p>The call is routed through Cloudflare’s infrastructure, so latency is low and identity is preserved.</p></li><li><p>We also store the real-time state updates within the agent, so we can view it on a website (served by the agent itself). This is great for use cases like customer service and education. </p></li></ul>
            <pre><code>export class MyAgent extends Agent {
  // receive phone calls via websocket
  async onConnect(connection: Connection, ctx: ConnectionContext) {
    if (ctx.request.url.includes("media-stream")) {
      const agent = new RealtimeAgent({
        instructions:
          "You are a helpful assistant that starts every conversation with a creative greeting.",
        name: "Triage Agent",
      });

      connection.send(`Welcome! You are connected with ID: ${connection.id}`);

      const twilioTransportLayer = new TwilioRealtimeTransportLayer({
        twilioWebSocket: connection,
      });

      const session = new RealtimeSession(agent, {
        transport: twilioTransportLayer,
      });

      await session.connect({
        apiKey: process.env.OPENAI_API_KEY as string,
      });

      session.on("history_updated", (history) =&gt; {
        this.setState({ history });
      });
    }
  }
}</code></pre>
            <p>This lets an agent become truly multimodal, accepting and outputting data as audio, video, text, email. This pattern opened up exciting possibilities for modular agents and long-running workflows where each agent focuses on a specific domain.</p>
    <div>
      <h2>What we learned (and what you should know)</h2>
      <a href="#what-we-learned-and-what-you-should-know">
        
      </a>
    </div>
    
    <div>
      <h3>1. OpenAI assumes you bring your own state — Cloudflare gives you one</h3>
      <a href="#1-openai-assumes-you-bring-your-own-state-cloudflare-gives-you-one">
        
      </a>
    </div>
    <p>OpenAI’s SDK is stateless by default. You can attach memory abstractions, but the SDK doesn’t tell you where or how to persist it. Cloudflare’s Durable Objects, by contrast, <i>are</i> persistent — that’s the whole point. Every instance has a unique identity and storage API <code>(this.ctx.storage)</code>. This means we can:</p><ul><li><p>Store long-term memory across invocations</p></li><li><p>Hydrate the agent’s memory before <code>run()</code></p></li><li><p>Save any updates after <code>run()</code> completes</p></li></ul>
    <div>
      <h3>2. Durable Object routing isn’t just routing — it’s your agent factory</h3>
      <a href="#2-durable-object-routing-isnt-just-routing-its-your-agent-factory">
        
      </a>
    </div>
    <p>At first glance, <code>routeAgentRequest</code> looks like a simple dispatcher: map a request to a Durable Object based on a URL. But it plays a deeper role — it defines the identity boundary for your agents. We realized this while trying to scope agent instances per user and per task.</p><p>In Durable Objects, identity is tied to an ID. When you call <code>idFromName()</code>, you get a stable, name-based ID that always maps to the same object. This means repeated calls with the same name return the same agent instance — along with its memory and state. In contrast, calling <code>.newUniqueId()</code> creates a new, isolated object each time.</p><p>This is where routing becomes critical: it's where you decide how long an agent should live, and what it should remember.</p><p>This lets us:</p><ul><li><p>Spin up multiple agents per user (e.g. one per session or task)</p></li><li><p>Co-locate memory and logic</p></li><li><p>Avoid unintended memory sharing between conversations</p></li></ul><p><b>Gotcha:</b> If you forget to use <code>idFromName()</code> and just call <code>.newUniqueId()</code>, you’ll get a new agent each time, and your memory will never persist. This is a common early bug that silently kills statefulness.</p>
    <div>
      <h3>​​3. Agents are composable — and that’s powerful</h3>
      <a href="#3-agents-are-composable-and-thats-powerful">
        
      </a>
    </div>
    <p>Agents can invoke each other using Durable Object routing, forming workflows where each agent owns its own memory and logic. This enables composition — building systems from specialized parts that cooperate.</p><p>This makes agent architecture more like microservices — composable, stateful, and distributed.</p>
    <div>
      <h2>Final thoughts: building agents that think <i>and</i> live</h2>
      <a href="#final-thoughts-building-agents-that-think-and-live">
        
      </a>
    </div>
    <p>This pattern — OpenAI cognition + Cloudflare execution — worked better than we expected. It let us:</p><ul><li><p>Write agents with full planning and memory</p></li><li><p>Pause and resume them asynchronously</p></li><li><p>Avoid building orchestration from scratch</p></li><li><p>Compose multiple agents into larger systems</p></li></ul><p>The hardest parts:</p><ul><li><p>Correctly scoping agent architecture</p></li><li><p>Persisting only valid state</p></li><li><p>Debugging with good observability</p></li></ul><p>At Cloudflare, we are incredibly excited to see what <i>you</i> build with this powerful combination. The future of AI agents is intelligent, distributed, and incredibly capable. Get started today by exploring the <a href="https://github.com/openai/openai-agents-js"><u>OpenAI Agents SDK</u></a> and diving into the <a href="https://developers.cloudflare.com/agents/"><u>Cloudflare Agents SDK documentation </u></a>(which leverages Cloudflare Workers and Durable Objects).</p><p>We’re just getting started, and we love to see all that you build. Please <a href="https://discord.com/invite/cloudflaredev"><u>join our Discord</u></a>, ask questions, and tell us what you’re building.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">3RJX3pjuKNyVyxPYsPBbGg</guid>
            <dc:creator>Kate Reznykova</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
        <item>
            <title><![CDATA[Connect any React application to an MCP server in three lines of code]]></title>
            <link>https://blog.cloudflare.com/connect-any-react-application-to-an-mcp-server-in-three-lines-of-code/</link>
            <pubDate>Wed, 18 Jun 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ We're open-sourcing use-mcp, a React library that connects to any MCP server in just 3 lines of code, as well as our AI Playground, a complete chat interface that can connect to remote MCP servers.  ]]></description>
            <content:encoded><![CDATA[ <p>You can <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>deploy</u></a> a <a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u>remote Model Context Protocol (MCP) server</u></a> on Cloudflare in just one-click. Don’t believe us? Click the button below. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>This will get you started with a remote MCP server that supports the latest MCP standards and is the reason why thousands of remote MCP servers have been deployed on Cloudflare, including ones from companies like <a href="https://blog.cloudflare.com/mcp-demo-day/"><u>Atlassian, Linear, PayPal, and more</u></a>. </p><p>But deploying servers is only half of the equation — we also wanted to make it just as easy to build and deploy remote MCP clients that can connect to these servers to enable new AI-powered service integrations. That's why we built <code>use-mcp</code>, a React library for connecting to remote MCP servers, and we're excited to contribute it to the MCP ecosystem to enable more developers to build remote MCP clients.</p><p>Today, we're open-sourcing two tools that make it easy to build and deploy MCP clients:</p><ol><li><p><a href="https://github.com/modelcontextprotocol/use-mcp"><u>use-mcp</u></a> — A React library that connects to any remote MCP server in just 3 lines of code, with transport, authentication, and session management automatically handled. We're excited to contribute this library to the <a href="https://github.com/modelcontextprotocol"><u>MCP ecosystem</u></a> to enable more developers to build remote MCP clients. </p></li><li><p><a href="https://github.com/cloudflare/ai/tree/main/playground/ai"><u>The AI Playground</u></a> — Cloudflare’s <a href="https://playground.ai.cloudflare.com/"><u>AI chat interface</u></a> platform that uses a number of LLM models to interact with remote MCP servers, with support for the latest MCP standard, which you can now deploy yourself. </p></li></ol><p>Whether you're building an AI-powered chat bot, a support agent, or an internal company interface, you can leverage these tools to connect your AI agents and applications to external services via MCP. </p><p>Ready to get started? Click on the button below to deploy your own instance of Cloudflare’s AI Playground to see it in action. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/playground/ai"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
    <div>
      <h2>use-mcp: a React library for building remote MCP clients</h2>
      <a href="#use-mcp-a-react-library-for-building-remote-mcp-clients">
        
      </a>
    </div>
    <p><a href="https://github.com/modelcontextprotocol/use-mcp"><u>use-mcp</u></a> is a <a href="https://www.npmjs.com/package/use-mcp"><u>React library</u></a> that abstracts away all the complexity of building MCP clients. Add the <code>useMCP()</code> hook into any React application to connect to remote MCP servers that users can interact with. </p><p>Here’s all the code you need to add to connect to a remote MCP server: </p>
            <pre><code>mport { useMcp } from 'use-mcp/react'
function MyComponent() {
  const { state, tools, callTool } = useMcp({
    url: 'https://mcp-server.example.com'
  })
  return &lt;div&gt;Your actual UI code&lt;/div&gt;
}</code></pre>
            <p>Just specify the URL, and you're instantly connected. </p><p>Behind the scenes, <code>use-mcp</code> handles the transport protocols (both Streamable HTTP and Server-Sent Events), authentication flows, and session management. It also includes a number of features to help you build reliable, scalable, and production-ready MCP clients. </p>
    <div>
      <h3>Connection management </h3>
      <a href="#connection-management">
        
      </a>
    </div>
    <p>Network reliability shouldn’t impact user experience. <code>use-mcp </code>manages connection retries and reconnections with a backoff schedule to ensure your client can recover the connection during a network issue and continue where it left off. The hook exposes real-time <a href="https://github.com/modelcontextprotocol/use-mcp/tree/main?tab=readme-ov-file#return-value"><u>connection states</u></a> ("connecting", "ready", "failed"), allowing you to build responsive UIs that keep users informed without requiring you to write any custom connection handling logic. </p>
            <pre><code>const { state } = useMcp({ url: 'https://mcp-server.example.com' })

if (state === 'connecting') {
  return &lt;div&gt;Establishing connection...&lt;/div&gt;
}
if (state === 'ready') {
  return &lt;div&gt;Connected and ready!&lt;/div&gt;
}
if (state === 'failed') {
  return &lt;div&gt;Connection failed&lt;/div&gt;
}</code></pre>
            
    <div>
      <h3>Authentication &amp; authorization</h3>
      <a href="#authentication-authorization">
        
      </a>
    </div>
    <p>Many MCP servers require some form of authentication in order to make tool calls. <code>use-mcp</code> supports <a href="https://oauth.net/2.1/"><u>OAuth 2.1</u></a> and handles the entire OAuth flow.  It redirects users to the login page, allows them to grant access, securely stores the access token returned by the OAuth provider, and uses it for all subsequent requests to the server. The library also provides <a href="https://github.com/modelcontextprotocol/use-mcp/tree/main?tab=readme-ov-file#api-reference"><u>methods</u></a> for users to revoke access and clear stored credentials. This gives you a complete authentication system that allows you to securely connect to remote MCP servers, without writing any of the logic. </p>
            <pre><code>const { clearStorage } = useMcp({ url: 'https://mcp-server.example.com' })

// Revoke access and clear stored credentials
const handleLogout = () =&gt; {
  clearStorage() // Removes all stored tokens, client info, and auth state
}</code></pre>
            
    <div>
      <h3>Dynamic tool discovery</h3>
      <a href="#dynamic-tool-discovery">
        
      </a>
    </div>
    <p>When you connect to an MCP server, <code>use-mcp</code> fetches the tools it exposes. If the server adds new capabilities, your app will see them without any code changes. Each tool provides type-safe metadata about its required inputs and functionality, so your client can automatically validate user input and make the right tool calls.</p>
    <div>
      <h3>Debugging &amp; monitoring capabilities</h3>
      <a href="#debugging-monitoring-capabilities">
        
      </a>
    </div>
    <p>To help you troubleshoot MCP integrations, <code>use-mcp </code>exposes a <code>log</code> array containing structured messages at debug, info, warn, and error levels, with timestamps for each one. You can enable detailed logging with the <code>debug</code> option to track tool calls, authentication flows, connection state changes, and errors. This real-time visibility makes it easier to diagnose issues during development and production. </p>
    <div>
      <h3>Future-proofed &amp; backwards compatible</h3>
      <a href="#future-proofed-backwards-compatible">
        
      </a>
    </div>
    <p>MCP is evolving rapidly, with recent updates to transport mechanisms and upcoming changes to authorization. <code>use-mcp</code> supports both Server-Sent Events (SSE) and the newer Streamable HTTP transport, automatically detecting and upgrading to newer protocols, when supported by the MCP server. </p><p>As the MCP specification continues to evolve, we'll keep the library updated with the latest standards, while maintaining backwards compatibility. We are also excited to contribute <code>use-mcp</code> to the <a href="https://github.com/modelcontextprotocol/"><u>MCP project</u></a>, so it can grow with help from the wider community.</p>
    <div>
      <h3>MCP Inspector, built with use-mcp</h3>
      <a href="#mcp-inspector-built-with-use-mcp">
        
      </a>
    </div>
    <p>In use-mcp’s <a href="https://github.com/modelcontextprotocol/use-mcp/tree/main/examples"><u>examples directory</u></a>, you’ll see a minimal <a href="https://inspector.use-mcp.dev/"><u>MCP Inspector</u></a> that was built with the <code>use-mcp</code> hook. . Enter any MCP server URL to test connections, see available tools, and monitor interactions through the debug logs. It's a great starting point for building your own MCP clients or something you can use to debug connections to your MCP server. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6PmPcZicaO39x9SuRqzqSX/b6caa6c7af1d6b03f17c41771598d1b5/image1.png" />
          </figure><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/modelcontextprotocol/use-mcp/tree/main/examples/inspector"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
    <div>
      <h2>Open-sourcing the AI Playground </h2>
      <a href="#open-sourcing-the-ai-playground">
        
      </a>
    </div>
    <p>We initially built the <a href="https://playground.ai.cloudflare.com/"><u>AI Playground</u></a> to give users a chat interface for testing different AI models supported by Workers AI. We then added MCP support, so it could be used as a remote MCP client to connect to and test MCP servers. Today, we're open-sourcing the playground, giving you the complete chat interface with the MCP client built in, so you can deploy it yourself and customize it to fit your needs. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/playground/ai"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>The playground comes with built-in support for the latest MCP standards, including both Streamable HTTP and Server-Sent Events transport methods, OAuth authentication flows that allow users to sign-in and grant permissions, as well as support for bearer token authentication for direct MCP server connections.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5iaUzuxBZafrH1q0VYHTJf/a7585da38f75818111b3521c9a5ef4e3/image2.png" />
          </figure>
    <div>
      <h3>How the AI Playground works</h3>
      <a href="#how-the-ai-playground-works">
        
      </a>
    </div>
    <p>The AI Playground is built on Workers AI, giving you access to a full catalog of large language models (LLMs) running on Cloudflare's network, combined with the Agents SDK and <code>use-mcp</code> library for MCP server connections.</p><p>The AI Playground uses the <code>use-mcp</code> library to manage connections to remote MCP servers. When the playground starts up, it initializes the MCP connection system with <code>const{tools: mcpTools} = useMcp()</code>, which provides access to all tools from connected servers. At first, this list is empty because it’s not connected to any MCP servers, but once a connection to a remote MCP server is established, the tools are automatically discovered and populated into the list. </p><p>Once <a href="https://github.com/cloudflare/ai/blob/af1ce8be87d6a4e6bc10bb83f7959e63b28c1c8e/playground/ai/src/McpServers.tsx#L550"><u>connected</u></a>, the playground immediately has access to any tools that the MCP server exposes. The <code>use-mcp</code> library handles all the protocol communication and tool discovery, and maintains the connection state. If the MCP server requires authentication, the playground handles OAuth flows through a dedicated callback page that uses <code>onMcpAuthorization </code>from <code>use-mcp</code> to complete the authentication process.</p><p>When a user sends a chat message, the playground takes the <code>mcpTools</code> from the <code>use-mcp</code> hook and passes them directly to Workers AI, enabling the model to understand what capabilities are available and invoke them as needed. </p>
            <pre><code>const stream = useChat({
  api: "/api/inference",
  body: {
    model: params.model,
    tools: mcpTools, // Tools from connected MCP servers
    max_tokens: params.max_tokens,
    system_message: params.system_message,
  },
})</code></pre>
            
    <div>
      <h3>Debugging and monitoring</h3>
      <a href="#debugging-and-monitoring">
        
      </a>
    </div>
    <p>To monitor and debug connections to MCP servers, we’ve added a Debug Log interface to the playground. This displays real-time information about the MCP server connections, including connection status, authentication state, and any connection errors. </p><p>During the chat interactions, the debug interface will show the raw message exchanged between the playground and the MCP server, including the tool invocation and its result. This allows you to monitor the JSON payload being sent to the MCP server, the raw response returned, and track whether the tool call succeeded or failed. This is especially helpful for anyone building remote MCP servers, as it allows you to see how your tools are behaving when integrated with different language models. </p>
    <div>
      <h2>Contributing to the MCP ecosystem</h2>
      <a href="#contributing-to-the-mcp-ecosystem">
        
      </a>
    </div>
    <p>One of the reasons why MCP has evolved so quickly is that it's an open source project, powered by the community. We're excited to contribute the <code>use-mcp</code> library to the <a href="https://github.com/modelcontextprotocol"><u>MCP ecosystem</u></a> to enable more developers to build remote MCP clients. </p><p>If you're looking for examples of MCP clients or MCP servers to get started with, check out the<a href="https://github.com/cloudflare/ai"> <u>Cloudflare AI GitHub repository</u></a> for working examples you can deploy and modify. This includes the complete AI Playground <a href="https://github.com/cloudflare/ai/tree/main/playground/ai"><u>source code,</u></a> a number of remote MCP servers that use different authentication &amp; authorization providers, and the <a href="https://github.com/cloudflare/ai/tree/main/demos/use-mcp-inspector"><u>MCP Inspector</u></a>. </p><p>We’re also building the <a href="https://github.com/cloudflare/mcp-server-cloudflare"><u>Cloudflare MCP servers</u></a> in public and welcome contributions to help make them better. </p><p>Whether you're building your first MCP server, integrating MCP into an existing application, or contributing to the broader ecosystem, we'd love to hear from you. If you have any questions, feedback, or ideas for collaboration, you can reach us via email at <a href="#"><u>1800-mcp@cloudflare.com</u></a>. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7sYYS9c45orRX6SaUw5qTx/b975c5221ab538cc8f1167b706da375f/image3.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">4gk3k2ZiTN6DZoHu3e090r</guid>
            <dc:creator>Dina Kozlov</dc:creator>
            <dc:creator>Glen Maddern</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
        <item>
            <title><![CDATA[Making Cloudflare the best platform for building AI Agents]]></title>
            <link>https://blog.cloudflare.com/build-ai-agents-on-cloudflare/</link>
            <pubDate>Tue, 25 Feb 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Today we’re excited to share a few announcements on how we’re making it even easier to build AI agents on Cloudflare. ]]></description>
            <content:encoded><![CDATA[ <p>As engineers, we’re obsessed with efficiency and automating anything we find ourselves doing more than twice. If you’ve ever done this, you know that the happy path is always easy, but the second the inputs get complex, automation becomes really hard. This is because computers have traditionally required extremely specific instructions in order to execute.</p><p>The state of AI models available to us today has changed that. We now have access to computers that can reason, and make judgement calls in lieu of specifying every edge case under the sun.</p><p>That’s what <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/">AI agents</a> are all about.</p><p>Today we’re excited to share a few announcements on how we’re making it <i>even</i> <i>easier</i> to build AI agents on Cloudflare, including:</p><ul><li><p><code>agents-sdk</code> — a new JavaScript framework for building AI agents</p></li><li><p>Updates to Workers AI: structured outputs, tool calling, and longer context windows for <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a>, Cloudflare’s serverless inference engine</p></li><li><p>An update to the <a href="https://github.com/cloudflare/workers-ai-provider"><u>workers-ai-provider</u></a> for the AI SDK</p></li></ul><p>We truly believe that Cloudflare is the ideal platform for building Agents and AI applications (more on why below), and we’re constantly working to make it better — you can expect to see more announcements from us in this space in the future.</p><p>Before we dive deep into the announcements, we wanted to give you a quick primer on agents. If you are familiar with agents, feel free to skip ahead. </p>
    <div>
      <h2>What are agents?</h2>
      <a href="#what-are-agents">
        
      </a>
    </div>
    <p>Agents are AI systems that can autonomously execute tasks by making decisions about tool usage and process flow. Unlike traditional automation that follows predefined paths, agents can dynamically adapt their approach based on context and intermediate results. Agents are also distinct from co-pilots (e.g. traditional chat applications) in that they can fully automate a task, as opposed to simply augmenting and extending human input.</p><ul><li><p>Agents → non-linear, non-deterministic (can change from run to run)</p></li><li><p>Workflows → linear, deterministic execution paths</p></li><li><p>Co-pilots → augmentative AI assistance requiring human intervention</p></li></ul>
    <div>
      <h3>Example: booking vacations</h3>
      <a href="#example-booking-vacations">
        
      </a>
    </div>
    <p>If this is your first time working with, or interacting with agents, this example will illustrate how an agent works within a context like booking a vacation.</p><p>Imagine you're trying to book a vacation. You need to research flights, find hotels, check restaurant reviews, and keep track of your budget.</p><p><b>Traditional workflow automation</b></p><p>A traditional automation system follows a predetermined sequence: it can take inputs such as dates, location, and budget, and make calls to predefined APIs in a fixed order. However, if any unexpected situations arise, such as flights being sold out, or the specified hotels being unavailable, it cannot adapt. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7fHwj0r4JgRDawOQnNN618/2f369a5224dee288d3baf656d5952469/image1.png" />
          </figure><p><b>AI co-pilot</b></p><p>A co-pilot acts as an intelligent assistant that can provide hotel and itinerary recommendations based on your preferences. If you have questions, it can understand and respond to natural language queries and offer guidance and suggestions. However, it is unable to take the next steps to execute the end-to-end action on its own. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/24e3EQSLKo3CJsKv0gFban/6a23620857c6bca8a873da185ee5be56/image2.png" />
          </figure><p><b>Agent</b></p><p>An agent combines AI's ability to make judgements and call the relevant tools to execute the task. An agent's output will be nondeterministic given: real-time availability and pricing changes, dynamic prioritization of constraints, ability to recover from failures, and adaptive decision-making based on intermediate results. In other words, if flights or hotels are unavailable, an agent can reassess and suggest a new itinerary with altered dates or locations, and continue executing your travel booking.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/30QFnfkVyFm1tyV9B2QvXU/ac79ff6ac70ba609d4ecf714d34f0146/image3.png" />
          </figure>
    <div>
      <h2>agents-sdk — the framework for building agents</h2>
      <a href="#agents-sdk-the-framework-for-building-agents">
        
      </a>
    </div>
    <p>You can now add agent powers to any existing Workers project with just one command:</p>
            <pre><code>$ npm i agents-sdk</code></pre>
            <p>… or if you want to build something from scratch, you can bootstrap your project with the <a href="https://github.com/cloudflare/agents-starter"><u>agents-starter template</u></a>:</p>
            <pre><code>$ npm create cloudflare@latest -- --template cloudflare/agents-starter
// ... and then deploy it
$ npm run deploy</code></pre>
            <p><code>agents-sdk</code> is a framework that allows you to build agents —  software that can autonomously execute tasks — and deploy them directly into production on Cloudflare Workers.</p><p>Your agent can start with the basics and act on HTTP requests…</p>
            <pre><code>import { Agent } from "agents-sdk";

export class IntelligentAgent extends Agent {
  async onRequest(request) {
    // Transform intention into response
    return new Response("Ready to assist.");
  }
}</code></pre>
            <p>Although this is just the initial release of <code>agents-sdk</code>, we wanted to ship more than just a thin wrapper over an existing library. Agents can communicate with clients in real time, persist state, execute long-running tasks on a schedule, send emails, run asynchronous workflows, browse the web, query data from your Postgres database, call AI models, and support human-in-the-loop use-cases. All of this works today, out of the box.</p><p>For example, you can build a powerful chat agent with the <code>AIChatAgent</code> class:</p>
            <pre><code>// src/index.ts
export class Chat extends AIChatAgent&lt;Env&gt; {
  /**
   * Handles incoming chat messages and manages the response stream
   * @param onFinish - Callback function executed when streaming completes
   */
  async onChatMessage(onFinish: StreamTextOnFinishCallback&lt;any&gt;) {
    // Create a streaming response that handles both text and tool outputs
    return agentContext.run(this, async () =&gt; {
      const dataStreamResponse = createDataStreamResponse({
        execute: async (dataStream) =&gt; {
          // Process any pending tool calls from previous messages
          // This handles human-in-the-loop confirmations for tools
          const processedMessages = await processToolCalls({
            messages: this.messages,
            dataStream,
            tools,
            executions,
          });

          // Initialize OpenAI client with API key from environment
          const openai = createOpenAI({
            apiKey: this.env.OPENAI_API_KEY,
          });

          // Cloudflare AI Gateway
          // const openai = createOpenAI({
          //   apiKey: this.env.OPENAI_API_KEY,
          //   baseURL: this.env.GATEWAY_BASE_URL,
          // });

          // Stream the AI response using GPT-4
          const result = streamText({
            model: openai("gpt-4o-2024-11-20"),
            system: `
              You are a helpful assistant that can do various tasks. If the user asks, then you can also schedule tasks to be executed later. The input may have a date/time/cron pattern to be input as an object into a scheduler The time is now: ${new Date().toISOString()}.
              `,
            messages: processedMessages,
            tools,
            onFinish,
            maxSteps: 10,
          });

          // Merge the AI response stream with tool execution outputs
          result.mergeIntoDataStream(dataStream);
        },
      });

      return dataStreamResponse;
    });
  }
  async executeTask(description: string, task: Schedule&lt;string&gt;) {
    await this.saveMessages([
      ...this.messages,
      {
        id: generateId(),
        role: "user",
        content: `scheduled message: ${description}`,
      },
    ]);
  }
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    if (!env.OPENAI_API_KEY) {
      console.error(
        "OPENAI_API_KEY is not set, don't forget to set it locally in .dev.vars, and use `wrangler secret bulk .dev.vars` to upload it to production"
      );
      return new Response("OPENAI_API_KEY is not set", { status: 500 });
    }
    return (
      // Route the request to our agent or return 404 if not found
      (await routeAgentRequest(request, env)) ||
      new Response("Not found", { status: 404 })
    );
  },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            <p>… and connect to your Agent with any React-based front-end with the <a href="https://github.com/cloudflare/agents-starter/blob/main/src/app.tsx"><code><u>useAgent</u></code></a> hook that can automatically establish a bidirectional WebSocket, sync client state, and allow you to build Agent-based applications without a mountain of bespoke code:</p>
            <pre><code>// src/app.tsx
import { useAgent } from "agents-sdk/react";  

const agent = useAgent({
  agent: "chat",
});</code></pre>
            <p>We spent some time thinking about the production story here too: an agent framework that absolves itself of the hard parts — durably persisting state, handling long-running tasks &amp; loops, and horizontal scale — is only going to get you so far. Agents built with <code>agents-sdk</code> can be deployed directly to Cloudflare and run on top of <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> — which you can think of as stateful micro-servers that can scale to tens of millions — and are able to run wherever they need to. Close to a user for low-latency, close to your data, and/or anywhere in between.</p><p><code>agents-sdk</code> also exposes:</p><ul><li><p>Integration with React applications via a <code>useAgent</code> hook that can automatically set up a WebSocket connection between your app and an agent</p></li><li><p>An <code>AIChatAgent</code> extension that makes it easier to build intelligent chat agents</p></li><li><p>State management APIs via <code>this.setState</code> as well as a native <code>sql</code> API for writing and querying data within each Agent</p></li><li><p>State synchronization between frontend applications and the agent state</p></li><li><p>Agent routing, enabling agent-per-user or agent-per-workflow use-cases. Spawn millions (or tens of millions) of agents without having to think about how to make the infrastructure work, provision CPU, or scale out storage.</p></li></ul><p>Over the coming weeks, expect to see even more here: tighter integration with email APIs to enable more human-in-the-loop use-cases, hooks into WebRTC for voice &amp; video interactivity, a built-in evaluation (evals) framework, and the ability to self-host agents on your own infrastructure.</p><p>We’re aiming high here: we think this is just the beginning of what agents are capable of, and we think we can make Workers the best place (but not the only place) to build &amp; run them.</p>
    <div>
      <h2>JSON mode, longer context windows, and improved tool calling in Workers AI</h2>
      <a href="#json-mode-longer-context-windows-and-improved-tool-calling-in-workers-ai">
        
      </a>
    </div>
    <p>When users express needs conversationally, tool calling converts these requests into structured formats like JSON that APIs can understand and process, allowing the AI to interact with databases, services, and external systems. This is essential for building agents, as it allows users to express complex intentions in natural language, and AI to decompose these requests, call appropriate tools, evaluate responses and deliver meaningful outcomes.</p><p>When using tool calling or building AI agents, the text generation model must respond with valid JSON objects rather than natural language. Today, we're adding JSON mode support to Workers AI, enabling applications to request a structured output response when interacting with AI models. Here's a request to <code>@cf/meta/llama-3.1-8b-instruct-fp8-fast</code> using JSON mode:</p>
            <pre><code>{
  "messages": [
    {
      "role": "system",
      "content": "Extract data about a country."
    },
    {
      "role": "user",
      "content": "Tell me about India."
    }
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "capital": {
          "type": "string"
        },
        "languages": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "name",
        "capital",
        "languages"
      ]
    }
  }
}</code></pre>
            <p>And here’s how the model will respond:</p>
            <pre><code>{
  "response": {
    "name": "India",
    "capital": "New Delhi",
    "languages": [
      "Hindi",
      "English",
      "Bengali",
      "Telugu",
      "Marathi",
      "Tamil",
      "Gujarati",
      "Urdu",
      "Kannada",
      "Odia",
      "Malayalam",
      "Punjabi",
      "Sanskrit"
    ]
  }
}</code></pre>
            <p>As you can see, the model is complying with the JSON schema definition in the request and responding with a validated JSON object. JSON mode is compatible with OpenAI’s <code>response_format</code> implementation:</p>
            <pre><code>response_format: {
  title: "JSON Mode",
  type: "object",
  properties: {
    type: {
      type: "string",
      enum: ["json_object", "json_schema"],
    },
    json_schema: {},
  }
}</code></pre>
            <p>This is the list of models that now support JSON mode:</p><ul><li><p><a href="https://developers.cloudflare.com/workers-ai/models/llama-3.1-8b-instruct-fast/"><u>@cf/meta/llama-3.1-8b-instruct-fast</u></a></p></li><li><p><a href="https://developers.cloudflare.com/workers-ai/models/llama-3.1-70b-instruct/"><u>@cf/meta/llama-3.1-70b-instruct</u></a></p></li><li><p><a href="https://developers.cloudflare.com/workers-ai/models/llama-3.3-70b-instruct-fp8-fast/"><u>@cf/meta/llama-3.3-70b-instruct-fp8-fast</u></a></p></li><li><p><a href="https://developers.cloudflare.com/workers-ai/models/deepseek-r1-distill-qwen-32b/"><u>@cf/deepseek-ai/deepseek-r1-distill-qwen-32b</u></a></p></li><li><p><a href="https://developers.cloudflare.com/workers-ai/models/llama-3-8b-instruct/"><u>@cf/meta/llama-3-8b-instruct</u></a></p></li><li><p><a href="https://developers.cloudflare.com/workers-ai/models/llama-3.1-8b-instruct/"><u>@cf/meta/llama-3.1-8b-instruct</u></a></p></li><li><p><a href="https://developers.cloudflare.com/workers-ai/models/hermes-2-pro-mistral-7b/"><u>@hf/nousresearch/hermes-2-pro-mistral-7b</u></a></p></li></ul><p>We will continue extending this list to keep up with new, and requested models.</p><p>Lastly, we are changing how we restrict the size of AI requests to text generation models, moving from byte-counts to token-counts, introducing the concept of <b>context window</b> and raising the limits of the models in our catalog.</p><p>In generative AI, the context window is the sum of the number of input, reasoning, and completion or response tokens a model supports. You can now find the context window limit on each <a href="https://developers.cloudflare.com/workers-ai/models/llama-3.1-70b-instruct/"><u>model page</u></a> in our developer documentation and decide which suits your requirements and use case.</p><p>JSON mode is also the perfect companion when using function calling. You can use structured JSON outputs with traditional function calling or the Vercel AI SDK via the <code>workers-ai-provider</code>.</p>
    <div>
      <h2><a href="https://github.com/cloudflare/workers-ai-provider">workers-ai-provider</a> 0.1.1</h2>
      <a href="#0-1-1">
        
      </a>
    </div>
    <p>One of the most common ways to build with AI tooling today is by using the popular <a href="https://sdk.vercel.ai/docs/introduction"><u>AI SDK</u></a>. <a href="https://github.com/cloudflare/workers-ai-provider"><u>Cloudflare’s provider</u></a> for the AI SDK makes it easy to use Workers AI the same way you would call any other LLM, directly from your code.</p><p>In the <a href="https://github.com/cloudflare/workers-ai-provider/tree/workers-ai-provider%400.1.1"><u>most recent version</u></a>, we’ve shipped the following improvements: </p><ul><li><p>Tool calling enabled for generateText</p></li><li><p>Streaming now works out of the box</p></li><li><p>Usage statistics are now enabled</p></li><li><p>You can now use AI Gateway, even when streaming</p></li></ul><p>A key part of building agents is using LLMs for routing, and making decisions on which tools to call next, and summarizing structured and unstructured data. All of these things need to happen quickly, as they are on the critical path of the user-facing experience.</p><p>Workers AI, with its globally distributed fleet of GPUs, is a perfect fit for smaller, low-latency LLMs, so we’re excited to make it easy to use with tools developers are already familiar with. </p>
    <div>
      <h2>Why build agents on Cloudflare? </h2>
      <a href="#why-build-agents-on-cloudflare">
        
      </a>
    </div>
    <p>Since launching Workers in 2017, we’ve been building a platform to allow developers to build applications that are fast, scalable, and cost-efficient from day one. We took a fundamentally different approach from the way code was previously run on servers, making a bet about what the future of applications was going to look like — isolates running on a global network, in a way that was truly serverless. No regions, no concurrency management, no managing or scaling infrastructure. </p><p>The release of Workers was just the beginning, and we continued shipping primitives to extend what developers could build. Some more familiar, like a key-value store (<a href="https://developers.cloudflare.com/kv/"><u>Workers KV</u></a>), and some that we thought would play a role in enabling net new use cases like <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a>. While we didn’t quite predict AI agents (though “Agents” was one of the proposed names for Durable Objects), we inadvertently created the perfect platform for building them. </p><p>What do we mean by that? </p>
    <div>
      <h3>A platform that only charges you for what you use (regardless of how long it takes)</h3>
      <a href="#a-platform-that-only-charges-you-for-what-you-use-regardless-of-how-long-it-takes">
        
      </a>
    </div>
    <p>To be able to run agents efficiently, you need a system that can seamlessly scale up and down to support the constant stop, go, wait patterns. Agents are basically long-running tasks, sometimes waiting on slow reasoning LLMs and external tools to execute. With Cloudflare, you don’t have to pay for long-running processes when your code is not executing. Cloudflare Workers is designed to scale down and <a href="https://blog.cloudflare.com/workers-pricing-scale-to-zero/"><u>only charge you for CPU time</u></a>, as opposed to wall-clock time. </p><p>In many cases, especially when calling LLMs, the difference can be in orders of magnitude — e.g. 2–3 milliseconds of CPU vs. 10 seconds of wall-clock time. When building on Workers, we pass that difference on to you as cost savings. </p>
    <div>
      <h3>Serverless AI Inference</h3>
      <a href="#serverless-ai-inference">
        
      </a>
    </div>
    <p>We took a similar serverless approach when it comes to inference itself. When you need to call an AI model, you need it to be instantaneously available. While the foundation model providers offer APIs that make it possible to just call the LLM, if you’re running open-source models, <a href="https://www.cloudflare.com/learning/ai/what-is-lora/"><u>LoRAs</u></a>, or self-trained models, most cloud providers today require you to pre-provision resources for what your peak traffic will look like. This means that the rest of the time, you’re still paying for GPUs to sit there idle. With Workers AI, you can pay only when you’re calling our inference APIs, as opposed to unused infrastructure. In fact, you don’t have to think about infrastructure at all, which is the principle at the core of everything we do. </p>
    <div>
      <h3>A platform designed for durable execution</h3>
      <a href="#a-platform-designed-for-durable-execution">
        
      </a>
    </div>
    <p><a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> and <a href="https://developers.cloudflare.com/workflows"><u>Workflows</u></a> provide a robust programming model that ensures guaranteed execution for asynchronous tasks that require persistence and reliability. This makes them ideal for handling complex operations like long-running deep thinking LLM calls, human-in-the-loop approval processes, or interactions with unreliable third-party APIs. By maintaining state across requests and automatically handling retries, these tools create a resilient foundation for building sophisticated AI agents that can perform complex, multistep tasks without losing context or progress, even when operations take significant time to complete.</p>
    <div>
      <h2>Lastly, new and updated agents documentation</h2>
      <a href="#lastly-new-and-updated-agents-documentation">
        
      </a>
    </div>
    <p>Did you catch all of that?</p><p>No worries if not: we’ve updated our <a href="https://developers.cloudflare.com/agents"><u>agents documentation</u></a> to include everything we talked about above, from breaking down the basics of agents, to showing you how to tackle foundational examples of building with agents.</p><p>We’ve also updated our <a href="https://developers.cloudflare.com/workers/get-started/prompting/"><u>Workers prompt</u></a> with knowledge of the agents-sdk library, so you can use Cursor, Windsurf, Zed, ChatGPT or Claude to help you build AI Agents and deploy them to Cloudflare.</p>
    <div>
      <h2>Can’t wait to see what you build! </h2>
      <a href="#cant-wait-to-see-what-you-build">
        
      </a>
    </div>
    <p>We’re just getting started, and we love to see all that you build. Please join our <a href="https://discord.com/invite/cloudflaredev"><u>Discord</u></a>, ask questions, and tell us what you’re building.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Durable Objects]]></category>
            <guid isPermaLink="false">1k3ytqqRxQ9SsiYLMSBDfO</guid>
            <dc:creator>Rita Kozlov</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
            <dc:creator>Matt Silverlock</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare acquires PartyKit to allow developers to build real-time multi-user applications]]></title>
            <link>https://blog.cloudflare.com/cloudflare-acquires-partykit/</link>
            <pubDate>Fri, 05 Apr 2024 13:00:56 GMT</pubDate>
            <description><![CDATA[ We're thrilled to announce that PartyKit, a trailblazer in enabling developers to craft ambitious real-time, collaborative, multiplayer applications, is now a part of Cloudflare ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We're thrilled to announce that PartyKit, an open source platform for deploying real-time, collaborative, multiplayer applications, is now a part of Cloudflare. This acquisition marks a significant milestone in our journey to redefine the boundaries of serverless computing, making it more dynamic, interactive, and, importantly, stateful.</p>
    <div>
      <h3>Defining the future of serverless compute around state</h3>
      <a href="#defining-the-future-of-serverless-compute-around-state">
        
      </a>
    </div>
    <p>Building real-time applications on the web have always been difficult. Not only is it a distributed systems problem, but you need to provision and manage infrastructure, databases, and other services to maintain state across multiple clients. This complexity has traditionally been a barrier to entry for many developers, especially those who are just starting out.</p><p><a href="/introducing-workers-durable-objects">We announced Durable Objects in 2020</a> as a way of building synchronized real time experiences for the web. Unlike regular serverless functions that are ephemeral and stateless, Durable Objects are stateful, allowing developers to build applications that maintain state across requests. They also act as an ideal synchronization point for building real-time applications that need to maintain state across multiple clients. Combined with WebSockets, Durable Objects can be used to build a wide range of applications, from multiplayer games to collaborative drawing tools.</p><p>In 2022, PartyKit began as a project to further explore the capabilities of Durable Objects and make them more accessible to developers by exposing them through familiar components. In seconds, you could create a project that configured behavior for these objects, and deploy it to Cloudflare. By integrating with popular libraries such as <a href="https://github.com/yjs/yjs">Yjs</a> (the gold standard in collaborative editing) and React, PartyKit made it possible for developers to build a wide range of use cases, from multiplayer games to collaborative drawing tools, into their applications.</p><p>Building experiences with real-time components was previously only accessible to multi-billion dollar companies, but new computing primitives like Durable Objects on the edge make this accessible to regular developers and teams. With PartyKit now under our roof, we're doubling down on our commitment to this future — a future where serverless is stateful.</p><p>We’re excited to give you a preview into our shared vision for applications, and the use cases we’re excited to simplify together.</p>
    <div>
      <h3>Making state for serverless easy</h3>
      <a href="#making-state-for-serverless-easy">
        
      </a>
    </div>
    <p>Unlike conventional approaches that rely on external databases to maintain state, thereby complicating scalability and increasing costs, PartyKit leverages Cloudflare's Durable Objects to offer a seamless model where stateful serverless functions can operate as if they were running on a single machine, maintaining state across requests. This innovation not only simplifies development but also opens up a broader range of use cases, including real-time computing, collaborative editing, and multiplayer gaming, by allowing thousands of these "machines" to be spun up globally, each maintaining its own state. PartyKit aims to be a complement to traditional serverless computing, providing a more intuitive and efficient method for developing applications that require stateful behavior, thereby marking the "next evolution" of serverless computing.</p>
    <div>
      <h3>Simplifying WebSockets for Real-Time Interaction</h3>
      <a href="#simplifying-websockets-for-real-time-interaction">
        
      </a>
    </div>
    <p>WebSockets have revolutionized how we think about bidirectional communication on the web. Yet, the challenge has always been about scaling these interactions to millions without a hitch. Cloudflare Workers step in as the hero, providing a serverless framework that makes real-time applications like chat services, multiplayer games, and collaborative tools not just possible but scalable and efficient.</p>
    <div>
      <h3>Powering Games and Multiplayer Applications Without Limits</h3>
      <a href="#powering-games-and-multiplayer-applications-without-limits">
        
      </a>
    </div>
    <p>Imagine building multiplayer platforms where the game never lags, the collaboration is seamless, and video conferences are crystal clear. Cloudflare's Durable Objects morph the stateless serverless landscape into a realm where persistent connections thrive. PartyKit's integration into this ecosystem means developers now have a powerhouse toolkit to bring ambitious multiplayer visions to life, without the traditional overheads.</p><p>This is especially critical in gaming — there are few areas where low-latency and real-time interaction matter more. Every millisecond, every lag, every delay defines the entire experience. With PartyKit's capabilities integrated into Cloudflare, developers will be able to leverage our combined technologies to create gaming experiences that are not just about playing but living the game, thanks to scalable, immersive, and interactive platforms.</p>
    <div>
      <h3>The toolkit for building Local-First applications</h3>
      <a href="#the-toolkit-for-building-local-first-applications">
        
      </a>
    </div>
    <p>The Internet is great, and increasingly always available, but there are still a few situations where we are forced to disconnect — whether on a plane, a train, or a beach.</p><p>The premise of local-first applications is that work doesn't stop when the Internet does. Wherever you left off in your doc, you can keep working on it, assuming the state will be restored when you come back online. By storing data on the client and syncing when back online, these applications offer resilience and responsiveness that's unmatched. Cloudflare's vision, enhanced by PartyKit's technology, aims to make local-first not just an option but the standard for application development.</p>
    <div>
      <h3>What's next for PartyKit users?</h3>
      <a href="#whats-next-for-partykit-users">
        
      </a>
    </div>
    <p>Users can expect their existing projects to continue working as expected. We will be adding more features to the platform, including the ability to create and use PartyKit projects inside existing Workers and Pages projects. There will be no extra charges to use PartyKit for commercial purposes, other than the standard usage charges for Cloudflare Workers and other services. Further, we're going to expand the roadmap to begin working on integrations with popular frameworks and libraries, such as React, Vue, and Angular. We're deeply committed to executing on the PartyKit vision and roadmap, and we're excited to see what you build with it.</p>
    <div>
      <h3>The Beginning of a New Chapter</h3>
      <a href="#the-beginning-of-a-new-chapter">
        
      </a>
    </div>
    <p>The acquisition of PartyKit by Cloudflare isn't just a milestone for our two teams; it's a leap forward for developers everywhere. Together, we're not just building tools; we're crafting the foundation for the next generation of Internet applications. The future of serverless is stateful, and with PartyKit's expertise now part of our arsenal, we're more ready than ever to make that future a reality.</p><p>Welcome to the Cloudflare team, PartyKit. Look forward to building something remarkable together.</p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Acquisitions]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Durable Objects]]></category>
            <guid isPermaLink="false">7iSu3hCtgPt2FoZ60sWKuO</guid>
            <dc:creator>Sunil Pai</dc:creator>
            <dc:creator>Rita Kozlov</dc:creator>
        </item>
        <item>
            <title><![CDATA[10 things I love about Wrangler v2.0]]></title>
            <link>https://blog.cloudflare.com/10-things-i-love-about-wrangler/</link>
            <pubDate>Mon, 09 May 2022 13:00:07 GMT</pubDate>
            <description><![CDATA[ We are proud to announce that Wrangler goes public today for general usage, and can’t wait to see what people build with it ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Last November, <a href="/wrangler-v2-beta/">we announced</a> the beta release of a full rewrite of Wrangler, our CLI for building Cloudflare Workers. Since then, we’ve been working round the clock to make sure it's feature complete, bug-free, and easy to use. We are proud to announce that Wrangler goes public today for general usage, and can’t wait to see what people build with it!</p><p>Rewrites can be scary. Our goal for this version of Wrangler was backward compatibility with the original version, while significantly improving the developer experience. I'd like to take this opportunity to present 10 reasons why you should upgrade to the new Wrangler!</p>
    <div>
      <h3>1. It's simpler to install:</h3>
      <a href="#1-its-simpler-to-install">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2iw5RCJVagbVV6ME253GWC/fe280e63ee2fcf7c18fdfaedd83ae0be/image7-1.png" />
            
            </figure><p><i>A simpler way to get started.</i></p><p>Previously, folks would have to install <code>@cloudflare/wrangler</code> globally on a system. This made it hard to use different versions of Wrangler across projects. Further, it was hard to install on some CI systems because of lack of access to a user's root folder.  Sometimes, folks would forget to add the <code>@cloudflare</code> scope when installing, confusing them when a completely unrelated package was installed and didn't work as expected.</p><p>Let's fix that. We've simplified this by now publishing to the <code>wrangler</code> package, so you can run <code>npm install wrangler</code> and it works as expected. You can also install it locally to a project's <code>package.json</code>, like any other regular npm package. It also works across a much broader range of CPU architectures and operating systems, so you can use it on more machines.</p><p>This makes it a lot more convenient when starting. But why stop there?</p>
    <div>
      <h3>2. Zero config startup:</h3>
      <a href="#2-zero-config-startup">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6Ws2aTtoakQ32HRr61DSn1/e72267324fadc0f664c8a7860d18e493/image1-13.png" />
            
            </figure><p><i>Get started with zero configuration</i></p><p>It's now much simpler to get started with a new project. Previously, you would have to create a <code>wrangler.toml</code> configuration file, and fill it in with details about your cloudflare account, how the project was structured, setting up a custom build process and so on. We heard feedback from many of you who would get frustrated during this step, and how it would take many minutes before you could get to developing a simple Worker.</p><p>Let's fix that. You no longer need to create a configuration file when starting, and none of the fields are mandatory. Wrangler infers details about your account and project as you start developing, and you can add configuration incrementally when you need to.</p><p>In fact, you don't even need to install Wrangler to start! You can create a Worker (say, as <code>index.js</code>) and use <code>npx</code> (a utility that comes installed with <code>node.js</code>) to fetch Wrangler from the npm registry and start developing immediately!</p><div></div>
<p></p><p>This is great for extremely simple Workers, but why stop there?</p>
    <div>
      <h3>3. <code>wrangler init my-worker -y</code>, one liner to set up a full project:</h3>
      <a href="#3-wrangler-init-my-worker-y-one-liner-to-set-up-a-full-project">
        
      </a>
    </div>
    <p>We noticed users would struggle to set up a project with Wrangler, even after they'd installed Wrangler and configured <code>wrangler.toml</code>. Most users want to set up a <code>package.json</code>, commonly use <code>typescript</code> to write code, and set up <code>git</code> to track changes in this project. So, we expanded the <code>wrangler init &lt;project name&gt;</code> command to set up a production grade project. You can optionally choose to use <code>typescript</code>, install the official type definitions for Workers, and use <code>git</code> to track changes.</p><p>My favorite trick here is to pass <code>-y</code> to accept all questions without asking. Try running <code>npx wrangler init my-worker -y</code> in your terminal today!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4L7voFxn3ddNCdIoUgMqas/73cf4dc0ccf428e1dfc170c03055376a/image5-1.png" />
            
            </figure><p><i>One line to set up a full Workers project</i></p>
    <div>
      <h3>4. <code>--local</code> mode:</h3>
      <a href="#4-local-mode">
        
      </a>
    </div>
    <p>Wrangler typically runs a development server on our global network, setting up a local proxy when developing, so you can develop against a "real" environment in the cloud. This is great for making sure the code you develop will behave the same in development, and after you deploy it to production. The trade-off here is it's harder to develop code when you have a bad Internet connection, or if you're running tests on a CI machine. It's also marginally slower to iterate while coding. Users have asked us for a long time to be able to 'run' their code locally on their machines, so that they can iterate quickly and run tests in environments like CI.</p><p>Wrangler now lets you develop on your machine by simply calling <code>wrangler dev --local</code>, and no additional configuration. This is powered by <a href="https://miniflare.dev">Miniflare</a>, a fully featured simulator of the Cloudflare Workers runtime. You can even toggle across 'edge' and 'local' modes by tapping the 'L' hotkey when developing; however you prefer!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3zC0yCCFhNhagjbOWfwITV/f050f23608405a71d4d6055fa4ee2209/image2-4.png" />
            
            </figure><p><i>Local mode, powered by Miniflare.</i></p>
    <div>
      <h3>5. Tail any Worker, any time:</h3>
      <a href="#5-tail-any-worker-any-time">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6zCLJukTN9Uc4DFpdUmm51/393f31ed3cc88b16c3de2b503f1e5245/image6-4.png" />
            
            </figure><p><i>Tail your logs anywhere, anytime.</i> </p><p>It's useful to be able to "tail" a Worker's output to a terminal, and see what's going on in real time. While you can already view these logs in the Workers dashboard, some people are more comfortable seeing the logs in their terminal, and then slicing and dicing to debug any issues that may be occuring. Previously, you would have to checkout a Worker's repository locally, install dependencies, and then call <code>wrangler tail</code> in the project folder. This was clearly cumbersome, and relied on developer expertise to see something as simple as a Worker's logs.</p><p>Now you can simply call <code>npx wrangler tail &lt;worker name&gt;</code> in your terminal, without any configuration or setup, and immediately see the logs that you expect. We use this ourselves to quickly inspect our production Workers and see what's going on inside them!</p>
    <div>
      <h3>6. Better warnings and errors, everywhere:</h3>
      <a href="#6-better-warnings-and-errors-everywhere">
        
      </a>
    </div>
    <p>One of the worst feelings a developer can face is being presented with an error when writing code, and not knowing how to fix it and proceed. We heard feedback from many of you who were frustrated with the lack of error messages, and how you would spend hours trying to figure out what went wrong. We've now added new error and warning messages, so you can easily spot the problems in your code. When possible, we also include steps you can follow to fix your Worker, including things that you can simply copy and paste! This makes Wrangler much more friendly to use, and we promise the experience will only get better.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4vKCpjFLpx71tU1eTJEMl5/a696f5d0971f65cd1db8b7479ecf0787/image3-3.png" />
            
            </figure>
    <div>
      <h3>7. On-demand developer tools for debugging:</h3>
      <a href="#7-on-demand-developer-tools-for-debugging">
        
      </a>
    </div>
    <p>We introduced initial support for debugging Workers in Wrangler <a href="/profiling-your-workers-with-wrangler">in September</a> which enables debugging a Worker directly on our global network. However, getting started with debugging was still a bit cumbersome, because you would have to start Wrangler with an <code>--inspect</code> flag, then open a special page in your browser (<code>chrome://inspect</code>), configuring it to detect Wrangler running on a special port, and then launching the debugger. This would also mean you might have lost any debugging messages that were logged before you opened the Chrome developer tools.</p><p>We fixed this. Now you don't need to pass any special flags when starting up. You can simply hit the <code>D</code> hotkey when developing and a developer tools instance pops up in your browser. And by buffering the messages before you even start up the devtools, you don't lose any logs or errors! You can also use VS Code developer tools to directly hook into your Worker's debugging session!</p>
    <div>
      <h3>8. A modern module system:</h3>
      <a href="#8-a-modern-module-system">
        
      </a>
    </div>
    <p>Modern JavaScript isn't simply about the syntax that the language supports, but also writing code as modules, and leveraging the extremely broad ecosystem of community libraries and frameworks. Previously, Wrangler required that you set up <code>webpack</code> or a custom build with bundlers (like <code>rollup</code>, <code>vite</code>, or <code>esbuild</code>, to name a few) to consume libraries and modules. This introduces a lot of friction, especially when starting a new project and trying out new ideas.</p><p>Now, support for npm modules comes out of the box, with no extra configuration required! You can install any package from the <a href="http://npmjs.com/">npm registry</a>, organize your own code with modules, and it all works as expected. We're also introducing an experimental <code>node.js</code> compatibility mode for using <code>node.js</code> modules that wouldn't previously work without setting up your own polyfills! This means you can use popular frameworks and libraries that you're already familiar with while focusing on delivering value to your users.</p>
    <div>
      <h3>9. Closes many outstanding issues:</h3>
      <a href="#9-closes-many-outstanding-issues">
        
      </a>
    </div>
    <p>A rewrite should be judged not just by the new features that are implemented, but by how many existing issues are resolved. We went through hundreds of outstanding issues and bugs with Wrangler, and are happy to say that we solved almost all of them! Across the board, every command and feature got a facelift, bug fixes, and test coverage to make sure it doesn't break in the future. Developers on using Cloudflare Workers will be glad to hear that simply upgrading Wrangler will immediately fix previous concerns and problems. Which leads us to my absolute favorite feature...</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7o0yX40KcaE8j27F9bya4t/5f0da5100ef84878727629ec96c3dfd5/image9.png" />
            
            </figure>
    <div>
      <h3>10. A commitment to improve:</h3>
      <a href="#10-a-commitment-to-improve">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2RzDQhFclIpVBwnHQEoQ6l/5e3092af38651c6e175c34fa38a6ad61/image8.png" />
            
            </figure><p><i>The effort into building wrangler v2.0, visualised.</i> </p><p>Wrangler has always been special software for us. It represents the primary interface that developers use to interact and use Cloudflare Workers, and we have major plans for the future. We have invested time, effort and resources to make sure Wrangler is the best tool for developers to use, and we're excited to see what the future holds. This is a commitment to our users and community that we will only keep improving on this foundation, and folks can expect their feedback and concerns to be heard loud and clear.</p> ]]></content:encoded>
            <category><![CDATA[Platform Week]]></category>
            <category><![CDATA[Wrangler]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">37mGbexsYqNbE5dmM4vMLX</guid>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
        <item>
            <title><![CDATA[wrangler 2.0 — a new developer experience for Cloudflare Workers]]></title>
            <link>https://blog.cloudflare.com/wrangler-v2-beta/</link>
            <pubDate>Tue, 16 Nov 2021 13:59:22 GMT</pubDate>
            <description><![CDATA[ We're excited to announce the second-generation of our developer tooling for Cloudflare Workers. It’s a new developer experience that’s out-of-the-box, lightning fast, and can even run Workers on a local machine. (Yes!) ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Much of a developer’s work is about making trade-offs: consistency versus availability, speed over correctness, you name it. While there will always be different technical trade-offs to consider, we believe there are some that you, as a developer, should never need to make.</p><p>One of those decisions is an easy-to-use development environment. Whether you’re onboarding a new developer to your team or you simply want to develop faster, it’s important that even the smallest of things are optimized for speed and simplicity.</p><p>That’s why we're excited to announce the second-generation of our developer tooling for Cloudflare Workers. It’s a new developer experience that’s out-of-the-box, lightning fast, and can even run Workers on a local machine. (Yes!)</p><p>If you’re already familiar with our existing tools, we’re not just talking about the wrangler CLI, we’re talking about its next major release: wrangler 2.0. Stick around to get a sneak-peak at the new experience.</p>
    <div>
      <h3>No config? No problem</h3>
      <a href="#no-config-no-problem">
        
      </a>
    </div>
    <p>We’ve made it much easier to get started with Cloudflare Workers. All you need is a single JavaScript file to run a Worker -- no configuration needed. You don't even need to decide on a name!</p><p>When you run <code>wrangler dev &lt;filename&gt;</code>, your code is automatically bundled and deployed to a development environment. Then, you can send HTTP requests to that environment using a localhost proxy. Here’s what that looks like in-action:</p><div></div>
    <div>
      <h3>Live debugging, just like that</h3>
      <a href="#live-debugging-just-like-that">
        
      </a>
    </div>
    <p>Now there’s a completely redesigned experience for debugging a Worker. With a simple command you get access to a remote debugger, the same used by Chrome when you click “Inspect,” which provides an interactive view of logs, exceptions, and requests. It feels like your Worker is running locally, yet it’s actually running on the Cloudflare network.</p><div></div><p>A debugger that “just works” and auto-detects your changes makes <i>all</i> the difference when you’re just trying to code. We’ve also made a number of improvements to make the debugging experience even easier:</p><ul><li><p>Keybind shortcuts, to quickly toggle features or open a window.</p></li><li><p>Support for “--public ”, to automatically serve your static assets.</p></li><li><p>Faster and more reliable file-watching.</p></li></ul><p>To start a debugging session, just run: <code>wrangler dev &lt;filename&gt;</code>, then hit the “D” keybind.</p>
    <div>
      <h3>Local mode? Flip a switch</h3>
      <a href="#local-mode-flip-a-switch">
        
      </a>
    </div>
    <p>Another aspect of the new debugging experience is the ability to switch to “local mode,” which runs your Worker on your local machine. In fact, you can easily switch between “network” and “local” mode with just a keybind shortcut.</p><div></div><p>How does this work? Recently, we announced that <a href="https://github.com/cloudflare/miniflare">Miniflare</a> (created by <a href="https://twitter.com/_mrbbot">Brendan Coll</a>), a project to locally emulate Workers in Node.js, has joined the Cloudflare organization. Miniflare is great for unit testing and situations where you’d like to debug Workers without an Internet connection. Now we’ve integrated it directly into the local development experience, so you can enjoy the benefits of both the network and your localhost!</p>
    <div>
      <h3>Let us know what you think!</h3>
      <a href="#let-us-know-what-you-think">
        
      </a>
    </div>
    <p>Serverless should be simple. We’re really excited about these improvements to the developer experience for Workers, and we have a <i>lot</i> more planned.</p><p>While we’re still working on wrangler 2.0, you can try the beta release by running: <code>npm install wrangler@beta</code> or by visiting the <a href="https://github.com/cloudflare/wranglerv2">repository</a> to see what we’re working on. If you’re already using wrangler to deploy existing applications, we recommend continuing to use wrangler 1.0 until the 2.0 release is officially out. We will continue to develop and maintain wrangler 1.0 until we’re finished with backwards-compatibility for 2.0.</p><p>If you’re starting a project or want to try out the new experience, we’d love to hear your feedback! Let us know what we’re missing or what you’d like to see in wrangler 2.0. You can create a feature request or start a discussion in the <a href="https://github.com/cloudflare/wranglerv2">repository</a>. (we’ll merge them into the existing wrangler repository when 2.0 is out of beta).</p><p>Thank you to all of our developers out there, and we look forward to seeing what you build!</p>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div></div><p></p> ]]></content:encoded>
            <category><![CDATA[Full Stack Week]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Wrangler]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">1bz4lkxX4UPI3IDoREY8Ll</guid>
            <dc:creator>Ashcon Partovi</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
    </channel>
</rss>