Surprise upgrade! Cloudflare's Agents SDK now ships retries built in!
Hey, it's me! Cloudflare just shipped a new version of the Agents SDK, and when I peeked inside I found retry handling baked right in. It's a quiet release, but it's packed with things developers have clearly been wishing for.
Cloudflare ChangelogWhat was announced?
Cloudflare Changelog announced Agents SDK v0.5.0. The headline items are:
- Built-in retry utilities via
this.retry() - Per-connection control over protocol messages
- A rewritten
@cloudflare/ai-chatv0.1.0 with data parts, persisted tool approvals, and more
The Agents SDK is the framework for building stateful AI agents on Cloudflare Workers, and this release focuses on making agents more reliable and chat UIs more pleasant to work with.
The story so far
Until now, if a call to some flaky external API failed, you had to write your own retry logic, including exponential backoff and jitter. If you wanted queued or scheduled tasks to carry their own retry settings, you had to build that yourself too.
On the WebSocket side, every connection automatically received JSON protocol messages (connection ID, state, MCP server list). For binary-only embedded devices or MQTT clients, those extra messages could get in the way.
@cloudflare/ai-chat had its own rough edges: tool approval state could get lost across page reloads or Durable Object hibernation, and there were race conditions around resuming streams.
What changes
You can now wrap any flaky async call in this.retry() and get exponential backoff with jitter for free, replacing hand-rolled retry logic with a standard SDK primitive.
If you're connecting embedded or IoT-style WebSocket clients, you can now turn off the extra protocol messages per connection, keeping the wire traffic clean.
For anyone building chat UIs, @cloudflare/ai-chat v0.1.0 is the bigger win: pending tool approvals now survive page refreshes, and data parts let you attach typed, structured data to messages.
Importantly, there are zero breaking changes — existing AIChatAgent and useAgentChat code keeps working as-is.
Dive Deep
this.retry() takes an async function plus options like maxAttempts and a shouldRetry predicate that decides whether a given error is worth retrying.
const data = await this.retry(() => callUnreliableService(), {
maxAttempts: 4,
shouldRetry: (err) => !(err instanceof PermanentError),
});
Retry options can also be passed per task to queue(), schedule(), scheduleEvery(), and addMcpServer(), and they get persisted in SQLite alongside the task.
await this.schedule(
Date.now() + 60_000,
"sendReport",
{ userId: "abc" },
{ retry: { maxAttempts: 5 } },
);
You can also set class-level retry defaults.
class MyAgent extends Agent {
static options = {
retry: { maxAttempts: 3 },
};
}
Retry options are validated immediately when a task is enqueued or scheduled, so misconfigurations surface early. Workflow operations also gained internal retries.
Protocol message control comes from implementing shouldSendProtocolMessages() per connection.
class MyAgent extends Agent {
shouldSendProtocolMessages(connection, ctx) {
const subprotocol = ctx.request.headers.get("Sec-WebSocket-Protocol");
return subprotocol !== "mqtt";
}
}
You can check the current state with isConnectionProtocolEnabled(), and the flag survives Durable Object hibernation.
On the @cloudflare/ai-chat side, the internals were rewritten around a new ResumableStream class and a WebSocket ChatTransport, with simplified SSE parsing. New capabilities include:
- Data parts: typed
data-*JSON attached to messages, supporting in-place updates keyed by type and ID, appends, and transient parts - Persisted tool approvals: pending tool approval state now survives page refreshes and DO hibernation
maxPersistedMessages: caps how many messages are kept in SQLite, auto-pruning the rest- A
bodyoption foruseAgentChatto attach common data to every request - Incremental persistence using hash-based caching to skip redundant SQL writes
- Row-size protection with two-stage compression against SQLite's 2 MB row limit
autoContinueAfterToolResultnow defaults totrue, so client-side tool results and approvals automatically trigger the server to continue
Bug fixes include a race condition in stream resumption, lost client-side tool schemas after DO hibernation, and an InvalidPromptError that used to happen after tool approval. Getters like getQueue() and getSchedule(), which only do synchronous SQL work, dropped their unnecessary async, and POST-based SSE now sends an event: ping keepalive every 30 seconds to stop proxies from dropping long-running tool calls.
Upgrading is just a package bump.
npm i agents@latest @cloudflare/ai-chat@latest
Wrap-up
this.retry()brings exponential backoff plus jitter retries into the SDK itselfqueue(),schedule(),scheduleEvery(), andaddMcpServer()accept retry options persisted in SQLite- Class-level
static optionslet you set default retry behavior once shouldSendProtocolMessages()gives per-connection control over protocol messages@cloudflare/ai-chatv0.1.0 was rewritten with zero breaking changes, adding data parts, persisted tool approvals, andmaxPersistedMessages
If you're building agents or chat UIs on Cloudflare Workers, this is a quietly solid upgrade for reliability and UX. Run npm i agents@latest on your next deploy and give it a spin.