Migrate AI SDK 6.x to 7.0

Use the command below to add the migration skill:

npx skills add vercel/ai --skill migrate-ai-sdk-v6-to-v7

Then ask your agent:

Use the migrate-ai-sdk-v6-to-v7 skill and migrate my app from AI SDK v6 to v7.
  1. Backup your project. If you use a versioning control system, make sure all previous versions are committed.
  2. Upgrade to AI SDK 7.0.
  3. Follow the breaking changes guide below.
  4. Verify your project is working as expected.
  5. Commit your changes.

An example upgrade command would be:

pnpm install ai @ai-sdk/react @ai-sdk/openai @ai-sdk/otel

Codemods

The AI SDK provides Codemod transformations to help upgrade your codebase when a feature is deprecated, removed, or otherwise changed.

Codemods are transformations that run on your codebase automatically. They allow you to easily apply many changes without having to manually go through every file.

You can run all v7 codemods (v6 -> v7 migration) by running the following command from the root of your project:

npx @ai-sdk/codemod v7

Individual codemods can be run by specifying the name of the codemod:

npx @ai-sdk/codemod <codemod-name> <path>

For example, to run a specific v7 codemod:

npx @ai-sdk/codemod v7/rename-system-to-instructions src/

Codemods are intended as a tool to help you with the upgrade process. They may not cover all of the changes you need to make. You may need to make additional changes manually.

Codemod Table

Codemod NameDescription
remove-experimental-custom-providerReplaces experimental_customProvider with customProvider
remove-experimental-generate-imageReplaces experimental_generateImage and Experimental_GenerateImageResult with stable names
replace-experimental-output-with-outputReplaces experimental_output options and result access with output
remove-experimental-prepare-stepReplaces experimental_prepareStep with prepareStep
replace-cached-input-tokensReplaces usage.cachedInputTokens with usage.inputTokenDetails.cacheReadTokens
replace-reasoning-tokensReplaces usage.reasoningTokens with usage.outputTokenDetails.reasoningTokens
remove-experimental-active-toolsReplaces experimental_activeTools with activeTools
remove-tool-call-options-typeReplaces the removed ToolCallOptions type with ToolExecutionOptions
remove-is-tool-or-dynamic-tool-uipartReplaces isToolOrDynamicToolUIPart with isToolUIPart
remove-media-content-part-typeReplaces tool result content parts with type: 'media' with type: 'file-data'
replace-anthropic-cache-creation-input-tokensReplaces Anthropic cacheCreationInputTokens metadata access with standard usage fields
rename-experimental-transcribeRenames experimental_transcribe and Experimental_TranscriptionResult to stable names
rename-experimental-generate-speechRenames experimental_generateSpeech and Experimental_SpeechResult to stable names
rename-call-settings-typeReplaces CallSettings with LanguageModelCallOptions & Omit<RequestOptions, 'timeout'>
rename-step-count-isRenames stepCountIs to isStepCount
rename-system-to-instructionsRenames system prompt options, lifecycle fields, and repair-tool-call fields to instructions
rename-experimental-on-start-to-on-startRenames experimental_onStart to onStart
rename-experimental-on-step-start-to-on-step-startRenames experimental_onStepStart to onStepStart
rename-on-finish-to-on-endRenames onFinish callbacks to onEnd
rename-on-step-finish-to-on-step-endRenames onStepFinish callbacks to onStepEnd
rename-experimental-on-finish-to-on-endRenames experimental_onFinish callbacks to onEnd
rename-experimental-telemetry-to-telemetryRenames experimental_telemetry options to telemetry
rename-on-rerank-finish-to-on-rerank-endRenames telemetry onRerankFinish callbacks to onRerankEnd
rename-on-embed-finish-to-on-embed-endRenames telemetry onEmbedFinish callbacks to onEmbedEnd
rename-full-stream-to-streamRenames streamText result fullStream access to stream
move-include-raw-chunks-to-includeMoves includeRawChunks into include.rawChunks
rename-experimental-include-to-includeRenames experimental_include to include
rename-experimental-on-tool-call-start-to-on-tool-execution-startRenames experimental_onToolCallStart to onToolExecutionStart
rename-experimental-on-tool-call-finish-to-on-tool-execution-endRenames experimental_onToolCallFinish to onToolExecutionEnd
rename-experimental-context-to-contextRenames tool callback experimental_context access to context
rename-google-generative-ai-to-googleRenames Google provider types, classes, and functions that include GoogleGenerativeAI to Google
replace-image-message-part-with-fileReplaces image message parts with file parts using mediaType: 'image'

All Packages

Minimum Node.js Version

AI SDK 7.0 requires Node.js 22 or later. The SDK is tested on Node.js 22, 24, and 26.

Node.js 18 and 20 are no longer supported. Node.js 22 reached end-of-maintenance on April 30, 2026; for production workloads, prefer Node.js 24 (LTS) or Node.js 26. See the Node.js release schedule for current status and support timelines.

Update the engines field in your package.json if you enforce a minimum Node.js version:

package.json
{
"engines": {
"node": ">=22"
}
}

ESM Only — CommonJS Support Removed

All AI SDK packages are now ESM-only. The require() function is no longer supported.

If your project uses CommonJS (require()), switch to ESM import syntax:

Before (CommonJS)
const { generateText } = require('ai');
const { openai } = require('@ai-sdk/openai');
After (ESM)
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';

If your package.json does not already include "type": "module", add it or rename your files to use the .mjs extension.

AI SDK Core

Core API Renames and Removals

Provider Management: Remove Deprecated experimental_customProvider

The deprecated experimental_customProvider export has been removed in AI SDK 7. Replace it with customProvider.

AI SDK 6
import { experimental_customProvider } from 'ai';
export const myProvider = experimental_customProvider({
languageModels: {
// ...
},
});
AI SDK 7
import { customProvider } from 'ai';
export const myProvider = customProvider({
languageModels: {
// ...
},
});

This is only an import and symbol rename. The customProvider options and behavior are unchanged.

Remove Deprecated experimental_generateImage Export

The deprecated experimental_generateImage export has been removed in AI SDK 7. Replace it with generateImage.

The deprecated Experimental_GenerateImageResult type export has also been removed. Replace it with GenerateImageResult.

