github cloudflare/agents @cloudflare/think@0.2.5

Patch Changes

  • #1330 b4d3fcf Thanks @threepointone! - Fix subAgent() cross-DO I/O errors on first use and drop the "experimental" compatibility flag requirement.

    subAgent() cross-DO I/O fix

    Three issues in the facet initialization path caused "Cannot perform I/O on behalf of a different Durable Object" errors when spawning sub-agents in production:

    • subAgent() constructed a Request in the parent DO and passed it to the child via stub.fetch(). The Request carried native I/O tied to the parent isolate, which the child rejected.
    • The facet flag was set after the first onStart() ran, so broadcastMcpServers() fired with _isFacet === false on the initial boot.
    • _broadcastProtocol(), the inherited broadcast(), and _workflow_broadcast() iterated the connection registry without an _isFacet guard, letting broadcasts reach into the parent DO's WebSocket registry from a child isolate.

    Replaces the fetch-based handshake with a new _cf_initAsFacet(name) RPC that runs entirely in the child isolate, sets _isFacet before init, and seeds partyserver's __ps_name key directly. Adds _isFacet guards to _broadcastProtocol() and overrides broadcast() to no-op on facets so downstream callers (chat-streaming paths, workflow broadcasts, user this.broadcast(...)) are covered. Removes the previous internal _cf_markAsFacet() method — _cf_initAsFacet(name) is the correct entry point (it sets the flag before running the first onStart(), which _cf_markAsFacet did not).

    "experimental" compatibility flag no longer required

    ctx.facets, ctx.exports, and env.LOADER (Worker Loader) have graduated out of the "experimental" compatibility flag in workerd. agents and @cloudflare/think no longer require it:

    • subAgent() / abortSubAgent() / deleteSubAgent() — the @experimental JSDoc tag and runtime error messages no longer reference the flag. The runtime guards on ctx.facets / ctx.exports stay in place and now nudge users toward updating compatibility_date instead.
    • Think — the @experimental JSDoc tag no longer references the flag.

    No code change is required; remove "experimental" from your compatibility_flags in wrangler.jsonc if it was only there for these features.

  • #1332 7cb8acf Thanks @threepointone! - Expose createdAt on fiber and chat recovery contexts so apps can suppress continuations for stale, interrupted turns.

    • FiberRecoveryContext (from agents) gains createdAt: number — epoch milliseconds when runFiber started, read from the cf_agents_runs row that was already tracked internally.
    • ChatRecoveryContext (from @cloudflare/ai-chat and @cloudflare/think) gains the same createdAt field, threaded through from the underlying fiber.

    With this, the stale-recovery guard pattern described in #1324 is a short override:

    override async onChatRecovery(ctx: ChatRecoveryContext): Promise<ChatRecoveryOptions> {
      if (Date.now() - ctx.createdAt > 2 * 60 * 1000) return { continue: false };
      return {};
    }

    No behavior change for existing callers. See docs/chat-agents.md (new "Guarding against stale recoveries" section) for the full recipe, including a loop-protection pattern using onChatResponse.

Don't miss a new agents release

NewReleases is sending notifications on new releases.