Agent tracing is now available for applications built with the Agents SDK. Traces show each agent turn alongside model calls, tool runs, approvals, token usage, and Workers runtime operations.
Turn on Workers tracing in your Wrangler configuration:
Think and Flue applications emit agent traces automatically. For direct AI SDK calls, wrap the AI SDK namespace once. wrapAISDK() supports AI SDK v6 and v7. This AI SDK v7 example also supplies the agent identity:
import * as ai from "ai";import { wrapAISDK } from "agents/observability/ai";const tracedAI = wrapAISDK(ai);await tracedAI.generateText({ model, prompt: "Find an available appointment", runtimeContext: { agentId: "booking-agent-production", conversationId: "conversation-123", }, telemetry: { functionId: "booking-agent", includeRuntimeContext: { agentId: true, conversationId: true, }, },});
import * as ai from "ai";import { wrapAISDK } from "agents/observability/ai";const tracedAI = wrapAISDK(ai);await tracedAI.generateText({ model, prompt: "Find an available appointment", runtimeContext: { agentId: "booking-agent-production", conversationId: "conversation-123", }, telemetry: { functionId: "booking-agent", includeRuntimeContext: { agentId: true, conversationId: true, }, },});
Message and tool payload recording is off by default. Turn it on only when the payloads are safe to store:
Open the Agents tab ↗ in the Cloudflare dashboard to inspect sessions, replay conversations, and view trace waterfalls. For advanced setup, privacy controls, and trace structure, refer to Agent tracing.
wrangler dev and vite dev automatically capture structured OpenTelemetry traces and correlated console logs during local Worker invocations.
Debug with AI agents
When the tooling detects an AI agent session, it prints a terminal hint pointing to the Local Explorer API at /cdn-cgi/explorer/api. The API serves an OpenAPI schema and exposes a read-only observability query endpoint for discovering telemetry, querying traces and logs, and inspecting binding state.
The agent can identify the exact failing operation, fix the code, rerun the request, and verify the result. This debug loop requires no deployment or temporary logs.
Inspect traces in Local Explorer
Humans can inspect the same traces and correlated console logs in the Local Explorer browser UI. Each trace shows spans, timing, attributes, and errors.
Automatic spans cover handler calls, outbound fetch() calls, and binding calls. Custom spans appear alongside these automatic spans.
We're releasing an early preview of @cloudflare/computer ↗, an open-source agent runtime that gives every agent its own computer. The runtime dynamically orchestrates between fast, efficient isolates and full Linux containers, so the agent always runs on the right compute primitive for the task at hand.
@cloudflare/computer provides a virtual filesystem backed by SQLite, which you can populate from cloud storage, source control, or any files you choose. Agents can read, write, and edit files, run shell commands, and interact with Git repositories. All operations are gated, audited, and observed.
Install the package via npm:
npm install @cloudflare/computer
Instantiate a Workspace inside any Durable Object to give your agent a filesystem and execution runtime:
import { Workspace } from "@cloudflare/computer";export class Agent { workspace = new Workspace({ storage: this.ctx.storage, });}
Several execution backends are included or you can write your own:
Isolate runtime — fast, horizontally scalable execution via just-bash and Dynamic Workers, ideal for file manipulation and data processing.
Container runtime — full Linux environment via Cloudflare Containers, mounted through FUSE, for tasks that need native binaries, package managers, or a complete userland.
The AI SDK-compatible toolkit provides common agent tools (read, write, edit, ls, exec) and guides the model to choose the appropriate backend for each task.
You can now call methods between Python and JavaScript Workers using Workers RPC. This works through Service bindings without extra dependencies, schema definitions, or serialization code.
Cross-language RPC calls behave like ordinary function calls. Exceptions propagate to the call site. You can pass structured cloneable types ↗ as parameters or return values, and Pyodide Foreign Function Interface (FFI) automatically converts types between languages.
Call a TypeScript Worker from Python
Define a method in a TypeScript Worker:
index.jsjs
import { WorkerEntrypoint } from "cloudflare:workers";export class RpcService extends WorkerEntrypoint { async add(a, b) { return a + b; }}
index.tsts
import { WorkerEntrypoint } from "cloudflare:workers";export class RpcService extends WorkerEntrypoint { async add(a: number, b: number): Promise<number> { return a + b; }}
Call it from a Python Worker through a Service binding:
wrangler check startup now reports your Worker's raw and compressed bundle sizes. It also summarizes local CPU activity during startup directly in your terminal.
Large bundles and costly startup work can introduce cold-start latency, so use this command to find code and large dependencies that slow your Worker before it handles requests.
The summary includes sampled, active, garbage collection, and idle time. Wrangler continues to save a .cpuprofile file for detailed flamegraph analysis in Chrome DevTools or VS Code.
⛅️ wrangler 4.116.0───────────────────────────────────────────────├ Building your Worker│ Worker Built! 🎉│├ Analysing│ Startup phase analysed││ Bundle: 7171.25 KiB / gzip: 2197.00 KiB││ Local startup profile:│ Profile window: 70.3 ms│ Sampled time: 70.3 ms│ Active: 38.5 ms (including 3.7 ms garbage collection)│ Idle: 31.8 ms│ Samples: 36││ CPU Profile has been written to worker-startup.cpuprofile. Load it into the Chrome DevTools profiler (or directly in VSCode) to view a flamegraph.││ Note that the CPU Profile was measured on your Worker running locally on your machine, which has a different CPU than when your Worker runs on Cloudflare.││ As such, CPU Profile can be used to understand where time is spent at startup, but the overall startup time in the profile should not be expected to exactly match what your Worker's startup time will be when deploying to Cloudflare.
The profile runs locally, so its duration will differ from startup time on Cloudflare. For authoritative startup time, deploy your Worker or upload a version.
Available in Wrangler version 4.116.0 or later. For more information, refer to wrangler check startup.
Workers Builds now uses Node.js 24.18.0 by default. The build image preinstalls Node.js 22.23.2 and 24.18.0.
You can continue to override the default with the NODE_VERSION environment variable, an .nvmrc file, or a .node-version file. For more information, refer to Override default versions.
Cloudflare's product-specific MCP servers now support the new MCP 2026-07-28 Specification. Each request runs on a fresh stateless server without an MCP protocol session or protocol-specific Durable Object.
The /mcp endpoint also accepts stateless requests from 2025 Streamable HTTP clients. Most clients can reconnect without configuration changes.
Use /mcp for new connections. Historical /sse URLs continue to work as aliases for the same Streamable HTTP handler, but they no longer serve the deprecated HTTP+SSE transport. If a client forces SSE transport, change it to Streamable HTTP or automatic transport detection.
The Workers runtime now provides built-in tracing.startActiveSpan() and span.end() APIs, allowing you to write custom spans for operations that last beyond a single callback — for example, instrumenting a stream pipeline where the span should stay open until the stream is fully consumed.
This augments the existing API for writing custom spans, tracing.enterSpan(), which automatically ends a span when its callback is returned. With startActiveSpan(), the span remains open after the callback returns, and you call span.end() when the work is complete:
src/index.jsjs
import { tracing } from "cloudflare:workers";const encoder = new TextEncoder();export default { fetch() { return tracing.startActiveSpan("stream-response", (span) => { let timer; const body = new ReadableStream({ start(controller) { controller.enqueue(encoder.encode("Starting...\n")); timer = setTimeout(() => { controller.enqueue(encoder.encode("Complete.\n")); controller.close(); span.setAttribute("stream.status", "complete"); span.end(); }, 1000); }, cancel() { if (timer !== undefined) clearTimeout(timer); span.setAttribute("stream.status", "cancelled"); span.end(); }, }); return new Response(body, { headers: { "content-type": "text/plain" }, }); }); },};
Agents SDK v0.20.0 adds client and server support for the MCP 2026-07-28 release candidate ↗. Workers can serve tools, prompts, resources, and elicitation without an MCP transport session or Durable Object. Agents can connect to both MCP 2026-07-28 servers and existing legacy servers.
Client support
The MCP client manager now uses @modelcontextprotocol/client. For each connection, it probes for MCP 2026-07-28 support with server/discover. If the server does not support the stateless protocol, the client continues with the legacy initialize handshake on the same connection. Existing addMcpServer calls do not need a protocol-version setting or separate clients for each protocol generation.
For stateless requests, elicitation uses input_required through multi-round-trip requests (MRTR). The legacy path uses the same form and URL handlers for pushed requests. The SDK collects input, retries the original operation, and resolves the original callTool, getPrompt, or readResource promise with its final result.
OAuth callbacks now validate issuer metadata through the v2 SDK. Discovery state and issuer-bound credentials persist across browser redirects and Durable Object hibernation.
Run stateless servers
createMcpHandler now accepts a factory that returns a server from @modelcontextprotocol/server. The factory creates an isolated server for each request.
The isolated agents/mcp/server entry keeps McpAgent, WorkerTransport, MCP client transports, and SDK v1 modules out of stateless server bundles.
The Workers wrapper validates present browser Origins, supports explicit delegation to trusted Origin middleware, and exposes request handling plus typed change notifications.
Backward compatibility
The same createMcpHandler(createServer)(request, env, ctx) route serves MCP 2026-07-28 clients and legacy clients that use stateless requests. You do not need separate routes or tool definitions for ordinary tools, prompts, and resources.
McpAgent is deprecated and feature-frozen. Migrate existing McpAgent servers to the stateless handler at your earliest convenience. If a server depends on protocol sessions, RPC, pushed server-to-client requests, standalone streams, or replay, use the migration guide to design stateless equivalents and run both routes while clients transition.
Migrate existing SDK v1 servers
Upgrade the Agents SDK:
npm i agents@latest
yarn add agents@latest
pnpm add agents@latest
bun add agents@latest
Move ordinary SDK v1 server definitions into an SDK v2 factory and serve them with createMcpHandler. The handler's default legacy compatibility means most stateless deployments need only one route.
If an existing McpAgent server still needs sessionful features, add the stateless path beside it. Use isLegacyRequest() to send only legacy traffic to the existing route:
Migrate the remaining sessionful features, allow existing sessions to drain, then remove the legacy route. Refer to Migrate to MCP SDK v2 for package changes, compatibility limits, and rollout steps.
Deprecations in v0.20.0
This release deprecates the following Agents SDK APIs:
Deprecated API
Replacement
Status
McpAgent
Use an SDK v2 factory with createMcpHandler for stateless servers. Use the migration guide to replace stateful features before removing a legacy route.
Feature-frozen. No removal version is announced.
createMcpHandler(v1Server, options)
Move the server to an SDK v2 factory and call createMcpHandler(factory, options). Use createLegacyMcpHandler only as a temporary bridge for sessionful features.
Scheduled for removal in the next major version.
MCPClientManager.callTool(params, resultSchema, options) and the equivalent withX402Client overload
Use callTool(params, options) or callTool(confirm, params, options).
Compatibility overload. No removal version is announced.
The MCP 2026-07-28 draft separately deprecates Roots, Sampling, Logging, the old HTTP+SSE transport, and Dynamic Client Registration.
Wrangler now provides createTestHarness(), an API for running integration tests against Workers built with Wrangler or the Cloudflare Vite plugin from any Node.js test runner.
This release reduces repeated MCP schema conversion and adds an opt-out for Think's automatic MCP tool exposure. It also lets non-AI-SDK hosts invoke the durable Code Mode runtime directly.
Control direct MCP tool exposure in Think
Agents SDK MCP clients now reuse converted input and output schemas while a live connection keeps the same tool catalog. This avoids converting every MCP JSON Schema to Zod again for each model turn.
@cloudflare/think also adds includeMcpTools. Set it to false when you expose MCP tools through Code Mode or another mechanism outside Think's automatic tool set:
import { Think } from "@cloudflare/think";export class MyAgent extends Think { includeMcpTools = false; waitForMcpConnections = true;}
import { Think } from "@cloudflare/think";export class MyAgent extends Think<Env> { includeMcpTools = false; waitForMcpConnections = true;}
This setting skips Think's automatic getAITools() call. MCP registration, restoration, discovery, raw catalog access, direct calls, and Code Mode connectors continue to work.
@cloudflare/codemode@latest adds execute(), search(), and describe() to the durable runtime handle. MCP servers and other hosts can now execute code and discover connector methods without adapting the runtime to an AI SDK tool.
Search and describe results include requiresApproval: true for protected connector methods. Resolve a paused execution with the existing approve() and reject() methods.
We are turning on budget alerts by default for eligible Pay-as-you-go accounts. If your account does not already have a budget alert, Cloudflare will create one for you with a $10 account-level threshold. Your default alert will enable at the turn of your next billing cycle, so it will not fire based on usage you have already incurred.
We are rolling this out in cohorts over the coming weeks, so eligible accounts may see their default alert appear at different times.
The default alert behaves exactly like an alert you would create yourself. When your cumulative usage-based spend this cycle reaches the threshold, you receive an email notification. The alert is informational only. It does not cap your usage or impact your account in any way.
Usage is processed once per day for the prior day's activity, so budget alerts fire the day after the threshold is reached rather than in real time.
Budget alerts only consider spend on usage-based products. Recurring subscription fees, such as the Workers Paid plan fee or other monthly plan charges, are not included in the threshold calculation.
You can change the threshold, add additional alerts, or remove the default alert entirely from Manage Account > Billing > Billable Usage, or from your Notifications settings. If you already configured your own budget alert, nothing changes.
You can now monitor the total SQLite storage used by a Durable Object namespace over time in the Cloudflare dashboard. The new Total storage chart shows the maximum storage reported during each hour. This helps you identify storage growth, validate data cleanup, and investigate unexpected usage.
The chart appears only for SQLite-backed Durable Object namespaces. It does not appear for namespaces that use the legacy key-value storage backend. Viewing storage for individual Durable Objects by ID or name is not supported.
Platforms can now create temporary preview accounts through the Cloudflare REST API. This lets your platform deploy a live Worker before the user signs in to Cloudflare.
With the Temporary Accounts API, coding agents, AI app builders, and other platforms can build a similar flow for generated Workers and supported resources.
Your platform can keep users in its onboarding flow while they generate, deploy, and test an application. Users do not need an existing Cloudflare account, and your platform does not need write access to one.
The API returns a claim URL that lets the user make the temporary account and its resources permanent.
Cloudflare Drop ↗ demonstrates this preview-and-claim pattern for static sites. Someone can upload a site, test and share it for one hour, then sign in or create an account only when they want to keep it.
This API expands the flow first introduced with wrangler deploy --temporary. Your backend now controls the provisioning and deployment experience directly:
Show Cloudflare's Terms of Service and Privacy Policy in your product, and require the user to accept them.
Request and solve a proof-of-work challenge.
Create a temporary preview account.
Deploy with the returned temporary account ID and API token.
Show the deployed Worker URL and claim URL to the user.
Agents connected to Model Context Protocol (MCP) servers with addMcpServer can now handle elicitation ↗ requests.
Elicitation lets an MCP server request user input while it handles a tool call. Form mode collects structured, non-sensitive data. URL mode asks for consent before opening an out-of-band flow, such as third-party authorization or payment.
sequenceDiagram
participant User
participant Agent as Agent (MCP client)
participant Server as MCP server
participant Browser
Server->>Agent: elicitation/create
Agent->>User: Show server, reason, and input or URL
User->>Agent: Submit, open, decline, or cancel
Agent->>Browser: Open URL after consent (URL mode)
Agent->>Server: accept, decline, or cancel
Server-->>Agent: Optional URL completion notification
Register a handler for each mode your Agent supports in onStart():
import { Agent } from "agents";export class MyAgent extends Agent { onStart() { this.mcp.configureElicitationHandlers({ form: (request, serverId) => this.forwardToUser(request, serverId), url: (request, serverId) => this.forwardToUser(request, serverId), }); } forwardToUser(request, serverId) { // Show the request in your UI and resolve after the user responds. throw new Error( `Implement elicitation for ${serverId}: ${request.params.message}`, ); }}
import { Agent } from "agents";import type { ElicitRequest, ElicitResult } from "agents/mcp";export class MyAgent extends Agent<Env> { onStart() { this.mcp.configureElicitationHandlers({ form: (request, serverId) => this.forwardToUser(request, serverId), url: (request, serverId) => this.forwardToUser(request, serverId), }); } private forwardToUser( request: ElicitRequest, serverId: string, ): Promise<ElicitResult> { // Show the request in your UI and resolve after the user responds. throw new Error( `Implement elicitation for ${serverId}: ${request.params.message}`, ); }}
Connections advertise only the modes with configured handlers. An Agent without handlers advertises no elicitation capability, which lets the server use its fallback. The SDK stores the advertised modes with each MCP server registration so they survive Durable Object hibernation. Callback functions remain in memory and reattach when onStart() runs.
If your account does not already have a key-value (KV) backed Durable Object namespace, you can no longer create new ones. New Durable Object namespaces must use the SQLite storage backend, which has been recommended for all new Durable Objects since it became generally available ↗ in 2024.
Create a new class with a new_sqlite_classes migration:
SQLite-backed Durable Objects have feature parity with the key-value backend — including the key-value storage API — and additionally support relational SQL queries and point-in-time recovery to restore an object's storage to any point in the past 30 days.
If you attempt to create a new key-value backed namespace (a new_classes migration) on an affected account, the deployment fails with the following error:
Creating new key-value backed Durable Object namespaces is no longer supported on this account. Please create a namespace using a `new_sqlite_classes` migration instead.
This change only affects accounts that are not already using the key-value storage backend. Accounts with at least one existing key-value backed namespace can still create new ones for now, and the Workers Free plan has only ever supported SQLite-backed Durable Objects. It is part of a broader move toward SQLite as the single storage backend for Durable Objects, ahead of a future migration path for existing key-value backed objects.
Wrangler now collects npm package dependency information from your project's package.json during wrangler deploy and wrangler versions upload, and includes it in the upload metadata sent to the Cloudflare API. This data, each dependency's name, declared version range, and exact installed version, enables dependency analytics and future supply chain security features such as vulnerability alerting.
Cloudflare Drop ↗ lets you deploy a static site to Cloudflare without requiring a Cloudflare account to get started.
Upload a folder or zip file of static assets (static HTML, CSS, JavaScript, images, and fonts) and get a temporary live preview that stays live for 1 hour. During that window, you can test the site, share the preview URL, or claim the deployment to keep it.
When you are ready to make the deployment permanent, click Claim to sign in or create a Cloudflare account. You can claim the site into an existing Cloudflare account or create a new account for the deployment.
After claiming the site, you can:
Add a domain: Connect an existing domain or purchase a new one for your site.
Enable observability: Monitor your site's performance and usage.
Enable Markdown for Agents: Allow AI agents to access your site's content in Markdown.
Control access: Make your site private and choose who can view it.
A new declarative exports field in your Wrangler configuration file replaces the imperative migrations array for managing Durable Object class lifecycle. Instead of writing an ordered list of migration steps with unique tags, you declare each Durable Object class your Worker exports and Cloudflare compares that against what's already deployed to determine what Durable Object state needs to be created, renamed, or deleted.
With legacy migrations, renaming ChatRoom to Room requires retaining both tagged steps:
Each entry is keyed by class name. The state field carries the lifecycle (created by default — a live class — plus tombstone states deleted, renamed, and transferred, and the expecting-transfer receiving state for cross-Worker transfers).
Key improvements over the legacy migrations array:
No migration tags. The current exports map is the source of truth — there is no historical chain of v1, v2, v3 entries to maintain.
Structured deployment output. Wrangler reports when it creates, updates, deletes, renames, or transfers Durable Object classes. It also identifies stale configuration entries that are safe to remove. Deployments with no changes or notices do not print this output.
Zero-downtime rename and transfer patterns are first-class. Tombstones may coexist with the source class still in code, enabling a three-deploy rename and a four-deploy cross-Worker transfer without runtime errors during the rollout window.
Cross-Worker safety. When you delete or rename a class, Cloudflare lists every other Worker in your account whose bindings still reference the namespace, so you can redeploy them before the change goes live.
Existing Workers using the legacy migrations array continue to work unchanged. To move to exports, refer to the migration guide. exports and migrations are mutually exclusive within a single Worker.
We have released version 5 of @cloudflare/workers-types ↗. This release simplifies the package to expose only the latest runtime types.
We still recommend that you generate types for your Worker using wrangler types, but if you want to use the package directly, you can install it with your package manager of choice:
npm i -D @cloudflare/workers-types@latest
yarn add -D @cloudflare/workers-types@latest
pnpm add -D @cloudflare/workers-types@latest
bun add -d @cloudflare/workers-types@latest
The package now exposes two entrypoints:
@cloudflare/workers-types reflects the latest compatibility date, using the latest stable compatibility flags.
The dated entrypoints, such as @cloudflare/workers-types/2022-11-30 and @cloudflare/workers-types/2023-03-01, are removed. With runtime type generation in Wrangler v4, you can generate these with the wrangler types command to create types locked to your Worker's compatibility date.
Wrangler CLI now supports auth profiles: named logins that you scope to specific Cloudflare accounts and switch between automatically, based on the directory you are working in.
A profile is a named OAuth login bound to a directory. Commands run in that directory, and its subdirectories, use the matching account — so you can move between accounts without re-running wrangler login.
Use profiles to keep a separate login for each client when working at an agency, or to separate staging and production into different accounts. Pair a profile with an account_id in your Wrangler configuration file so a command cannot reach the wrong account.
# Create a profile for each account, choosing which accounts it can reachwrangler auth create client-awrangler auth activate client-a ~/clients/client-awrangler auth create client-bwrangler auth activate client-b ~/clients/client-b
Use the --profile flag to run a single command with a specific profile:
wrangler deploy --profile personal
In CI and other automated environments, CLOUDFLARE_API_TOKEN still takes precedence over all profiles.
For setup, the resolution order, and the full command reference, refer to Authentication profiles.
You can now monitor how much memory your Workers and Durable Objects consume across invocations with the new Memory Usage chart in the Workers Metrics tab, broken down by P50, P90, P99, and P999 percentiles.
Memory usage measures the V8 isolate memory at the time of each invocation, subject to the 128 MB per-isolate limit — a single isolate can handle many concurrent requests and shares memory across them.
Use the Memory Usage chart to:
Track memory trends — Spot gradual increases that may indicate a memory leak before they cause Exceeded Memory errors.
Correlate with deployments — Deployment markers on the chart help you identify whether a new version introduced a memory regression.
Right-size your Worker — Understand your baseline memory footprint and how much headroom you have before hitting the 128 MB limit.
For Durable Objects, memory usage reflects the in-memory state an object holds (class properties, caches, active WebSocket connections), which persists across invocations until the object is hibernated or evicted. This state is not preserved across eviction, hibernation, or a crash, so persist anything important to storage.
To view memory usage, open the Metrics tab for your Worker ↗ or Durable Object namespace ↗. For Durable Objects, you can filter by DO ID or name to drill down into memory usage for a specific object. You can also query memory usage programmatically via the GraphQL Analytics API using the workersInvocationsAdaptive dataset — the quantiles.memoryUsageBytesP50 through quantiles.memoryUsageBytesP999 fields return percentile values in bytes.
For local memory debugging, you can also profile memory with DevTools to take heap snapshots and identify specific objects causing high memory usage.
Workers fetch() requests now support the cf.vary request option. Use cf.vary to control how Cloudflare caches origin responses with a Vary header for a single subrequest.
The latest release of the Agents SDK ↗ makes it easier to run long work in the background, drive turns through one entry point, and keep chat agents working through deploys, evictions, and reconnects.
This release adds first-class detached (background) sub-agent runs with live progress and durable milestones, a single runTurn turn-admission entry point, and a large round of recovery and reliability fixes that continue converging @cloudflare/think and @cloudflare/ai-chat onto one model.
Background sub-agents with progress and milestones
runAgentTool can now dispatch a sub-agent without blocking the calling turn. A detached run returns a handle immediately and is owned by a durable, eviction-surviving backbone instead of being abandoned when the dispatching turn ends.
Durable, exactly-once-on-the-happy-path completion via a warm fast path plus a self-scheduling reconcile backbone that survives eviction and deploys.
Bounded. An absolute maxBudgetMs ceiling (default 24h) and cancelAgentTool(runId) keep abandoned runs from holding a concurrency slot forever.
detached: { notify: true } lets a finished background run inject a message back into the chat so the model reacts to the result — no hand-wired onFinish needed.
Sub-agents can also report mid-run progress that rides their own turn stream back to the parent's connected clients:
// Inside the child sub-agent:await this.reportProgress({ fraction: 0.6, phase: "deploying", message: "Generating menu page…",});
// Inside the child sub-agent:await this.reportProgress({ fraction: 0.6, phase: "deploying", message: "Generating menu page…",});
Progress surfaces on AgentToolRunState.progress via useAgentToolEvents, so a background-runs tray can render a live bar without drilling in, and the latest snapshot is persisted for inspection after eviction. Naming a milestone promotes a signal to a durable, replayable row, and detached: { onMilestones } can surface a milestone as a synthetic chat message ("narrate" for a cheap status line, or "react" to drive a model turn).
One entry point for turns: runTurn
@cloudflare/think adds a public runTurn(options) facade that unifies turn admission behind a single mode:
stream mode accepts array and function inputs to match wait mode, and all entry points now route through a shared internal admission path that throws a clear error on nested blocking admissions that previously could deadlock.
Recovery and reliability
A large part of this release continues hardening recovery and converging @cloudflare/think and @cloudflare/ai-chat onto one model:
Stream stall watchdog.AIChatAgent can detect and recover from a hung model/transport stream via the opt-in chatStreamStallTimeoutMs watchdog. With chatRecovery enabled the stall routes into the same bounded-recovery machinery a deploy or eviction uses; otherwise it surfaces as a terminal stream error so the spinner clears.
Interrupted tool-call repair.AIChatAgent now repairs a transcript with a dead server-tool call before re-entering inference (parity with @cloudflare/think), so a recovered turn no longer fails with AI_MissingToolResultsError. An overridable repairInterruptedToolPart(part) hook lets apps customize the repaired shape.
Stuck status after reconnect. Fixed AI SDK status getting stuck when a reconnect races a turn that has been accepted but has not started streaming yet, so the UI now renders the in-flight turn instead of settling on ready.
Live "recovering…" on connect.AIChatAgent now replays the recovering status to a client that connects mid-recovery, so useAgentChat's isRecovering reflects in-progress recovery immediately instead of appearing frozen.
Terminal connection failures. The client stops reconnecting on terminal WebSocket close events and exposes them via connectionError / onConnectionError on AgentClient, useAgent, and useAgentChat.
Agent-tool child recovery. A healthy long-running sub-agent run is no longer abandoned as interrupted after a deploy (both @cloudflare/think and AIChatAgent).
Workflows from sub-agent facets. Agent Workflows can now start from sub-agent facets, with callbacks and Workflow RPC routed back to the originating facet.
Plus forward-progress crediting convergence, broadcast-first give-up ordering, an event-driven auto-continuation barrier, and structured row-size compaction in AIChatAgent.
Other improvements
Shared chat React core. A new agents/chat/react entry exposes useAgentChat, transport helpers, and shared wire types, with syncMessagesToServer for server-authoritative transcript storage. @cloudflare/think/react and @cloudflare/ai-chat/react are now thin wrappers over it.
Optional ai peer. The root agents and @cloudflare/codemode runtimes no longer reference AI SDK types, so they bundle without ai / zod installed; AI-specific entry points still require the peer when imported. just-bash likewise moves to an optional peer used only by the skills bash runner.
Code Mode. The default DynamicWorkerExecutor timeout increases from 30s to 60s, executions now dispose the dynamically-loaded Worker and its RPC stub after each run (fixing a flaky isolate-shutdown assertion), connector imports are cleaned up, and the outer MCP tool-call context is passed to openApiMcpServer request callbacks.
Voice. Voice turns now support AI SDK fullStream responses (and warn when textStream is used).
MCP.McpAgent server-to-client requests can now be sent from callbacks that do not inherit the agent's async context, including callbacks reached through Worker Loader RPC.
Experimental: server actions and channels. This release lays groundwork for guarded server actions (action() / getActions() with a durable replay ledger and approvals) and a unified channels surface (configureChannels(), deliverNotice()). Both are experimental and their APIs may change, so we don't recommend depending on them yet.
Upgrade
To update to the latest version:
npm i agents@latest @cloudflare/think@latest @cloudflare/ai-chat@latest @cloudflare/codemode@latest @cloudflare/voice@latest
Durable Objects now supports a usjurisdiction, letting you create Durable Objects that only run and store data within the United States. Use the us jurisdiction when you need to keep a Durable Object's compute and storage inside the United States to meet data residency requirements.
Create a namespace restricted to the us jurisdiction the same way as any other jurisdiction:
Workers may still access Durable Objects constrained to the us jurisdiction from anywhere in the world. The jurisdiction constraint only controls where the Durable Object itself runs and persists data.