AI SDK 6
import {
experimental_generateImage,
type Experimental_GenerateImageResult,
} from 'ai';
const result: Experimental_GenerateImageResult =
await experimental_generateImage({
model: yourImageModel,
prompt: 'A red panda eating bamboo',
});
AI SDK 7
import { generateImage, type GenerateImageResult } from 'ai';
const result: GenerateImageResult = await generateImage({
model: yourImageModel,
prompt: 'A red panda eating bamboo',
});

experimental_transcribe Renamed to transcribe

The transcription API has graduated out of experimental status and has been renamed to transcribe. The Experimental_TranscriptionResult type has also been renamed to TranscriptionResult.

AI SDK 6
import {
experimental_transcribe as transcribe,
type Experimental_TranscriptionResult,
} from 'ai';
const result: Experimental_TranscriptionResult = await transcribe({
model: yourTranscriptionModel,
audio,
});
AI SDK 7
import { transcribe, type TranscriptionResult } from 'ai';
const result: TranscriptionResult = await transcribe({
model: yourTranscriptionModel,
audio,
});

The old names continue to work as deprecated aliases in AI SDK 7 and will be removed in a future major release.

experimental_generateSpeech Renamed to generateSpeech

The speech generation function has graduated out of experimental status and has been renamed to generateSpeech. The Experimental_SpeechResult type has also been renamed to SpeechResult.

AI SDK 6
import { experimental_generateSpeech as generateSpeech } from 'ai';
const result = await generateSpeech({
model: yourSpeechModel,
text: 'Hello',
});
AI SDK 7
import { generateSpeech } from 'ai';
const result = await generateSpeech({
model: yourSpeechModel,
text: 'Hello',
});

The old experimental_generateSpeech and Experimental_SpeechResult exports continue to work as deprecated aliases in AI SDK 7 and will be removed in a future major release.

Structured Outputs: Remove Deprecated experimental_output Option and Result

The deprecated experimental_output option has been removed in AI SDK 7. Replace all remaining usages with output.

The deprecated generateText() result property experimental_output has also been removed. Read result.output instead.

This name was deprecated in AI SDK 6, so if you already migrated to output, no changes are needed. Otherwise, update both the call options and any result access:

AI SDK 6
const result = await generateText({
model: yourModel,
experimental_output: Output.object({
schema: recipeSchema,
}),
prompt: 'Generate a recipe.',
});
console.log(result.experimental_output);
AI SDK 7
const result = await generateText({
model: yourModel,
output: Output.object({
schema: recipeSchema,
}),
prompt: 'Generate a recipe.',
});
console.log(result.output);

CallSettings Renamed to LanguageModelCallOptions and RequestOptions

CallSettings has been split into LanguageModelCallOptions (model-facing options) and RequestOptions (transport options). Replace usages in custom wrappers or helpers:

  • CallSettingsLanguageModelCallOptions & Omit<RequestOptions, 'timeout'> (note: CallSettings never included timeout)

The deprecated CallSettings type remains available in AI SDK 7.

Stop Condition Helper Rename: stepCountIs -> isStepCount

Rename imports and usage in tool-loop stop conditions:

Before
import { stepCountIs } from 'ai';
stopWhen: stepCountIs(3);
After
import { isStepCount } from 'ai';
stopWhen: isStepCount(3);

Prompts and Step Preparation

system Renamed to instructions

The top-level prompt option for system instructions has been renamed from system to instructions.

AI SDK 6
const result = await generateText({
model: yourModel,
system: 'You are a helpful assistant.',
prompt: 'Hello!',
});
AI SDK 7
const result = await generateText({
model: yourModel,
instructions: 'You are a helpful assistant.',
prompt: 'Hello!',
});

This applies to AI SDK functions that accept prompt or messages, including generateText, streamText, generateObject, streamObject, and streamUI.

The same rename applies to prepareStep results for generateText and streamText, and to the options passed into experimental_repairToolCall:

AI SDK 6
const result = streamText({
model: yourModel,
prompt: 'Hello!',
prepareStep: () => ({
system: 'Use concise answers for this step.',
}),
});
AI SDK 7
const result = streamText({
model: yourModel,
prompt: 'Hello!',
prepareStep: () => ({
instructions: 'Use concise answers for this step.',
}),
});

The system option is still accepted as a deprecated fallback. When both instructions and system are provided, instructions takes precedence.

prepareStep Instructions Carry Forward

In AI SDK 7, instructions returned from prepareStep are used in future steps until prepareStep returns another instructions or system override. This matches how messages returned from prepareStep carry forward.

In AI SDK 6, prepareStep instruction overrides only applied to the current step. Later steps fell back to the top-level system instructions unless they returned their own override.

If your prepareStep logic depends on one-step-only instruction overrides, return the desired instructions for each step explicitly:

AI SDK 7
const result = streamText({
model: yourModel,
instructions: 'Use the default behavior.',
prompt: 'Hello!',
prepareStep: ({ stepNumber, initialInstructions }) => ({
instructions:
stepNumber === 0
? 'Use special instructions for the first step.'
: initialInstructions,
}),
});

The prepareStep callback receives both instructions, which is the current instruction state for the step, and initialInstructions, which is the top-level instruction value from the original call.

If your tool call repair function forwards the current system instructions to another model call, read and pass instructions instead of system:

AI SDK 6
const result = await generateText({
model: yourModel,
tools,
prompt: 'Hello!',
experimental_repairToolCall: async ({ system, messages }) => {
return repairWithModel({ system, messages });
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
tools,
prompt: 'Hello!',
experimental_repairToolCall: async ({ instructions, messages }) => {
return repairWithModel({ instructions, messages });
},
});

Lifecycle callback events for generateText, streamText, and agents also use instructions instead of system:

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
experimental_onStart: ({ system }) => {
console.log(system);
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStart: ({ instructions }) => {
console.log(instructions);
},
});

Prompt Messages: System Messages in prompt or messages Are Rejected by Default

AI SDK 7 rejects system messages in the prompt or messages fields by default. System instructions should usually be passed with the top-level instructions option.

This can break older persisted chats or custom prompt arrays that include { role: 'system' } messages:

AI SDK 6
const result = await generateText({
model: yourModel,
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' },
],
});

Move system instructions to the instructions option when possible:

