NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #2684 most downloaded on npm
AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.
Last release 3 days ago
01 Oct 2026
Ships on a steady schedule
a new release about every 8 days
Some releases are documented
notes for 26 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
13 years old
1568 releases · first in 2014
6ec57f5: feat(ai): make the experimental lifecycle callbacks stable
@ai-sdk/gateway@4.0.0-canary.106
One column per quarter.
@ai-sdk/gateway@4.0.0-canary.105
25a64f8: Remove deprecated experimental generateImage exports.
25a64f8: Remove deprecated experimental generateImage exports.
375fdd7: fix: harden download URL SSRF guard against hostname and redirect bypasses
validateDownloadUrl and the file download helpers (downloadBlob, download) could be bypassed in several ways when handling untrusted URLs:
localhost., myhost.local.) skipped the localhost/.local blocklist.::127.0.0.1), IPv4-translated (::ffff:0:127.0.0.1), and NAT64 (64:ff9b::127.0.0.1, including the 64:ff9b:1::/48 local-use prefix) — were not decoded and checked against the private IPv4 ranges.fetch had already followed them, so the request to a redirect target (e.g. an internal/metadata address) had already been issued before the check ran.100.64.0.0/10, used by some cloud providers for internal traffic), benchmarking (198.18.0.0/15), IETF protocol assignments (192.0.0.0/24), the reserved 240.0.0.0/4 block (including the 255.255.255.255 broadcast address), and IPv6 site-local (fec0::/10) and multicast (ff00::/8).The validator now strips trailing dots before the hostname checks and fully expands IPv6 addresses to detect embedded private IPv4 targets. The download helpers now follow redirects manually (redirect: 'manual'), re-validating each hop before requesting it, so an unsafe redirect target is never fetched. When a redirect cannot be inspected because the runtime returns an opaque response, the helpers fail closed (reject the redirect) on the server; only in a real browser — where SSRF is not reachable (fetch is constrained by CORS and cannot reach a server's internal network or cloud-metadata endpoints) — is the redirect followed natively so legitimate redirected downloads keep working.
f18b08f: fix: redact server error details from UI message streams by default
toUIMessageStream, createUIMessageStream, and toUIMessageChunk defaulted their onError callback to getErrorMessage, which serializes the raw error (error.toString() / JSON.stringify(error)) into the client-facing { type: 'error', errorText } chunk — and also into tool-output-error parts. The documented default was () => 'An error occurred.', so applications relying on the documented behavior were unknowingly streaming server exception details (internal hostnames, paths, provider request data, validation inputs) to end users.
The default onError now returns the documented generic 'An error occurred.'. Raw error details are only emitted when the developer explicitly supplies an onError handler. This also redacts tool-output-error and invalid-tool-input error text by default; pass an onError to surface richer messages.
b4507d5: fix(provider-utils): cancel response body on download rejection to prevent socket leak
When a download was rejected early — because the Content-Length header exceeded the size limit, the response status was not ok, or a redirect resolved to a blocked URL — the fetch response body was left unconsumed and uncancelled. With WHATWG Fetch/undici this leaves the underlying TCP socket open instead of returning it to the connection pool, allowing an attacker-controlled origin to exhaust file descriptors and cause a denial of service. The body is now cancelled on all early-rejection paths in readResponseWithSizeLimit, download, and downloadBlob, and fetchWithValidatedRedirects cancels each redirect hop's body before following or rejecting the next hop.
Updated dependencies [8c17bf8]
Updated dependencies [aeda373]
Updated dependencies [558777f]
Updated dependencies [375fdd7]
Updated dependencies [b4507d5]
f9a496f: Promote transcribe and TranscriptionResult to stable exports, with deprecated experimental aliases for backwards compatibility.
generateSpeech and SpeechResult to stable exports.transcribe and TranscriptionResult to stable exports, with deprecated experimental aliases for backwards compatibility.bae5e2b: fix(security): re-validate tool approvals from client message history before execution
bae5e2b: fix(security): re-validate tool approvals from client message history before execution
The approval-replay path in generateText/streamText (and WorkflowAgent.stream) reconstructed approved tool calls from the client-supplied messages array and executed them without re-validating input against the tool's schema or re-applying the approval policy. A client could forge an assistant message with a pre-approved tool-call part and have the server execute a tool with attacker-chosen arguments.
The replay path now validates HMAC signature (when experimental_toolApprovalSecret is configured), re-validates tool-call input against the tool's input schema, and re-resolves the approval policy before execution.
69d7128: fix(workflow): reuse the core tool-approval validation in WorkflowAgent
WorkflowAgent.stream previously reconstructed approved tool calls with a copy of the core collection logic and validated them inline. Because the logic was duplicated, it could drift from the hardened generateText/streamText implementation. WorkflowAgent now collects approvals via the shared collectToolApprovals and re-validates each one through the shared validateApprovedToolApprovals (input-schema re-validation, HMAC signature verification when configured, and approval-policy re-resolution) in addition to its existing needsApproval guard, so a client-forged approval cannot execute a tool with unvalidated input. The duplicated collector was removed; collectToolApprovals and validateApprovedToolApprovals are now exported from ai/internal.
Updated dependencies [bae5e2b]
a5018ab: fix(ai): return schema-transformed elements in array output mode
a5018ab: fix(ai): return schema-transformed elements in array output mode
Previously final array output validation checked each element against the schema but returned the raw model output. Array output now returns the validated values so Zod transforms, coercions, defaults, and pipes are applied consistently with object output.
21d3d60: feat(harness): implement harness specification
426dbbb: fix(ai): reject streamText result promises with NoOutputGeneratedError when the model stream ends without producing any output. Previously such streams resolved with an empty step. Incomplete streams with partial output still resolve with the partial result.
7fd3360: Harden UI message stream processing against prototype pollution from chunk IDs.
1e4b350: Honor tool.toModelOutput in WorkflowAgent.
1e4b350: Honor tool.toModelOutput in WorkflowAgent.
WorkflowAgent now routes successful local, provider-executed, and approved tool results through each tool's optional toModelOutput hook, matching generateText, streamText, and ToolLoopAgent. Previously the hook was ignored and results were always serialized as text or json.
Internally exports the shared tool-result model-output helpers from ai/internal, and uses the shared getErrorMessage behavior for workflow tool error results.
Updated dependencies [a3bb04a]
4757690: feat(ai): rename onObjectStepFinish to onObjectStepEnd
4757690: feat(ai): rename onObjectStepFinish to onObjectStepEnd
eeefc3f: fix(ai): enforce timeout.stepMs for the whole step in streamText
Previously streamText's step timer was cleared synchronously right after the step's stream was registered, before the stream produced anything, so stepMs never aborted a step that stalled before emitting content. The step timer now survives until the step's stream finishes or aborts, matching generateText. chunkMs/totalMs and normal step-finish cleanup are unchanged.
b79b6a8: fix(ai): add approval guard for denied tool outputs
Updated dependencies [6b4d325]
19736ee: feat(ai): rename onStepFinish to onStepEnd
ce769dd: feat(provider): add experimental Realtime API support for voice conversations
ce769dd: feat(provider): add experimental Realtime API support for voice conversations
Adds first-class support for realtime (speech-to-speech) APIs:
Experimental_RealtimeModelV4 spec in @ai-sdk/provider with normalized event types and factoryopenai.experimental_realtime() / google.experimental_realtime() / xai.experimental_realtime() work in both server and browser.getToken() static method on each provider for server-side ephemeral token creationexperimental_getRealtimeToolDefinitions helper for provider session tool definitionsexperimental_useRealtime hook in @ai-sdk/react returning UIMessage[] (aligned with useChat), with onToolCall and addToolOutput for client-driven tool executioninputAudioTranscription session config for showing transcribed user audio messages when supported by the providerUpdated dependencies [ce769dd]
@ai-sdk/gateway@4.0.0-canary.98
ee798eb: chore(provider-utils): rename Experimental_Sandbox to Experimental_SandboxSession
Experimental_Sandbox to Experimental_SandboxSessiontoolOrder option to control the order in which tools are sent to provider APIs.@ai-sdk/gateway@4.0.0-canary.96
@ai-sdk/gateway@4.0.0-canary.95
@ai-sdk/gateway@4.0.0-canary.94
b5092f5: fix(ai): do not re-validate tool input for output-error parts in validateUIMessages
bcce2dd: feat(stream-text): expose standalone stream transformation helpers and deprecate the equivalent streamText result methods.
bcce2dd: feat(stream-text): expose standalone stream transformation helpers and deprecate the equivalent streamText result methods.
The new toUIMessageChunk and toUIMessageStream helpers let you convert a streamText stream (or any compatible ReadableStream<TextStreamPart<TOOLS>>) into UI message chunks without going through the result object — useful for custom transports, tests, and other producers of TextStreamPart.
result.toUIMessageStreamResponse(options) and result.pipeUIMessageStreamToResponse(response, options) can migrate by passing toUIMessageStream({ stream: result.stream, ...options }) to createUIMessageStreamResponse or pipeUIMessageStreamToResponse.
The new toTextStream helper extracts text deltas from a streamText stream, so result.toTextStreamResponse(options) and result.pipeTextStreamToResponse(response, options) can migrate to createTextStreamResponse({ stream: toTextStream({ stream: result.stream }), ...options }) and pipeTextStreamToResponse({ response, stream: toTextStream({ stream: result.stream }), ...options }).
result.toUIMessageStream, result.toUIMessageStreamResponse, result.pipeUIMessageStreamToResponse, result.toTextStreamResponse, and result.pipeTextStreamToResponse are now @deprecated. They still work in v7 and will be removed in the next major release. Migration snippets are in the v6 → v7 migration guide.
@ai-sdk/gateway@4.0.0-canary.93
023550e: Deprecate streamText result fullStream in favor of stream.
streamText result fullStream in favor of stream.e67d80e: fix: rename onFinish to onEnd
onChunk594029e: feat(ai): wrap the model call in telemetry context
6c93e36: feat(provider-utils): add spawnCommand method to Experimental_Sandbox to allow for detached command execution
spawnCommand method to Experimental_Sandbox to allow for detached command execution@ai-sdk/gateway@4.0.0-canary.91
@ai-sdk/gateway@4.0.0-canary.90
@ai-sdk/gateway@4.0.0-canary.89
e3d9c0e: Add allowSystemInMessages option to ToolLoopAgent.
e3d9c0e: Add allowSystemInMessages option to ToolLoopAgent.
This exposes the same option that exists on streamText and generateText, whether role: "system" messages are allowed in the prompt or messages fields. When unset, system messages are rejected because they can create a prompt injection attack risk. Ideally, use the instructions option instead. Set to true to allow system messages, or false to explicitly reject them.
const agent = new ToolLoopAgent({
model,
allowSystemInMessages: true,
});
await agent.generate({
messages: [
{ role: "system", content: "Server context" },
{ role: "user", content: "Hello" },
],
});
The option can also be returned from prepareCall for dynamic per-call configuration.
@ai-sdk/gateway@4.0.0-canary.88
@ai-sdk/gateway@4.0.0-canary.87
@ai-sdk/gateway@4.0.0-canary.86
7fc6bd6: Raise minimum supported Node.js version to 22. Supported versions: 22, 24, and 26.
62d6481: Post-publish release notifications now link to each package’s GitHub release and npm page.
e3a0419: fix(ai): default missing embedding warnings to an empty array
@ai-sdk/gateway@4.0.0-canary.83
334ae5d: Update step performance metrics with explicit effective, input, output, and total token throughput fields.
@ai-sdk/gateway@4.0.0-canary.81
98627e5: feat(ai): remove onChunk event from telemetry
a7de9c9: fix: make sandbox experimental
@ai-sdk/provider-utils@5.0.0-canary.39
ed74dae: fix(ui): make input optional on output-error tool and dynamic-tool UI message parts
ed74dae: fix(ui): make input optional on output-error tool and dynamic-tool UI message parts
validateUIMessages rejected persisted assistant messages whose output-error tool parts had no input key. This happened for any errored tool call where the SDK set input: undefined (e.g. NoSuchToolError / InvalidToolInputError): JSON serialization stripped the undefined value, and Zod 4.4+ treats a missing z.unknown() key as a validation failure (previously it was implicitly optional). The schema now matches the runtime shape produced by process-ui-message-stream, so reloading a thread that contains an errored tool call no longer throws AI_TypeValidationError.
f4cc8eb: feat: add performance statistics
e80ada0: fix(ai): download tool-result file URLs
1dca341: fix: rename telemetry onFinish to onEnd
2605e5f: fix test mocks to return the first array-backed result on the first call
38ca8dc: fix(gateway): enable retry support for gateway errors
eaf849f: Rename rerank telemetry finish callback to onRerankEnd.
onRerankEnd.b67525f: feat: instructions as prepareStep input
@ai-sdk/gateway@4.0.0-canary.76
@ai-sdk/provider-utils@5.0.0-canary.37
e95e38d: fix: Make generateText and streamText result usage report total usage across all steps and deprecate totalUsage.
generateText and streamText result usage report total usage across all steps and deprecate totalUsage.instructions as the primary prompt option and deprecate systemfinalStep on text generation results@ai-sdk/provider-utils@5.0.0-canary.35
c0c8ca2: fix(ai): remove deprecated LanguageModelUsage properties
69aeb0e: feat: add deprecated tool call lifecycle callback aliases for AI SDK 6 compatibility.
7392266: feat: move includeRawChunks to include.rawChunks
79b2468: feat: add request.messages to StepResult
2427d88: feat(ai): change Tool.sensitiveContext to telemetry.includeToolsContext and make it opt-in
5463d0d: feat(provider): align tool result output content file part types with top-level message file part types
@ai-sdk/gateway@4.0.0-canary.69
47e65d6: fix(ai): tag step/chunk timeout aborts with TimeoutError reason
47e65d6: fix(ai): tag step/chunk timeout aborts with TimeoutError reason
When timeout: { stepMs } or timeout: { chunkMs } fires, the abort reason is now a TimeoutError DOMException, matching what AbortSignal.timeout() produces natively. Consumers can distinguish a framework timeout from a user-initiated cancel via signal.reason.name === 'TimeoutError'.
0c4c275: trigger initial canary release
Nothing published for this version
### Patch Changes - Updated dependencies [77cc1af] - @ai-sdk/gateway@4.0.0-beta.114
### Patch Changes - Updated dependencies [eb024b6] - @ai-sdk/gateway@4.0.0-beta.113
75763b0: agents: tag outgoing requests with an ai-sdk-agent user-agent segment for usage attribution (tool-loop, workflow)
Your coding agent can read these notes before it upgrades. Set up the MCP server →