Skip to content

Releases: cloudflare/agents

agents@0.11.9

29 Apr 01:54
2bf1497

Choose a tag to compare

Patch Changes

  • #1412 8fb7c03 Thanks @threepointone! - Make applyChunkToParts idempotent against an existing tool part with the same toolCallId, and add isReplayChunk(parts, chunk) for stream broadcasters that want to drop provider replay chunks (#1404).

    Some providers (notably the OpenAI Responses API) re-emit a prior tool call in continuation streams. The previous tool-input-start handler unconditionally pushed a fresh tool part, which produced duplicate parts in the message; tool-input-delta and tool-input-available overwrote a fully resolved input/state if a chunk happened to arrive for an already-known toolCallId. The new behavior:

    • tool-input-start for a toolCallId that already exists in parts is a no-op (it does not push a duplicate or regress state).
    • tool-input-delta only mutates input while the existing part is still input-streaming.
    • tool-input-available only advances from input-streaming to input-available; replays against parts that have already moved past input-streaming (including approval-requested/approval-responded and any terminal state) are no-ops.

    isReplayChunk(parts, chunk) is exported from agents/chat for stream broadcasters (e.g. AIChatAgent._streamSSEReply) that want to detect "this chunk is a replay of an already-known tool call" and skip re-broadcasting it. AI SDK v6's updateToolPart on the client mutates an existing tool part in place when the toolCallId matches, so re-broadcasting these replay chunks would visibly regress an output-available part to input-streaming on connected clients. tool-output-available is not treated as a replay because its in-place update is safe when the output already matches.

    Tool calls that the model genuinely wants to re-issue always carry a new toolCallId, so an existing match is never a legitimate "start over".

@cloudflare/ai-chat@0.5.4

29 Apr 01:54
2bf1497

Choose a tag to compare

Patch Changes

  • #1412 8fb7c03 Thanks @threepointone! - Stop provider tool-call replays from regressing tool part state during continuation streams (#1404).

    Some providers (notably the OpenAI Responses API) re-emit prior tool calls in continuation streams as a tool-input-starttool-input-deltatool-input-availabletool-output-available sequence carrying the same toolCallId and the same output the part already holds. The AI SDK's updateToolPart mutates an existing tool part in place when the toolCallId matches, so a replayed tool-input-start was clobbering an output-available part back to input-streaming on the client and producing the worker warn _applyToolResult: Tool part with toolCallId X not in expected state.

    Two fixes:

    • _streamSSEReply now drops replay tool-input chunks before broadcasting them to clients or storing them for resume, using the new shared isReplayChunk helper. The cloned server-side streaming message is never corrupted because applyChunkToParts is idempotent against existing toolCallIds for these chunk types (also fixed below).
    • _applyToolResult accepts output-available and output-error as valid starting states for idempotent re-application. A duplicate cf_agent_tool_result (cross-tab re-run, redelivered WS frame, provider replay round-trip) is now a silent no-op rather than a warn + skipped update. The cross-message tool-output-available/tool-output-error fallback in _streamSSEReply gets the same tolerance.

    _findAndUpdateToolPart skips the SQLite write and MESSAGE_UPDATED broadcast when the apply produced no semantic change, so idempotent re-applies don't churn UI on connected tabs.

hono-agents@3.0.11

28 Apr 22:56
cbf3e18

Choose a tag to compare

Patch Changes

  • ca510d4 Thanks @threepointone! - Tighten the agents peer dependency floor from >=0.9.0 to >=0.11.7 to reflect the current monorepo set we actually test against. Upper bound (<1.0.0) is unchanged. The corresponding agents devDependency is also bumped from ^0.11.0 to ^0.11.7 so dev and peer floors line up.

    No runtime change in hono-agents itself. The visible effect for consumers: pairing the latest hono-agents with a stale agents (<0.11.7) now produces a peer warning where it previously did not. That's the intended signal — agents versions older than 0.11.7 are no longer tested against this hono-agents.

agents@0.11.8

28 Apr 22:56
cbf3e18

Choose a tag to compare

