This release adds per-connection protocol message control and a built-in retry system. Agents can now suppress JSON protocol frames for binary-only clients (MQTT, IoT devices) while keeping RPC and regular messaging working — useful for Durable Objects that serve mixed connection types. The new this.retry() method and per-task retry options bring exponential backoff with jitter to scheduling, queues, and MCP connections without external dependencies. This release also improves scheduling ergonomics with synchronous getter methods, a cleaner discriminated union schema, and fixes for hibernation, deep type recursion, and SSE keepalives.
Minor Changes
-
#920
4dea3bdThanks @threepointone! - AddshouldSendProtocolMessageshook andisConnectionProtocolEnabledpredicate for per-connection control of protocol text framesAdds the ability to suppress protocol messages (
CF_AGENT_IDENTITY,CF_AGENT_STATE,CF_AGENT_MCP_SERVERS) on a per-connection basis. This is useful for binary-only clients (e.g. MQTT devices) that cannot handle JSON text frames.Override
shouldSendProtocolMessages(connection, ctx)to returnfalsefor connections that should not receive protocol messages. These connections still fully participate in RPC and regular messaging — only the automatic protocol text frames are suppressed, both on connect and during broadcasts.Use
isConnectionProtocolEnabled(connection)to check a connection's protocol status at any time.Also fixes
isConnectionReadonlyto correctly survive Durable Object hibernation by re-wrapping the connection when the in-memory accessor cache has been cleared. -
#874
a6ec9b0Thanks @threepointone! - Add retry utilities:this.retry(), per-task retry options, andRetryOptionstypethis.retry(fn, options?)— retry any async operation with exponential backoff and jitter. Accepts optionalshouldRetrypredicate to bail early on non-retryable errors.queue(),schedule(),scheduleEvery()accept{ retry?: RetryOptions }for per-task retry configuration, persisted in SQLite alongside the task.addMcpServer()accepts{ retry?: RetryOptions }for configurable MCP connection retries.RetryOptionstype is exported for TypeScript consumers.- Retry options are validated eagerly at enqueue/schedule time — invalid values throw immediately.
- Class-level retry defaults via
static options = { retry: { ... } }— override defaults for an entire agent class. - Internal retries added for workflow operations (
terminateWorkflow,pauseWorkflow, etc.) with Durable Object-aware error detection.
Patch Changes
-
#899
04c6411Thanks @threepointone! - Fix React hooks exhaustive-deps warning in useAgent by referencing cacheInvalidatedAt inside useMemo body. -
#904
d611b94Thanks @ask-bonk! - Fix TypeScript "excessively deep" error with deeply nested state typesAdd a depth counter to
CanSerializeandIsSerializableParamtypes that bails out totrueafter 10 levels of recursion. This prevents the "Type instantiation is excessively deep and possibly infinite" error when using deeply nested types like AI SDKCoreMessage[]as agent state. -
#911
67b1601Thanks @threepointone! - Update all dependencies and fix breaking changes.Update all dependencies, add required
aria-labelprops to KumoButtoncomponents withshape(now required for accessibility), and fix state test for constructor-time validation of conflictingonStateChanged/onStateUpdatehooks. -
#889
9100e65Thanks @deathbyknowledge! - Fix scheduling schema compatibility with zod v3 and improve schema structure.- Change
zod/v3import tozodso the package works for users on zod v3 (who don't have thezod/v3subpath). - Replace flat object with optional fields with a
z.discriminatedUniononwhen.type. Each scheduling variant now only contains the fields it needs, making the schema cleaner and easier for LLMs to follow. - Replace
z.coerce.date()withz.string(). Zod v4'stoJSONSchema()cannot representDate, and the AI SDK routes zod v4 schemas through it directly. Dates are now returned as ISO 8601 strings. - Type change:
Schedule["when"]is now a discriminated union instead of a flat object with optional fields.when.dateisstringinstead ofDate.
- Change
-
#916
24e16e0Thanks @threepointone! - Widen peer dependency ranges across packages to prevent cascading major bumps during 0.x minor releases. Mark@cloudflare/ai-chatand@cloudflare/codemodeas optional peer dependencies ofagentsto fix unmet peer dependency warnings during installation. -
#898
cd2d34fThanks @jvg123! - Add keepalive ping to POST SSE response streams in WorkerTransportThe GET SSE handler already sends
event: pingevery 30 seconds to keep the connection alive, but the POST SSE handler did not. This caused POST response streams to be silently dropped by proxies and infrastructure during long-running tool calls (e.g., MCP tools/call), resulting in clients never receiving the response. -
#874
a6ec9b0Thanks @threepointone! - Make queue and schedule getter methods synchronousgetQueue(),getQueues(),getSchedule(),dequeue(),dequeueAll(), anddequeueAllByCallback()were unnecessarilyasyncdespite only performing synchronous SQL operations. They now return values directly instead of wrapping them in Promises. This is backward compatible — existing code usingawaiton these methods will continue to work.