AI SDK 7
const result = await generateText({
model: yourModel,
instructions: 'You are a helpful assistant.',
messages: [{ role: 'user', content: 'Hello!' }],
});

If you need to keep existing chat histories that already contain system messages, opt in to the previous behavior with allowSystemInMessages: true:

Only use allowSystemInMessages for trusted messages. If users can submit or edit these messages, they could inject a system message that overrides or sets the system prompt. In most cases, system instructions should only be set by trusted server-side code through the instructions property.

AI SDK 7
const result = await generateText({
model: yourModel,
allowSystemInMessages: true,
messages: persistedMessages,
});

This applies to AI SDK functions that accept prompt or messages, including generateText, streamText, generateObject, streamObject, and streamUI.

Remove Deprecated experimental_prepareStep Option

The deprecated experimental_prepareStep option has been removed in AI SDK 7. Replace all remaining usages with prepareStep.

This option was deprecated in AI SDK 5, so if you already migrated to prepareStep, no changes are needed. Otherwise, update generateText calls:

AI SDK 6
const result = await generateText({
model: yourModel,
tools: { weather },
experimental_prepareStep: ({ stepNumber }) => {
console.log('Preparing step', stepNumber);
return {
activeTools: ['weather'],
};
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
tools: { weather },
prepareStep: ({ stepNumber }) => {
console.log('Preparing step', stepNumber);
return {
activeTools: ['weather'],
};
},
});

prepareStep Message Overrides Carry Forward

When prepareStep returns messages, those messages are now used as the base for subsequent steps. The next step receives those messages plus the response messages from the previous step.

In AI SDK 6, a messages override only applied to the current step. To keep that behavior, rebuild the current step's messages from initialMessages and responseMessages inside prepareStep:

AI SDK 7
const result = await generateText({
model: yourModel,
tools: { weather },
prepareStep: ({ initialMessages, responseMessages }) => {
return {
messages: [
...initialMessages,
...responseMessages,
// add any one-step-only message changes here
],
};
},
});

Lifecycle Events

experimental_onStart Renamed to onStart

The generation start callback for generateText, streamText, and agents has been renamed from experimental_onStart to onStart.

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
experimental_onStart: () => {
console.log('Generation started');
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStart: () => {
console.log('Generation started');
},
});

experimental_onStepStart Renamed to onStepStart

The per-step start callback for generateText, streamText, and agents has been renamed from experimental_onStepStart to onStepStart.

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
experimental_onStepStart: ({ stepNumber }) => {
console.log(`Step ${stepNumber} started`);
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStepStart: ({ stepNumber }) => {
console.log(`Step ${stepNumber} started`);
},
});

onFinish Renamed to onEnd

The final lifecycle callback for generateText, streamText, and agents has been renamed from onFinish to onEnd.

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onFinish: ({ text }) => {
console.log(text);
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onEnd: ({ text }) => {
console.log(text);
},
});

The same rename applies to streamText, Agent.generate(), Agent.stream(), and ToolLoopAgent settings. The onFinish option is still accepted as a deprecated alias. When both onEnd and onFinish are provided, onEnd takes precedence.

onStepFinish Renamed to onStepEnd

The per-step lifecycle callback has been renamed from onStepFinish to onStepEnd.

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStepFinish: ({ stepNumber, usage }) => {
console.log(`Step ${stepNumber} used ${usage.totalTokens} tokens`);
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStepEnd: ({ stepNumber, usage }) => {
console.log(`Step ${stepNumber} used ${usage.totalTokens} tokens`);
},
});

This applies to generateText, streamText, generateObject, streamObject, agents, workflow agents, and UI message stream helpers. Telemetry integrations should implement onStepEnd.

The onStepFinish option is still accepted as a deprecated alias for user-facing callbacks. When both onStepEnd and onStepFinish are provided, onStepEnd takes precedence.

Embed Callbacks

The per-call callback option for completed embed and embedMany operations has been renamed from experimental_onFinish to onEnd.

AI SDK 6
const result = await embed({
model: yourEmbeddingModel,
value,
experimental_onFinish(event) {
console.log('Embedding finished:', event.usage.tokens);
},
});
AI SDK 7
const result = await embed({
model: yourEmbeddingModel,
value,
onEnd(event) {
console.log('Embedding ended:', event.usage.tokens);
},
});

Rerank Callback

The per-call callback option for completed rerank operations has been renamed from experimental_onFinish to onEnd.

AI SDK 6
const result = await rerank({
model: yourRerankingModel,
documents,
query,
experimental_onFinish(event) {
console.log('Rerank finished:', event.ranking.length);
},
});
AI SDK 7
const result = await rerank({
model: yourRerankingModel,
documents,
query,
onEnd(event) {
console.log('Rerank ended:', event.ranking.length);
},
});

Usage and Result Shape Changes

cachedInputTokens and reasoningTokens Removed from LanguageModelUsage

The deprecated top-level cachedInputTokens and reasoningTokens fields have been removed from LanguageModelUsage.

Use inputTokenDetails.cacheReadTokens and outputTokenDetails.reasoningTokens instead:

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
});
console.log(result.usage.cachedInputTokens);
console.log(result.usage.reasoningTokens);
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
});
console.log(result.usage.inputTokenDetails.cacheReadTokens);
console.log(result.usage.outputTokenDetails.reasoningTokens);

Telemetry

OpenTelemetry Moved to @ai-sdk/otel

OpenTelemetry span collection is no longer built into the ai package. To continue receiving OpenTelemetry traces, you must install the new @ai-sdk/otel package and register the OpenTelemetry instance globally.

pnpm install @ai-sdk/otel

Previously, OpenTelemetry spans were emitted automatically when experimental_telemetry was enabled:

AI SDK 6
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: { isEnabled: true },
});

Now, you must install @ai-sdk/otel and register the OpenTelemetry instance once at application startup. For Next.js, place this in your instrumentation.ts file alongside your OpenTelemetry provider setup:

instrumentation
import { registerTelemetry } from 'ai';
import { OpenTelemetry } from '@ai-sdk/otel';
registerTelemetry(new OpenTelemetry());
// ... your OpenTelemetry provider setup (e.g. registerOTel, NodeTracerProvider)

For Node.js applications (without Next.js), register the integration at the top level of your entry file.

This applies to all AI SDK functions that accept experimental_telemetry, including generateText, streamText, ToolLoopAgent, embed, embedMany, and rerank.

