Workers Issues provides built-in error monitoring for Cloudflare Workers. It detects production failures and groups related failures into issues without an SDK or application wrapper.
The Cloudflare API MCP server now sends these issues as MCP Events ↗︎, the first event it exposes. MCP clients discover cloudflare.alert.workers_observability_real_time_issue with events/list and subscribe with events/subscribe, scoped to an account or a single Worker. When Issues detects a new or recurring issue, the server posts a signed event to the client's webhook, so an agent can start investigating without polling.
To use it, enable Issues on your Worker and connect https://mcp.cloudflare.com/mcp with the Notifications Write and Workers Observability Write permissions to a client that supports MCP Events webhooks.
The Cloudflare Agents SDK now provides a browserTool that gives your agent a Browser Run browser it can return to on later turns. Your agent can open a website, inspect a page, and come back to it with its tabs, cookies, and login session intact while the browser session remains alive.
When you give browserTool to your agent, the model writes code that drives the browser through the Chrome DevTools Protocol (CDP). Screenshots return as images that an image-capable model can inspect and your UI can display.
Each Pi conversation gets its own active tab by default. Cookies and logins remain shared within the browser.
The browser stays alive between turns, including when the Durable Object hibernates. Its default idle timeout is 10 minutes. If the session expires or crashes, the tool creates a fresh browser and reports restarted: true. The old tabs and login state are gone.
You can also use the persistent browser with the AI SDK and TanStack AI adapters, or connect another harness through the public Browser and CDP APIs.
Refer to persistent browser tools for the complete Pi Durable example, required bindings, and behavior when a tool call is interrupted.
You can now request DNS64 through Cloudflare Gateway DNS location settings or Extension Mechanisms for DNS (EDNS) options.
DNS64 synthesizes AAAA records from A records for IPv6-only networks. These networks require network address translation from IPv6 to IPv4 (NAT64).
Turn on Enable DNS64 for a location, or include an empty EDNS option 65051 in individual queries. Both mechanisms support UDP, TCP, DNS over TLS (DoT), and DNS over HTTPS (DoH).
The existing cf-dns-options: dns64 DoH header remains supported independently. DNS64 is off by default. Each mechanism independently requests synthesis.
For configuration, API update behavior, and request examples, refer to DNS64.
The Core Web Vitals tell you whether a page is slow but beyond perceived load time, layout instability, or responsiveness they do not guide you to the problematic area directly. To help you with this, Real User Monitoring (RUM) in Web Analytics now breaks Largest Contentful Paint (LCP) and Interaction to Next Paint (INP) into their respective sub-parts. It also splits connection time into TCP and TLS. You can see this visualised in the dashboard or query it through the GraphQL Analytics API.
LCP sub-parts
LCP is broken into four phases, so you can see which one is impacting your perceived load time:
Time to First Byte: how long the browser waits for the HTML document (timeToFirstByte in GraphQL).
Resource load delay: how long the browser takes to discover the LCP resource after the document starts arriving (lcpResourceLoadDelay).
Resource load duration: how long it takes to download that resource (lcpResourceLoadTime).
Element render delay: the gap between the resource arriving and the element appearing on screen (lcpElementRenderDelay).
You do not have to remember all this detail, there are tooltips available to guide you next to each sub-part metric in the dashboard.
INP sub-parts
INP is broken into three phases, guiding you to the area slowing down responsiveness:
Input delay: how long an interaction (click, tap or key press) is blocked before it can be processed (inpInputDelay).
Processing duration: how long your event handlers take to run (inpProcessingDuration).
Presentation delay: how long the browser takes to render the next frame after the handlers finish (inpPresentationDelay).
TCP and TLS timing
The page load timing breakdown now separates connection setup from the TLS handshake, so you can tell a slow network path from a slow TLS negotiation:
Connection time (excluding TLS) (connectionTimeWithoutTLS)
TLS handshake time: (tlsTime).
Note: we've retained connectionTime in the GraphQL API so you can still analyze the combined time.
How to query the GraphQL data
The sub-parts are available on rumWebVitalsEventsAdaptiveGroups as percentiles, for example: lcpResourceLoadDelayP50 or inpInputDelayP50. The connection split is available on rumPerformanceEventsAdaptiveGroups as connectionTimeWithoutTLSP50 and tlsTimeP50, and so on for the other percentiles.
The percentiles available are: P25, P50, P75, P90, P95, P99, P999. All values are in microseconds. A negative value means the data is not available.
Head to the 'Core Web Vitals' section, here you can scroll down the report to see the sub-parts. The 'Page Load' section contains the Connection and TLS negotiation durations.
Cloudflare now preserves Workers context when a subrequest targets a Cloudflare-proxied hostname using Bring Your Own IP (BYOIP). These requests are identified as Cloudflare-to-Cloudflare traffic instead of external Internet traffic.
Previously, some BYOIP subrequests could lose Workers context and original client signals. This could cause security rules to behave unexpectedly, Bot Management to evaluate an internal Cloudflare connection instead of the original client, or affected requests to return false 403 responses.
Workers subrequests to BYOIP destinations now preserve the CF-Worker header and cf.worker.upstream_zone field. This supports consistent security rule evaluation across same-zone and cross-zone subrequests.
Bot Management fields on the destination zone now represent the original end-user connection for affected BYOIP subrequests. Bot scores, verified bot status, and JA3/JA4 fingerprints no longer represent the internal connection between Cloudflare services.
Customers benefit from consistent security rule evaluation, accurate Bot Management results, and fewer unexpected failures when Workers access BYOIP-backed hostnames. The improvement is automatic and requires no configuration changes.
This hotfix resolves an issue where the client could repeatedly disconnect and reconnect when a split tunnel configuration with hostname-based entries failed to apply.
This hotfix resolves an issue where the client could repeatedly disconnect and reconnect when a split tunnel configuration with hostname-based entries failed to apply.
This hotfix resolves an issue where the client could repeatedly disconnect and reconnect when a split tunnel configuration with hostname-based entries failed to apply.
The Cloudflare Agents SDK now provides a web_fetch tool that reads webpages, PDFs, and supported Office documents, using Workers AI Markdown Conversion to turn them into text the model can read. The tool requests Markdown directly from sites that support Markdown for Agents and formats JSON for the model.
When you give the web_fetch tool to your agent, the model provides a URL and receives back the page content, along with the final URL, HTTP status, and content type. Long pages come back in smaller sections, with an offset the model can use to continue reading. You control which hosts the agent can fetch, response size, timeouts, and redirects.
When you also provide the web_search tool to your agent, the model is told to use web_fetch to read the pages that web_search returns.
The web_fetch tool works with any harness. The SDK includes AI SDK and TanStack AI adapters. If you use a different harness, or need to fetch a page without calling a model, use fetchWeb(), windowWebFetchPage(), and renderWebFetchPage() from agents/webfetch. Direct fetching does not require a Durable Object or browser.
For setup, examples, and request controls, refer to Web fetch.
The Agents SDK now supports OpenCode 2.0 ↗︎ through the experimental OpenCodeHarness. Run OpenCode inside a plain Durable Object, with sessions stored in SQLite and Lifecycle jobs that wake interrupted work after eviction.
The agents/models/opencode provider connects OpenCode to Workers AI through the AI binding. OpenCode plugins extend the harness with custom tools, remote MCP servers, and skills. Refer to OpenCode's Cloudflare SDK documentation ↗︎ for the embedded host API.
Install Agents SDK 0.28.0 or later with the OpenCode packages:
npm i agents@latest @opencode/sdk@2 @opencode/plugin@2
The OpenCode harness guide includes the workerTools plugin, Wrangler configuration, and session APIs. The working example ↗︎ adds a browser UI, WebSocket streaming, and Workspace tools from @cloudflare/computer for files and code execution.
When you give the web_search tool to your agent, the model provides a query and max results, and receives back a short numbered list of titles, URLs, and trimmed descriptions. When you also provide the web_fetch tool to your agent, the model is told to use it to read the pages that the web_search tool returns.
The SDK also includes AI SDK and TanStack AI adapters. To search without a model, such as from a scheduled job, use createAIWebSearch() or createHTTPWebSearch() from agents/websearch.
For setup, options, and error handling, refer to Web search.
You can now manually request an API Shield schema learning run without waiting for the weekly schedule. Use this during testing after sending representative traffic to your API.
In Web Assets > Operations, open the More options menu for the operations table and select Ad-hoc learn schema. In the Schema learning dialog, select Run learning. The run covers the entire zone and uses observed traffic. Existing learning thresholds still apply.
The dialog shows the learning status and last completed run for the zone. The Learned schema view shows the learning result and last learning run for each operation. You can review individual results while the zone-wide run continues.
The Cloudflare dashboard now combines Zero Trust and main dashboard navigation. You can move between Cloudflare products from the same navigation.
All customers can browse Zero Trust products from the primary navigation.
Zero Trust customers can also access other services from this navigation. These include the developer platform, account memberships, and resource tagging.
As part of this change, the Zero Trust Network items were removed in favor of the new experiences available under Networking navigation, and Resolvers & Proxies was moved under Traffic Controls (previously Traffic Policies).
This update is available to all customers starting today.
You can now create Cloudflare Queues with jurisdictional restrictions, ensuring that messages published to a queue are stored and processed only within a specific jurisdiction. This helps you comply with data residency requirements such as the GDPR ↗︎ or FedRAMP ↗︎.
To create a jurisdiction-restricted queue with the Cloudflare CLI (cf), use the --jurisdiction flag:
cf queues create --queue-name my-eu-queue --jurisdiction eu
You can also pass a jurisdiction parameter when calling the Create Queue endpoint:
Supported jurisdictions are eu (European Union), us (United States), and fedramp (FedRAMP-Moderate data centers). Jurisdiction can only be set when a queue is created and cannot be changed afterwards.
This release introduces new detections to mitigate recent vulnerabilities affecting TanStack and Atlassian products.
Key Findings
CVE-2026-102989: A reflected Cross-Site Scripting (XSS) vulnerability affecting TanStack. Unauthenticated attackers can exploit this flaw to inject malicious scripts into web pages viewed by other users, potentially leading to session hijacking or unauthorized actions.
CVE-2026-21589: An arbitrary file access vulnerability affecting Atlassian products. Threat actors can exploit this flaw to read unauthorized files on the target system, risking the exposure of sensitive configuration data.
Ruleset
Rule ID
Legacy Rule ID
Description
Previous Action
New Action
Comments
Cloudflare Managed Ruleset
N/A
Generic Rules - Template Injection - 2 - Beta
Disabled
Disabled
This rule is merged into the original rule "Generic Rules - Template Injection - 2" (ID: ).
Workers Builds now consistently posts preview URLs to GitHub pull requests and GitLab merge requests within a few seconds of a build completing, so you can start testing and reviewing your changes sooner. Previously, posting preview URLs could often take minutes.
Pending requests and connections to Workers now have a grace period of up to 20 minutes during Workers runtime updates. Previously, the grace period was up to 30 seconds.
This gives long-running HTTP requests, streamed AI responses, and live WebSocket sessions more time to continue before an update interrupts them.
New incoming HTTP requests go to the updated version of the Workers runtime once it is ready. Processes running the previous version stop accepting these requests and drain existing work. The grace period applies to each process running the previous version. When it ends, unfinished requests and open connections on that process are terminated.
You should design your application to reconnect WebSockets, safely retry interrupted requests, and recover saved state after a restart. WebSockets can disconnect before the grace period ends, including connections using the WebSocket Hibernation API.
Cloudflare has improved how it handles and reports client-cancelled HTTP/3 requests across Free, Pro, Business, and Enterprise plans. Customers now get a clearer view of client behavior in Cloudflare analytics and, where available, logs.
Previously, Cloudflare did not always stop an HTTP/3 request when the client cancelled its request stream. Some cancellations were already recorded as 499, while others continued to the origin and showed the eventual upstream status.
Cloudflare now stops affected requests sooner, reducing unnecessary origin work, and records them as 499. Customers may notice more 499 status codes for HTTP/3 traffic. This reflects more consistent reporting of existing cancellations, not an increase in failed requests.
Customers who use 499 status codes in availability calculations should consider excluding them from server-side error rates because they represent requests cancelled by clients.
Markdown for Agents now converts HTML with an in-process streaming engine at the edge. It processes content as it arrives instead of buffering the HTML response and sending it to a separate conversion service. This reduces conversion overhead and memory use.
This release also changes the conversion limit and response headers:
Conversion supports up to 6 MiB (6,291,456 bytes) of decompressed HTML, increased from 2 MiB (2,097,152 bytes). The limit applies after decompression, not to the compressed response size.
Converted responses no longer generate the x-markdown-tokens or x-original-tokens headers. Clients that use these values need to calculate token counts themselves.
Content-Length is removed from converted responses rather than recalculated, because the Markdown body is streamed.
You can now view R2 bandwidth by the Cloudflare location that served each request in the Cloudflare UI. This helps you see which locations consume the most bandwidth with options to select a specific bucket and download (read) vs upload (write) bandwidth.
By default, the chart shows the top five locations by total bandwidth consumed during the selected time range. Use the Top 5 locations dropdown to select other locations, up to six at a time.
You can now use cf.appsec.request.failed_detections to control how your rules handle requests when a security detection reports a failure.
The field is an Array<String> of detection IDs that reports failures from content scanning, WAF attack score, attack signature detection, leaked credentials detection, and AI prompt detections for personally identifiable information (PII), prompt injection, custom topics, and unsafe topics.
The field does not alter the existing behavior of detections. Use it in rules to choose how to handle requests with reported failures.
When no failures are reported, the field returns []. You can use it on all plans, but your plan must still include the detections and rule features you want to use.
Supported rules:
Custom rules at the zone and account levels
Rate limiting rules at the zone and account levels
Request Header Transform Rules at the zone level
Match any reported failure:
len(cf.appsec.request.failed_detections) gt 0
Match a reported leaked credentials detection failure:
@cf/cloudflare/clef-omni is now available on Workers AI. Clef-omni is a decision model that takes audio (WAV or MP3) and video (MP4 or WebM) input alongside text and images. It joins Clef and Clef-flash in the Clef family of open-weight decision models. We also cut the price of Clef-flash, so it now costs less than Jev, and made Clef faster.
Clef-omni: one decision model for every modality
Previously, making a decision about a voice recording or a video meant chaining models together: transcribe the speech, split the audio and visual tracks, then pass the results to a text decision model. Clef-omni reads every modality directly in one request. A video's soundtrack is aligned with its frames, so the model can reason over what is seen and heard at the same time.
Clef-omni is built on a 30B-parameter mixture-of-experts (MoE) backbone with 3B active parameters. Like the rest of the Clef family, it does not generate text. It scores every allowed answer in a single pass, so decisions return quickly:
Text requests: about 20 ms
Image or audio inputs: under 100 ms
A 21-second video clip with sound: about 300 ms
Pass media as base64 data URLs in the images, audio, and videos fields:
const response = await env.AI.run("@cf/cloudflare/clef-omni", { model: "clef-omni", state: "Review the installation: a photo of the unit, an audio recording of it running, and a video of the fan.", images: ["data:image/png;base64,<base64-png>"], audio: ["data:audio/mpeg;base64,<base64-mp3>"], videos: ["data:video/mp4;base64,<base64-mp4>"], questions: { label_visible: { type: "noul", instructions: "Is the model and serial number label visible in the photo?", }, sounds_normal: { type: "noul", instructions: "Does the unit sound like it is running smoothly, without rattling or grinding?", }, fan_running: { type: "noul", instructions: "Is the fan running in the video?", }, },});
const response = await env.AI.run("@cf/cloudflare/clef-omni", { model: "clef-omni", state: "Review the installation: a photo of the unit, an audio recording of it running, and a video of the fan.", images: ["data:image/png;base64,<base64-png>"], audio: ["data:audio/mpeg;base64,<base64-mp3>"], videos: ["data:video/mp4;base64,<base64-mp4>"], questions: { label_visible: { type: "noul", instructions: "Is the model and serial number label visible in the photo?", }, sounds_normal: { type: "noul", instructions: "Does the unit sound like it is running smoothly, without rattling or grinding?", }, fan_running: { type: "noul", instructions: "Is the fan running in the video?", }, },});
Clef-omni scores highest of the Clef family on BANKING77, CLINC150+OOS, and Amazon ESCI:
Benchmark
Clef-omni
Clef
Clef-flash
Jev
BFCL (case exact)
98.2
98.47
98.76
95.75
BANKING77 (macro-F1)
94.8
94.20
90.93
79.74
CLINC150+OOS (macro-F1)
97.7
97.43
66.77
89.27
Amazon ESCI (macro-F1)
57.8
57.48
57.39
55.21
PhishNChips (accuracy)
73.2
79.60
75.05
62.55
Clef-flash is now cheaper
Clef-flash now costs $0.038 per million input tokens, down from $0.090, which makes it cheaper than Jev. To offer this price, the hosted Clef-flash context window is now 24K tokens, down from 64K. Based on usage data, only 0.24% of requests exceed 24K input tokens. If you need a larger context window, use Clef, which keeps its 64K context window.
The Clef-flash weights on Hugging Face are unchanged and support up to a 256K context window if you self-host.
All Clef models convert image inputs to input tokens, and Clef-omni does the same for audio and video. For details on how each input type is tokenized, refer to the Clef, Clef-flash, and Clef-omni model pages.
Clef is now faster
We optimized how Clef is served on Workers AI, so it now returns decisions up to 2x faster. The model weights are unchanged.
Input size
Before: median / p95 (ms)
Now: median / p95 (ms)
Median speedup
~800 tokens
262 / 438
152 / 351
1.7x
~3,400 tokens
616 / 777
305 / 531
2.0x
~16,000 tokens
2,721 / 3,250
1,635 / 1,805
1.7x
Part of this speedup comes from moving Clef to SGLang ↗︎. Clef support is coming to SGLang in version 0.5.22 (PR #42721 ↗︎). If you self-host Clef, launch commands are available in the Clef collection on Hugging Face ↗︎.
Get started
Clef-omni follows the same System One API as Clef and Clef-flash, and works with AI Gateway. To try it, change the model ID to @cf/cloudflare/clef-omni and set the model selector to clef-omni.
createBatch() now accepts an options object that creates up to 100 Workflow instances in one call. The result lists the created instances and explains why any others were not created. To use this form in local development and get its types from wrangler types, use Wrangler 4.148.0 or later.
To create instances that share the same options, pass count. Each instance receives a generated ID:
created contains the created instances. errors contains each entry that was not created, identified by its position in the input. IDs that already exist and IDs repeated within the batch are reported as errors instead of being skipped silently.
Passing an array to createBatch() is deprecated. Existing code that uses the array form continues to work.