Patch Changes

  • #1411 2fa68be Thanks @threepointone! - Add AbortRegistry.linkExternal(id, signal) for connecting external AbortSignals to per-request abort controllers, and add "aborted" to the SaveMessagesResult.status union (#1406).

    linkExternal is the integration point for callers that drive a chat turn programmatically and want to cancel it from outside without knowing the internally-generated request id (the helper-as-sub-agent pattern, where a parent's AbortSignal from the AI SDK tool execute needs to land inside a sub-agent's saveMessages call). When the external signal aborts, the registry's controller for id is cancelled — the same path chat-request-cancel takes over the WebSocket. The returned detacher must be called in finally to avoid leaking listeners on long-lived parent signals.

    SaveMessagesResult.status now includes "aborted" alongside "completed" and "skipped". Existing callers that only switch on "completed" are unaffected; turns cancelled via the new signal API surface as "aborted" rather than "completed".

    Also exposes SaveMessagesOptions from agents/chat for use by @cloudflare/think and @cloudflare/ai-chat typed APIs. AbortRegistry.cancel(id, reason?) now accepts an optional reason that flows through to signal.reason on the cancelled controller.

    See cloudflare/agents#1406 for the motivating use case.

  • ca510d4 Thanks @threepointone! - Tighten internal peer dependency floors to reflect the current monorepo set we actually test against: @cloudflare/ai-chat (>=0.0.8>=0.5.2) and @cloudflare/codemode (>=0.0.7>=0.3.4). Upper bound (<1.0.0) is unchanged.

    No runtime change in agents itself. The visible effect for consumers: pairing the latest agents with a stale @cloudflare/ai-chat (<0.5.2) or @cloudflare/codemode (<0.3.4) now produces a peer warning where it previously did not. That's the intended signal — those older combinations are no longer tested in the monorepo.

agents@0.11.7

28 Apr 19:48
2aef4d8

Choose a tag to compare

Patch Changes

  • #1405 03620a6 Thanks @threepointone! - Bump partyserver peer dependency to ^0.5.4. 0.5.4 closes cloudflare/partykit#390: fresh 0.5.x DOs with compatibility_date older than 2026-03-15 could lose this.name on alarm wake (no ctx.id.name propagation in older runtimes, and 0.5.x had stopped writing the __ps_name legacy fallback record). The fix is a defensive one-time __ps_name write on first fetch — idempotent, restores the safety net pre-0.5.x had. Affects any project on a pre-cutoff compatibility_date whose DOs schedule alarms (which includes Think's _chatRecoveryContinue).

@cloudflare/worker-bundler@0.1.3

28 Apr 22:56
cbf3e18

Choose a tag to compare

Patch Changes

  • 19a4c08 Thanks @threepointone! - Bump es-module-lexer from ^2.0.0 to ^2.1.0. Caret upper bound (<3.0.0) is unchanged.

    No API or runtime behavior change in @cloudflare/worker-bundler itself.

@cloudflare/voice@0.1.3

28 Apr 22:56
cbf3e18

Choose a tag to compare

Patch Changes

  • ca510d4 Thanks @threepointone! - Tighten the agents peer dependency floor from >=0.9.0 to >=0.11.7 to reflect the current monorepo set we actually test against. Upper bound (<1.0.0) is unchanged.

    No runtime change in @cloudflare/voice itself. The visible effect for consumers: pairing the latest @cloudflare/voice with a stale agents (<0.11.7) now produces a peer warning where it previously did not. That's the intended signal — agents versions older than 0.11.7 are no longer tested against this @cloudflare/voice.

@cloudflare/think@0.4.2

28 Apr 22:56
cbf3e18

Choose a tag to compare