Enabled by Default When an Integration Is Registered

In AI SDK 6, telemetry was opt-in — you had to set experimental_telemetry: { isEnabled: true } on every call to emit events. In AI SDK 7, telemetry is opt-out: once you register a telemetry integration (for example OpenTelemetry or DevToolsTelemetry), all AI SDK calls emit telemetry events by default.

AI SDK 6
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: { isEnabled: true },
});
AI SDK 7
import { generateText } from 'ai';
import { registerTelemetry } from 'ai';
import { OpenTelemetry } from '@ai-sdk/otel';
registerTelemetry(new OpenTelemetry());
const result = await generateText({
model: yourModel,
prompt: 'Hello',
});

You can safely remove experimental_telemetry: { isEnabled: true } from all of your calls. If you are already passing other fields like functionId or integrations, keep them — only isEnabled: true is redundant:

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: {
isEnabled: true,
functionId: 'my-awesome-function',
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: {
functionId: 'my-awesome-function',
},
});

To opt out of telemetry for a specific call, set isEnabled: false:

const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: { isEnabled: false },
});

To disable telemetry globally, do not register any telemetry integrations.

This applies to all AI SDK functions that accept experimental_telemetry, including generateText, streamText, ToolLoopAgent, embed, embedMany, and rerank.

tracer Property Removed from experimental_telemetry

The tracer property on experimental_telemetry has been removed. If you were passing a custom OpenTelemetry Tracer, pass it to the OpenTelemetry constructor instead:

AI SDK 6
import { generateText } from 'ai';
import { trace } from '@opentelemetry/api';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: {
isEnabled: true,
tracer: trace.getTracer('my-app'),
},
});
AI SDK 7
import { registerTelemetry } from 'ai';
import { OpenTelemetry } from '@ai-sdk/otel';
import { trace } from '@opentelemetry/api';
registerTelemetry(
new OpenTelemetry({
tracer: trace.getTracer('my-app'),
}),
);

This applies to all AI SDK functions that accept experimental_telemetry, including streamText, generateObject, streamObject, embed, and embedMany.

If you were not passing a custom tracer (relying on the default global tracer), no changes are needed — the OpenTelemetry is registered globally by default and uses trace.getTracer('ai') when no custom tracer is provided.

experimental_telemetry Renamed to telemetry

The telemetry option has graduated out of experimental status and has been renamed to telemetry. The old name experimental_telemetry continues to work as a deprecated alias in AI SDK 7 and will be removed in a future major release.

AI SDK 6
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: {
functionId: 'story-agent',
},
});
AI SDK 7
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
telemetry: {
functionId: 'story-agent',
},
});

This applies to all AI SDK functions and agents that accept telemetry configuration, including generateText, streamText, generateObject, streamObject, embed, embedMany, rerank, ToolLoopAgent, and WorkflowAgent.

No behavior changes beyond the rename. You can migrate incrementally — mixed usage of telemetry and experimental_telemetry in the same codebase is supported during the deprecation window.

onRerankFinish Renamed to onRerankEnd

The telemetry integration callback for individual reranking model calls has been renamed from onRerankFinish to onRerankEnd.

This also applies to the type field emitted on AI_SDK_TELEMETRY_TRACING_CHANNEL: tracing-channel subscribers now receive onRerankEnd instead of onRerankFinish.

Update telemetry integrations and tracing-channel subscribers to use onRerankEnd.

AI SDK 6
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onRerankFinish(event) {
console.log('Rerank finished:', event.ranking.length);
},
};
AI SDK 7
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onRerankEnd(event) {
console.log('Rerank ended:', event.ranking.length);
},
};

onEmbedFinish Renamed to onEmbedEnd

The telemetry integration callback for individual embedding model calls has been renamed from onEmbedFinish to onEmbedEnd.

This also applies to the type field emitted on AI_SDK_TELEMETRY_TRACING_CHANNEL: tracing-channel subscribers now receive onEmbedEnd instead of onEmbedFinish.

Update telemetry integrations and tracing-channel subscribers to use onEmbedEnd.

AI SDK 6
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onEmbedFinish(event) {
console.log('Embedding finished:', event.embeddings.length);
},
};
AI SDK 7
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onEmbedEnd(event) {
console.log('Embedding ended:', event.embeddings.length);
},
};

Streaming and Include Options

StreamTextResult.fullStream Renamed to stream

The full event stream returned by streamText has been renamed from fullStream to stream.

AI SDK 6
const result = streamText({
model: yourModel,
prompt: 'Hello!',
});
for await (const part of result.fullStream) {
console.log(part);
}
AI SDK 7
const result = streamText({
model: yourModel,
prompt: 'Hello!',
});
for await (const part of result.stream) {
console.log(part);
}

The fullStream property is still available as a deprecated alias for stream.

streamText onChunk Receives All Stream Parts

In AI SDK 7, streamText calls onChunk for every TextStreamPart emitted by the stream. In AI SDK 6, onChunk only received a subset of stream parts such as text deltas, reasoning deltas, sources, tool calls, tool input deltas, tool results, custom parts, and raw chunks.

Update handlers that assume the old subset to guard the chunk types they process:

AI SDK 7
const result = streamText({
model: yourModel,
prompt: 'Hello',
onChunk({ chunk }) {
if (chunk.type === 'text-delta') {
console.log(chunk.text);
}
},
});

onChunk can now also receive lifecycle, boundary, and terminal parts such as start, start-step, text-start, text-end, reasoning-start, reasoning-end, tool-input-end, finish-step, finish, abort, and error.

Move includeRawChunks to include.rawChunks

The top-level includeRawChunks option on streamText is deprecated in AI SDK 7. Move it into the include options object as rawChunks.

AI SDK 6
const result = streamText({
model: yourModel,
prompt: 'Hello',
includeRawChunks: true,
});
AI SDK 7
const result = streamText({
model: yourModel,
prompt: 'Hello',
include: {
rawChunks: true,
},
});

The deprecated top-level option continues to work in AI SDK 7, so you can migrate incrementally.

Rename experimental_include to include

The experimental_include option for generateText, streamText, and ToolLoopAgent is now stable and has been renamed to include.

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_include: {
requestBody: false,
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello',
include: {
requestBody: false,
},
});

The deprecated experimental_include name continues to work for backwards compatibility. If both include and experimental_include are provided, include takes precedence.

Request and Response Bodies Are Excluded by Default

In AI SDK 7, generateText and streamText no longer include request bodies in step results by default. generateText also no longer includes response bodies by default. This reduces memory usage, especially when prompts or provider responses contain large payloads such as images or files.

If your application reads result.request.body, step.request.body, result.response.body, or step.response.body, opt in with include.

AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Hello',
include: {
requestBody: true,
responseBody: true,
},
});

For streamText, only requestBody is available:

AI SDK 7
const result = streamText({
model: yourModel,
prompt: 'Hello',
include: {
requestBody: true,
},
});

Result Message Changes

Step Response Messages Are No Longer Accumulated

In AI SDK 7, step.response.messages on each StepResult only contains the response messages produced by that particular step.

In AI SDK 6, step.response.messages accumulated response messages from all previous steps. If your application reads step.response.messages from an intermediate or final step and expects the full assistant/tool message history, use the top-level result.responseMessages instead.

AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Use tools if needed',
tools,
stopWhen: isStepCount(5),
});
// Accumulated response messages from all steps:
const responseMessages = result.responseMessages;
// Response messages produced by each individual step:
const stepMessages = result.steps.map(step => step.response.messages);

If you specifically need to reconstruct response messages from step results, flatten the per-step messages:

AI SDK 7
const responseMessages = result.steps.flatMap(step => step.response.messages);

Prefer result.responseMessages when you want the full response message history. It also includes response messages produced before the first model step, such as tool results from approved tool calls in the input messages.

Tools and Tool Execution

Tool Execution Callbacks

The tool execution callback options for generateText and streamText have been renamed:

  • experimental_onToolCallStart is now onToolExecutionStart
  • experimental_onToolCallFinish is now onToolExecutionEnd

The old names continue to work as deprecated aliases in AI SDK 7 and will be removed in a future major release. They are only used as fallbacks when the new callback names are not provided.

AI SDK 6
const result = await generateText({
model: yourModel,
tools,
prompt: 'Hello',
experimental_onToolCallStart(event) {
console.log('Tool starting:', event.toolCall.toolName);
},
experimental_onToolCallFinish(event) {
console.log('Tool finished:', event.toolCall.toolName);
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
tools,
prompt: 'Hello',
onToolExecutionStart(event) {
console.log('Tool starting:', event.toolCall.toolName);
},
onToolExecutionEnd(event) {
console.log('Tool finished:', event.toolCall.toolName);
},
});

Context: experimental_context Became Tool context, and Shared Runtime Data Moved to runtimeContext

In AI SDK 7, the tool callback option previously exposed as experimental_context has been renamed to context and is now stable.

The bigger behavioral change is that AI SDK now separates:

  • tool-specific context, which is passed to tool callbacks from toolsContext
  • shared generation/agent runtime data, which flows through runtimeContext

In AI SDK 6, tools often read from one generic runtime context object. In AI SDK 7, each tool gets its own scoped context, and you provide those values through toolsContext, keyed by tool name.

tool() infers the type of a tool's context from its contextSchema, so each tool only sees the fields declared for that specific tool.

In AI SDK 6, tool code often accessed experimental_context and had to cast it manually:

AI SDK 6
const weather = tool({
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }, { experimental_context }) => {
const { weatherApiKey } = experimental_context as {
weatherApiKey: string;
};
return getWeather(location, weatherApiKey);
},
});

In AI SDK 7, rename experimental_context to context, declare the tool-specific context with contextSchema, and pass the per-tool values through toolsContext. The execute callback, approval callback, and tool input lifecycle hooks then receive a typed context automatically:

AI SDK 7
const weather = tool({
inputSchema: z.object({
location: z.string(),
}),
contextSchema: z.object({
apiKey: z.string(),
}),
execute: async ({ location }, { context: { apiKey } }) => {
return getWeather(location, apiKey);
},
});
const result = await generateText({
model: yourModel,
tools: { weather },
runtimeContext: {
requestId: 'req-123',
},
toolsContext: {
weather: {
apiKey: process.env.WEATHER_API_KEY!,
},
},
prepareStep: async ({ runtimeContext, toolsContext }) => {
console.log(runtimeContext.requestId);
console.log(toolsContext.weather.apiKey);
return {};
},
});

Use runtimeContext for shared generation or agent state that should be visible in prepareStep, events, and step results. Tool callbacks no longer read from that shared object. A tool's context now comes from its own entry in toolsContext, so it is limited to the fields that tool declared in contextSchema.

Potential breaking issues:

  • If you still destructure experimental_context in tool callbacks, rename it to context.
  • If you were previously passing one shared runtime object for both orchestration and tools, split it into runtimeContext and toolsContext.
  • Move tool-specific values into toolsContext under the matching tool name.
  • Rename shared top-level context usage to runtimeContext in generateText, streamText, and ToolLoopAgent.
  • Rename prepareStep usage from context to runtimeContext.
  • If a tool callback accesses fields that are not declared in its contextSchema, TypeScript will now report errors. Add those fields to that tool's schema.
  • If you have helper types or wrappers that assumed experimental_context or context was unknown, update them to accept a generic CONTEXT type.
  • If at least one tool declares contextSchema, toolsContext becomes required and only includes the tools that actually declare contextual data.
  • If you were relying on every tool callback seeing the same full runtime object, move shared step data to runtimeContext, or explicitly provide the needed per-tool data in each tool's toolsContext entry.

Migrate Deprecated needsApproval to toolApproval

The needsApproval property on tool() and dynamicTool() is deprecated in AI SDK 7 for generateText, streamText, and ToolLoopAgent.

Move approval logic to the toolApproval setting on the call or agent instead. This keeps approval policy close to the generation or agent configuration and lets you vary it by request.

AI SDK 6
const deleteFile = tool({
inputSchema: z.object({
path: z.string(),
}),
needsApproval: async ({ path }) => !path.startsWith('/tmp/'),
execute: async ({ path }) => {
await removeFile(path);
return { success: true };
},
});
await streamText({
model: yourModel,
tools: { deleteFile },
});
AI SDK 7
const deleteFile = tool({
inputSchema: z.object({
path: z.string(),
}),
execute: async ({ path }) => {
await removeFile(path);
return { success: true };
},
});
await streamText({
model: yourModel,
tools: { deleteFile },
toolApproval: {
deleteFile: async ({ path }) =>
path.startsWith('/tmp/') ? undefined : 'user-approval',
},
});