Patch Changes

  • ca510d4 Thanks @threepointone! - Tighten internal peer dependency floors to reflect the current monorepo set we actually test against: agents (>=0.8.7>=0.11.7), @cloudflare/codemode (>=0.0.7>=0.3.4), and @cloudflare/shell (>=0.2.0>=0.3.4). Upper bounds (<1.0.0) are unchanged.

    No runtime change in @cloudflare/think itself. The visible effect for consumers: pairing the latest @cloudflare/think with a stale agents (<0.11.7), @cloudflare/codemode (<0.3.4), or @cloudflare/shell (<0.3.4) now produces a peer warning where it previously did not. That's the intended signal — those older combinations are no longer tested in the monorepo.

  • #1411 2fa68be Thanks @threepointone! - Add options.signal to Think.saveMessages and Think.continueLastTurn for external cancellation of programmatic turns, plus protected abortRequest(id) / abortAllRequests() methods to replace bracket access into the private _aborts registry (#1406).

    saveMessages and continueLastTurn accept a second SaveMessagesOptions argument:

    const result = await this.saveMessages(messages, {
      signal: controller.signal,
    });
    if (result.status === "aborted") {
      // Inference loop terminated mid-stream; partial chunks persisted.
    }

    The signal is linked to Think's per-turn AbortController for the duration of the call. When it aborts:

    • the inference loop's signal aborts (the same path chat-request-cancel takes);
    • partial chunks already streamed are persisted to the resumable stream;
    • saveMessages resolves with { status: "aborted" };
    • onChatResponse fires with status: "aborted".

    Pre-aborted signals short-circuit before any model work runs. Listeners are detached cleanly when the turn finishes, so passing the same long-lived AbortSignal to many turns (e.g. a parent chat-turn signal driving multiple sub-agent calls) is safe and leak-free.

    abortRequest(id, reason?) and abortAllRequests() are protected entry points for DO subclasses (e.g. RPC-driven helpers) that want to cancel turns without tracking ids — they replace the historical (this as unknown as { _aborts: ... })._aborts.destroyAll() workaround used by helper-as-sub-agent implementations.

    SaveMessagesResult.status now includes "aborted" alongside "completed" and "skipped". Existing callers that only switch on "completed" are unaffected.

    Limitations.

    • AbortSignal cannot cross Durable Object RPC. Construct the controller inside the DO that calls saveMessages. To bridge a parent's intent into a child DO, return a ReadableStream from the child whose cancel callback aborts a per-turn controller — examples/agents-as-tools shows the canonical pattern.
    • The signal lives in memory only. If the DO hibernates mid-turn and chatRecovery is enabled, the recovered turn calls continueLastTurn() internally without the original signal — an abort fired after restart has no effect on the recovered turn.

    See cloudflare/agents#1406 for the motivating use case.

@cloudflare/shell@0.3.5

28 Apr 22:56
cbf3e18

Choose a tag to compare

Patch Changes

  • 19a4c08 Thanks @threepointone! - Bump dependencies: isomorphic-git from ^1.37.5 to ^1.37.6 (runtime) and @cloudflare/vitest-pool-workers from ^0.15.0 to ^0.15.1 (devDependency, test-only — does not affect the published artifact).

    No API or runtime behavior change in @cloudflare/shell itself.

@cloudflare/ai-chat@0.5.3

28 Apr 22:56
cbf3e18

Choose a tag to compare

Patch Changes

  • ca510d4 Thanks @threepointone! - Tighten the agents peer dependency floor from >=0.8.7 to >=0.11.7 to reflect the current monorepo set we actually test against. Upper bound (<1.0.0) is unchanged.

    No runtime change in @cloudflare/ai-chat itself. The visible effect for consumers: pairing the latest @cloudflare/ai-chat with a stale agents (<0.11.7) now produces a peer warning where it previously did not. That's the intended signal — agents versions older than 0.11.7 are no longer tested against this @cloudflare/ai-chat.

  • #1411 2fa68be Thanks @threepointone! - Add options.signal to AIChatAgent.saveMessages and continueLastTurn for external cancellation of programmatic turns, plus protected abortRequest(id) / abortAllRequests() methods (#1406).

    saveMessages and continueLastTurn accept a second SaveMessagesOptions argument:

    const result = await this.saveMessages(messages, {
      signal: controller.signal,
    });
    if (result.status === "aborted") {
      // Inference loop terminated mid-stream; partial chunks persisted.
    }

    The signal is linked to AIChatAgent's per-turn AbortController and produces the same end state as a chat-request-cancel WebSocket message: the inference loop's signal aborts, partial chunks persist, the result reports status: "aborted", and onChatResponse fires with the same status. Pre-aborted signals short-circuit before any model work runs. Listeners are detached cleanly when the turn finishes, so the same long-lived signal can be passed to many turns without leaking.

    abortRequest(id, reason?) and abortAllRequests() are protected entry points for subclasses that want to cancel turns without tracking ids.

    SaveMessagesResult.status now includes "aborted" alongside "completed" and "skipped". Existing callers that only switch on "completed" are unaffected.

    Limitations.

    • AbortSignal cannot cross Durable Object RPC. Construct the controller inside the DO that calls saveMessages.
    • The signal lives in memory only. If the DO hibernates mid-turn and chatRecovery is enabled, the recovered turn runs without the original signal.

    See cloudflare/agents#1406 for the motivating use case.