If you were using needsApproval: true, migrate it to toolApproval: { myTool: 'user-approval' }. If you were using a needsApproval function, move that logic into a per-tool SingleToolApprovalFunction or a generic toolApproval callback. This guidance applies to generateText, streamText, and ToolLoopAgent.

Remove Deprecated experimental_activeTools Option

The deprecated experimental_activeTools option has been removed in AI SDK 7. Replace all remaining usages with activeTools.

This option was deprecated in AI SDK 5, so if you already migrated to activeTools, no changes are needed. Otherwise, update both generateText and streamText calls:

AI SDK 6
const result = await generateText({
model: yourModel,
tools: { weather },
experimental_activeTools: ['weather'],
});
AI SDK 7
const result = await generateText({
model: yourModel,
tools: { weather },
activeTools: ['weather'],
});

Remove Deprecated ToolCallOptions Type

The deprecated ToolCallOptions type has been removed in AI SDK 7. Replace all remaining usages with ToolExecutionOptions.

If you already migrated away from the deprecated name in AI SDK 6, no changes are needed. Otherwise, update imports and type references:

AI SDK 6
import { ToolCallOptions } from 'ai';
function executeWithOptions(options: ToolCallOptions) {
// ...
}
AI SDK 7
import { ToolExecutionOptions } from 'ai';
function executeWithOptions(options: ToolExecutionOptions) {
// ...
}

UI Messages

Remove Deprecated isToolOrDynamicToolUIPart Function

The deprecated isToolOrDynamicToolUIPart function has been removed in AI SDK 7. Replace all remaining usages with isToolUIPart.

If you already migrated away from the deprecated name in AI SDK 6, no changes are needed. Otherwise, update imports and calls:

AI SDK 6
import { isToolOrDynamicToolUIPart } from 'ai';
if (isToolOrDynamicToolUIPart(part)) {
console.log('Tool part found');
}
AI SDK 7
import { isToolUIPart } from 'ai';
if (isToolUIPart(part)) {
console.log('Tool part found');
}

Tool and Message Content Parts

Remove Deprecated media Content Part Type

The deprecated tool result content part of { type: 'media' } has been removed in AI SDK 7.

Use { type: 'file-data' } for all inline file content, including images.

Tool Result Content: Migrate Away From image-* and file-* variants to file

All image-* and legacy file-* content part types for toModelOutput results are deprecated in AI SDK 7 in favor of a single canonical file variant that mirrors the top-level FilePart shape. Auto-migration is applied at runtime, so existing tool outputs continue to work without code changes. However, updating to the new shape is recommended.

The new shape carries a tagged data discriminated union, and it always has mediaType:

  • { type: 'file-data', data, mediaType, filename? }{ type: 'file', mediaType, filename, data: { type: 'data', data } }
  • { type: 'file-url', url, mediaType }{ type: 'file', mediaType, data: { type: 'url', url: new URL(url) } }
  • { type: 'file-reference', providerReference }{ type: 'file', mediaType, data: { type: 'reference', reference: providerReference } }

Images are just files with an image media type, so the image-* aliases collapse into the same shape — pass mediaType: 'image' (or a more specific image/* subtype) instead:

  • { type: 'image-data', data, mediaType }{ type: 'file', mediaType, data: { type: 'data', data } }
  • { type: 'image-url', url }{ type: 'file', mediaType: 'image', data: { type: 'url', url: new URL(url) } }
  • { type: 'image-file-reference', providerReference }{ type: 'file', mediaType: 'image', data: { type: 'reference', reference: providerReference } }

The -id content part types (file-id and image-file-id) are also generally deprecated in favor of the reference data shape, which carries a full ProviderReference (a provider-to-file-ID map like { openai: 'file_123', anthropic: 'file_abc' }) that lets the same logical file be reused across providers. The single-ID -id variants required the runtime to know which provider the ID belonged to; the explicit reference shape removes that ambiguity:

  • { type: 'file-id', fileId }{ type: 'file', mediaType, data: { type: 'reference', reference: { [provider]: fileId } } }
  • { type: 'image-file-id', fileId }{ type: 'file', mediaType: 'image', data: { type: 'reference', reference: { [provider]: fileId } } }

mediaType on the new file variant accepts either a full IANA type (e.g. 'image/png') or just a top-level segment (e.g. 'image', 'audio', 'video', 'text'). When only a top-level segment is provided, the subtype is auto-detected from inline bytes where possible. Update parsing/validation and discriminated unions to handle the single canonical file variant.

Message Parts: Migrate Away From Deprecated image Part

The { type: 'image', image, mediaType? } user-message content part is deprecated. Use { type: 'file', data, mediaType } with an image mediaType instead.

AI SDK 6
{ type: 'image', image: bytes }
AI SDK 7
{ type: 'file', mediaType: 'image', data: bytes }

mediaType on FilePart now accepts either a full IANA type (e.g. 'image/png') or just a top-level segment (e.g. 'image'). When only a top-level segment is provided, the subtype is auto-detected from inline bytes where possible.

Message Parts: Handle New reasoning-file Content Type

Some models can now return files as part of their reasoning trace, separate from regular output files. These files, which would have previously were using the file type, are now in a distinct reasoning-file type.

Update all exhaustive part handling (TypeScript unions, switch statements, runtime validators, renderers, serializers) to support type: 'reasoning-file'.

Also audit any code that reads generated files from result.files or step.files: files referenced in reasoning are now represented as reasoning-file parts in content / reasoning. In practice, this should rarely require an update because models usually reference the same file in their reasoning that they later output as regular content. Prior to supporting reasoning-file as a distinct type, this would result in the same files appearing in result.files or step.files as a duplicate.

Reasoning

Reasoning Configuration: Remove Overlapping Settings

The new top-level reasoning option is the provider-agnostic way to control reasoning effort.

When migrating to the top-level reasoning option, remove overlapping reasoning settings from providerOptions.

If both are present, provider-specific reasoning settings in providerOptions take precedence, which can silently bypass your new top-level reasoning configuration.

Multi-Step Result Shape

generateText and streamText usage Now Includes All Steps

The usage property on generateText and streamText results now returns the total token usage across all steps. This matches what totalUsage previously represented.

Use finalStep.usage to read the previous usage behavior, which only returned token usage from the final step:

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Write a haiku, then revise it.',
stopWhen: stepCountIs(2),
});
console.log(result.usage);
console.log(result.totalUsage);
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Write a haiku, then revise it.',
stopWhen: isStepCount(2),
});
console.log(result.finalStep.usage); // final step only
console.log(result.usage); // all steps

totalUsage is deprecated. Replace result.totalUsage with result.usage.

generateText and streamText Result Properties Now Include All Steps

The top-level content, toolCalls, staticToolCalls, dynamicToolCalls, toolResults, staticToolResults, dynamicToolResults, files, sources, and warnings properties on generateText and streamText results now return values accumulated across every step.

In AI SDK 6, these properties only returned values from the final step. Use finalStep to read the previous behavior:

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Use a tool, then summarize the result.',
stopWhen: stepCountIs(2),
});
console.log(result.toolCalls);
console.log(result.toolResults);
console.log(result.files);
console.log(result.sources);
console.log(result.warnings);
console.log(result.content);
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Use a tool, then summarize the result.',
stopWhen: isStepCount(2),
});
console.log(result.finalStep.toolCalls); // final step only
console.log(result.finalStep.toolResults); // final step only
console.log(result.finalStep.files); // final step only
console.log(result.finalStep.sources); // final step only
console.log(result.finalStep.warnings); // final step only
console.log(result.finalStep.content); // final step only
console.log(result.toolCalls); // all steps
console.log(result.toolResults); // all steps
console.log(result.files); // all steps
console.log(result.sources); // all steps
console.log(result.warnings); // all steps
console.log(result.content); // all steps

For streamText, await finalStep first when you need final-step-only values:

AI SDK 7
const result = streamText({
model: yourModel,
prompt: 'Use a tool, then summarize the result.',
stopWhen: isStepCount(2),
});
const finalStep = await result.finalStep;
console.log(finalStep.toolCalls); // final step only
console.log(finalStep.toolResults); // final step only
console.log(finalStep.files); // final step only
console.log(finalStep.sources); // final step only
console.log(finalStep.warnings); // final step only
console.log(finalStep.content); // final step only
console.log(await result.toolCalls); // all steps
console.log(await result.toolResults); // all steps
console.log(await result.files); // all steps
console.log(await result.sources); // all steps
console.log(await result.warnings); // all steps
console.log(await result.content); // all steps

Final-Step Result Properties Moved to finalStep

The top-level reasoning, reasoningText, request, response, and providerMetadata result properties on generateText and streamText are deprecated in AI SDK 7.

Use result.finalStep when you need final-step reasoning or final-step metadata:

AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Write a haiku, then revise it.',
stopWhen: stepCountIs(2),
});
console.log(result.reasoningText);
console.log(result.request.body);
console.log(result.response.headers);
console.log(result.providerMetadata?.anthropic);
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Write a haiku, then revise it.',
stopWhen: isStepCount(2),
});
console.log(result.finalStep.reasoningText);
console.log(result.finalStep.request.body);
console.log(result.finalStep.response.headers);
console.log(result.finalStep.providerMetadata?.anthropic);

For streamText, await finalStep first:

AI SDK 7
const result = streamText({
model: yourModel,
prompt: 'Write a haiku, then revise it.',
stopWhen: isStepCount(2),
});
const finalStep = await result.finalStep;
console.log(finalStep.reasoningText);
console.log(finalStep.request.body);
console.log(finalStep.response.headers);

The deprecated top-level aliases continue to work in AI SDK 7 so you can migrate incrementally.

generateText and streamText onEnd Result Properties Changed

The onEnd callback for generateText, streamText, and agents follows the same result property changes as generateText and streamText results:

  • usage now contains usage across all steps. totalUsage is deprecated; use usage instead.
  • content, toolCalls, toolResults, files, sources, and warnings now contain values from all steps.
  • Final-step-only properties are available on finalStep. The top-level reasoning, reasoningText, request, response, and providerMetadata properties are deprecated.
AI SDK 6
const result = await generateText({
model: yourModel,
prompt: 'Use a tool, then summarize the result.',
stopWhen: stepCountIs(2),
onFinish(event) {
console.log(event.usage); // final step only
console.log(event.totalUsage); // all steps
console.log(event.toolCalls); // final step only
console.log(event.providerMetadata);
},
});
AI SDK 7
const result = await generateText({
model: yourModel,
prompt: 'Use a tool, then summarize the result.',
stopWhen: isStepCount(2),
onEnd(event) {
console.log(event.finalStep.usage); // final step only
console.log(event.usage); // all steps
console.log(event.finalStep.toolCalls); // final step only
console.log(event.toolCalls); // all steps
console.log(event.finalStep.providerMetadata);
},
});

The deprecated top-level aliases on the onEnd event continue to work in AI SDK 7 so you can migrate incrementally.

Stream Response Helpers

streamText Response Helpers Deprecated — Use Stateless Helpers

The toUIMessageStream, toUIMessageStreamResponse, pipeUIMessageStreamToResponse, toTextStreamResponse, and pipeTextStreamToResponse methods on the streamText result are now deprecated. They still work in v7 (with deprecation warnings) and will be removed in the next major release.

The equivalent stateless helpers live on the top-level 'ai' export. Use them directly so the same transformation can be composed over any stream / textStream — not just a streamText result.

UI message stream

AI SDK 6
const result = streamText({ model, prompt });
const uiStream = result.toUIMessageStream({
originalMessages,
generateMessageId,
onFinish,
});
AI SDK 7
import { streamText, toUIMessageStream } from 'ai';
const result = streamText({ model, prompt });
const uiStream = toUIMessageStream({
stream: result.stream,
generateMessageId,
originalMessages,
onFinish,
});

UI message stream Response

AI SDK 6
return result.toUIMessageStreamResponse({ originalMessages });
AI SDK 7
import { createUIMessageStreamResponse, toUIMessageStream } from 'ai';
const uiStream = toUIMessageStream({
stream: result.stream,
generateMessageId,
originalMessages,
onFinish,
});
return createUIMessageStreamResponse({
stream: uiStream,
});

Pipe UI message stream to Node.js response

AI SDK 6
result.pipeUIMessageStreamToResponse(response, { originalMessages });
AI SDK 7
import { pipeUIMessageStreamToResponse, toUIMessageStream } from 'ai';
const uiStream = toUIMessageStream({
stream: result.stream,
generateMessageId,
originalMessages,
onFinish,
});
pipeUIMessageStreamToResponse({
stream: uiStream,
response,
});

Text stream Response

AI SDK 6
return result.toTextStreamResponse();
AI SDK 7
import { createTextStreamResponse, toTextStream } from 'ai';
const textStream = toTextStream({
stream: result.stream,
});
return createTextStreamResponse({ stream: textStream });

Pipe text stream to Node.js response

AI SDK 6
result.pipeTextStreamToResponse(response);
AI SDK 7
import { pipeTextStreamToResponse, toTextStream } from 'ai';
const textStream = toTextStream({
stream: result.stream,
});
pipeTextStreamToResponse({ response, stream: textStream });

MCP Package

MCP Transport: redirect Default Changed from 'follow' to 'error'

The redirect option on MCPTransportConfig (used by both HTTP and SSE transports) now defaults to 'error' instead of 'follow'. This means HTTP redirects are rejected by default to prevent server-side request forgery (SSRF) attacks where an MCP server could redirect requests to unintended hosts.

If your MCP server relies on HTTP redirects, explicitly set redirect: 'follow' in your transport configuration:

AI SDK 6
const mcpClient = await createMCPClient({
transport: {
type: 'http',
url: 'https://your-server.com/mcp',
},
});
AI SDK 7
const mcpClient = await createMCPClient({
transport: {
type: 'http',
url: 'https://your-server.com/mcp',
redirect: 'follow',
},
});

If the MCP server you use does not issue redirects, no changes are needed — the new default is more secure.

Vue Package

Chat Class Deprecated in Favor of useChat Composable

The Chat class exported from @ai-sdk/vue is deprecated in AI SDK 7 in favor of the new useChat composable. useChat exposes reactive refs for messages, status, and error, and automatically recreates the underlying chat when its init object changes — so reactive inputs (a route param, a selected model, etc.) flow through without manual orchestration.

AI SDK 6
<script setup lang="ts">
import { Chat } from '@ai-sdk/vue';
const chat = new Chat({});
</script>
<template>
<div v-for="m in chat.messages" :key="m.id">
<!-- ... -->
</div>
<button @click="chat.sendMessage({ text: 'hi' })">Send</button>
</template>
AI SDK 7
<script setup lang="ts">
import { useChat } from '@ai-sdk/vue';
const { messages, sendMessage } = useChat({
id: chatId,
transport: new DefaultChatTransport({
api: `/api/chats/${chatId}`,
body: { model: model.value },
}),
});
</script>
<template>
<div v-for="m in messages" :key="m.id">
<!-- ... -->
</div>
<button @click="sendMessage({ text: 'hi' })">Send</button>
</template>

To make the init reactive (recreate the chat when its inputs change), pass a getter or ref:

AI SDK 7
const { messages, sendMessage } = useChat(() => ({
id: chatId.value,
transport: new DefaultChatTransport({
api: `/api/chats/${chatId.value}`,
body: { model: model.value },
}),
}));

The Chat class continues to work as a deprecated export, so you can migrate incrementally.

OpenAI Provider

Responses Reasoning Summary Defaults to Detailed

For the OpenAI Responses provider, setting reasoning or providerOptions.openai.reasoningEffort to a value other than 'none' now defaults providerOptions.openai.reasoningSummary to 'detailed'.

If you want to keep reasoning summaries disabled, set providerOptions.openai.reasoningSummary to null.

Anthropic Provider

providerMetadata.anthropic.cacheCreationInputTokens Removed

The Anthropic-specific cacheCreationInputTokens field on providerMetadata.anthropic has been removed from the responses of generateText and streamText (as well as the @ai-sdk/google-vertex/anthropic sub-provider). This duplicated information that is already available on the standard, provider-agnostic usage object.

Use result.usage.inputTokenDetails.cacheWriteTokens to read the number of tokens written to the cache, and result.usage.inputTokenDetails.cacheReadTokens to read the number of tokens served from the cache:

AI SDK 6
const result = await generateText({
model: anthropic('claude-sonnet-4-5'),
messages: [
/* ... messages with cacheControl ... */
],
});
console.log(result.providerMetadata?.anthropic?.cacheCreationInputTokens);
AI SDK 7
const result = await generateText({
model: anthropic('claude-sonnet-4-5'),
messages: [
/* ... messages with cacheControl ... */
],
});
console.log(result.usage.inputTokenDetails.cacheWriteTokens);

If you need the raw Anthropic-shaped usage payload (including cache_creation_input_tokens, cache_read_input_tokens, cache_creation, service_tier, etc.), it is still available unchanged at result.finalStep.providerMetadata?.anthropic?.usage.

Google Provider

Renamed Types, Classes, and Functions: GenerativeAI Affix Removed

Every type, class, and function in @ai-sdk/google that contained GoogleGenerativeAI has been renamed to use simply Google — for example, createGoogleGenerativeAIcreateGoogle and GoogleGenerativeAIProviderGoogleProvider.

The old names still work as deprecated aliases, but you should migrate to the new names, if you currently reference them.

The main entry point the google constant, remains unchanged, so if that's all you use from the provider, no changes are required.

xAI Provider

Default Model Now Uses the Responses API

In AI SDK 7, xai(modelId) (and xai.languageModel(modelId)) uses the xAI Responses API by default instead of the Chat Completions API. Both APIs were already available in AI SDK 6 via xai.chat(modelId) and xai.responses(modelId); AI SDK 7 only changes which one xai(modelId) uses by default. To keep using the Chat Completions API, use xai.chat(modelId).

AI SDK 6
// used the Chat Completions API
const model = xai('grok-4.3');
AI SDK 7
// now uses the Responses API
const model = xai('grok-4.3');
// use the Chat Completions API explicitly
const chatModel = xai.chat('grok-4.3');

Migration Skill

Use the command below to add the migration skill and guide your agent

npx skills add vercel/ai --skill migrate-ai-sdk-v6-to-v7