AI SDK 6.x를 7.0으로 마이그레이션
AI SDK 6.x를 7.0으로 마이그레이션 (Migrate AI SDK 6.x to 7.0)
아래 명령으로 마이그레이션 스킬을 추가하세요:
npx skills add vercel/ai --skill migrate-ai-sdk-v6-to-v7
그런 다음 에이전트에 요청하세요:
Use the migrate-ai-sdk-v6-to-v7 skill and migrate my app from AI SDK v6 to v7.
출처: 문서
본문
권장 마이그레이션 절차 (Recommended Migration Process)
- 프로젝트를 백업하세요. 버전 관리 시스템을 사용한다면 모든 이전 버전이 커밋되어 있는지 확인하세요.
- AI SDK 7.0으로 업그레이드하세요.
- 아래의 호환성 깨지는 변경 가이드를 따르세요.
- 프로젝트가 예상대로 동작하는지 확인하세요.
- 변경 사항을 커밋하세요.
예시 업그레이드 명령:
pnpm install ai @ai-sdk/react @ai-sdk/openai @ai-sdk/otel
Codemods
AI SDK는 기능이 deprecated, 제거되었거나 변경될 때 코드베이스 업그레이드를 돕는 Codemod 변환을 제공해요.
Codemods는 코드베이스에서 자동으로 실행되는 변환입니다. 매 파일을 수동으로 검토하지 않고도 많은 변경을 쉽게 적용할 수 있게 해줘요.
프로젝트 루트에서 다음 명령을 실행하면 모든 v7 codemod(v6 → v7 마이그레이션)를 실행할 수 있어요:
npx @ai-sdk/codemod v7
개별 codemod는 codemod 이름을 지정해 실행할 수 있어요:
npx @ai-sdk/codemod <codemod-name> <path>
예를 들어 특정 v7 codemod를 실행하려면:
npx @ai-sdk/codemod v7/rename-system-to-instructions src/
Codemod 표
| Codemod Name | Description |
|---|---|
remove-experimental-custom-provider |
Replaces experimental_customProvider with customProvider |
remove-experimental-generate-image |
Replaces experimental_generateImage and Experimental_GenerateImageResult with stable names |
replace-experimental-output-with-output |
Replaces experimental_output options and result access with output |
remove-experimental-prepare-step |
Replaces experimental_prepareStep with prepareStep |
replace-cached-input-tokens |
Replaces usage.cachedInputTokens with usage.inputTokenDetails.cacheReadTokens |
replace-reasoning-tokens |
Replaces usage.reasoningTokens with usage.outputTokenDetails.reasoningTokens |
remove-experimental-active-tools |
Replaces experimental_activeTools with activeTools |
remove-tool-call-options-type |
Replaces the removed ToolCallOptions type with ToolExecutionOptions |
remove-is-tool-or-dynamic-tool-uipart |
Replaces isToolOrDynamicToolUIPart with isToolUIPart |
remove-media-content-part-type |
Replaces tool result content parts with type: 'media' with type: 'file-data' |
replace-anthropic-cache-creation-input-tokens |
Replaces Anthropic cacheCreationInputTokens metadata access with standard usage fields |
rename-experimental-transcribe |
Renames experimental_transcribe and Experimental_TranscriptionResult to stable names |
rename-experimental-generate-speech |
Renames experimental_generateSpeech and Experimental_SpeechResult to stable names |
rename-call-settings-type |
Replaces CallSettings with LanguageModelCallOptions & Omit<RequestOptions, 'timeout'> |
rename-step-count-is |
Renames stepCountIs to isStepCount |
rename-system-to-instructions |
Renames system prompt options, lifecycle fields, and repair-tool-call fields to instructions |
rename-experimental-on-start-to-on-start |
Renames experimental_onStart to onStart |
rename-experimental-on-step-start-to-on-step-start |
Renames experimental_onStepStart to onStepStart |
rename-on-finish-to-on-end |
Renames onFinish callbacks to onEnd |
rename-on-step-finish-to-on-step-end |
Renames onStepFinish callbacks to onStepEnd |
rename-experimental-on-finish-to-on-end |
Renames experimental_onFinish callbacks to onEnd |
rename-experimental-telemetry-to-telemetry |
Renames experimental_telemetry options to telemetry |
rename-on-rerank-finish-to-on-rerank-end |
Renames telemetry onRerankFinish callbacks to onRerankEnd |
rename-on-embed-finish-to-on-embed-end |
Renames telemetry onEmbedFinish callbacks to onEmbedEnd |
rename-full-stream-to-stream |
Renames streamText result fullStream access to stream |
move-include-raw-chunks-to-include |
Moves includeRawChunks into include.rawChunks |
rename-experimental-include-to-include |
Renames experimental_include to include |
rename-experimental-on-tool-call-start-to-on-tool-execution-start |
Renames experimental_onToolCallStart to onToolExecutionStart |
rename-experimental-on-tool-call-finish-to-on-tool-execution-end |
Renames experimental_onToolCallFinish to onToolExecutionEnd |
rename-experimental-context-to-context |
Renames tool callback experimental_context access to context |
rename-google-generative-ai-to-google |
Renames Google provider types, classes, and functions that include GoogleGenerativeAI to Google |
replace-image-message-part-with-file |
Replaces image message parts with file parts using mediaType: 'image' |
모든 패키지 (All Packages)
최소 Node.js 버전 (Minimum Node.js Version)
AI SDK 7.0은 Node.js 22 이상을 요구합니다. SDK는 Node.js 22, 24, 26에서 테스트됩니다.
Node.js 18과 20은 더 이상 지원되지 않아요. Node.js 22는 2026년 4월 30일에 유지보수 종료에 도달했습니다. 프로덕션 워크로드에는 Node.js 24 (LTS) 또는 Node.js 26 을 권장합니다. 현재 상태와 지원 일정은 Node.js release schedule 을 참조하세요.
최소 Node.js 버전을 강제한다면 package.json 의 engines 필드를 업데이트하세요:
{
"engines": {
"node": ">=22"
}
}
ESM 전용 — CommonJS 지원 제거
모든 AI SDK 패키지는 이제 ESM 전용입니다. require() 함수는 더 이상 지원되지 않아요.
프로젝트가 CommonJS(require())를 사용한다면 ESM import 문법으로 전환하세요:
const { generateText } = require('ai');
const { openai } = require('@ai-sdk/openai');
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
package.json 에 이미 "type": "module" 이 없다면 추가하거나 파일의 확장자를 .mjs 로 바꾸세요.
AI SDK Core
Core API 이름 변경 및 제거
프로바이더 관리: deprecated된 experimental_customProvider 제거
AI SDK 7에서 deprecated된 experimental_customProvider export가 제거되었습니다. customProvider 로 바꾸세요.
import { experimental_customProvider } from 'ai';
export const myProvider = experimental_customProvider({
languageModels: {
// ...
},
});
import { customProvider } from 'ai';
export const myProvider = customProvider({
languageModels: {
// ...
},
});
이것은 단지 import와 심볼 이름 변경입니다. customProvider 옵션과 동작은 변경되지 않습니다.
deprecated된 experimental_generateImage export 제거
AI SDK 7에서 deprecated된 experimental_generateImage export가 제거되었습니다. generateImage 로 바꾸세요.
deprecated된 Experimental_GenerateImageResult 타입 export도 제거되었습니다. GenerateImageResult 로 바꾸세요.
import {
experimental_generateImage,
type Experimental_GenerateImageResult,
} from 'ai';
const result: Experimental_GenerateImageResult =
await experimental_generateImage({
model: yourImageModel,
prompt: 'A red panda eating bamboo',
});
import { generateImage, type GenerateImageResult } from 'ai';
const result: GenerateImageResult = await generateImage({
model: yourImageModel,
prompt: 'A red panda eating bamboo',
});
experimental_transcribe 를 transcribe 로 변경
전사(transcription) API가 실험 상태에서 졸업하여 transcribe 로 이름이 변경되었습니다. Experimental_TranscriptionResult 타입도 TranscriptionResult 로 이름이 변경되었습니다.
import {
experimental_transcribe as transcribe,
type Experimental_TranscriptionResult,
} from 'ai';
const result: Experimental_TranscriptionResult = await transcribe({
model: yourTranscriptionModel,
audio,
});
import { transcribe, type TranscriptionResult } from 'ai';
const result: TranscriptionResult = await transcribe({
model: yourTranscriptionModel,
audio,
});
이전 이름은 AI SDK 7에서 deprecated 별칭으로 계속 동작하며 향후 major 릴리스에서 제거됩니다.
experimental_generateSpeech 를 generateSpeech 로 변경
음성 생성 함수가 실험 상태에서 졸업하여 generateSpeech 로 이름이 변경되었습니다. Experimental_SpeechResult 타입도 SpeechResult 로 이름이 변경되었습니다.
import { experimental_generateSpeech as generateSpeech } from 'ai';
const result = await generateSpeech({
model: yourSpeechModel,
text: 'Hello',
});
import { generateSpeech } from 'ai';
const result = await generateSpeech({
model: yourSpeechModel,
text: 'Hello',
});
이전 experimental_generateSpeech 와 Experimental_SpeechResult export는 AI SDK 7에서 deprecated 별칭으로 계속 동작하며 향후 major 릴리스에서 제거됩니다.
구조화된 출력: deprecated된 experimental_output 옵션과 결과 제거
AI SDK 7에서 deprecated된 experimental_output 옵션이 제거되었습니다. 남은 모든 사용처를 output 으로 바꾸세요.
deprecated된 generateText() 결과 속성 experimental_output 도 제거되었습니다. result.output 을 읽으세요.
이 이름은 AI SDK 6에서 deprecated되었으므로 이미 output 으로 마이그레이션했다면 변경이 필요 없어요. 그렇지 않으면 호출 옵션과 결과 접근을 모두 업데이트하세요:
const result = await generateText({
model: yourModel,
experimental_output: Output.object({
schema: recipeSchema,
}),
prompt: 'Generate a recipe.',
});
console.log(result.experimental_output);
const result = await generateText({
model: yourModel,
output: Output.object({
schema: recipeSchema,
}),
prompt: 'Generate a recipe.',
});
console.log(result.output);
CallSettings 를 LanguageModelCallOptions 와 RequestOptions 로 변경
CallSettings 는 LanguageModelCallOptions(모델 지향 옵션)와 RequestOptions(전송 옵션)로 분할되었습니다. 커스텀 래퍼나 헬퍼의 사용처를 교체하세요:
CallSettings→LanguageModelCallOptions & Omit<RequestOptions, 'timeout'>(참고:CallSettings는timeout을 포함하지 않았음)
deprecated된 CallSettings 타입은 AI SDK 7에서 계속 사용할 수 있습니다.
중지 조건 헬퍼 이름 변경: stepCountIs -> isStepCount
tool-loop 중지 조건에서 import와 사용처를 바꾸세요:
import { stepCountIs } from 'ai';
stopWhen: stepCountIs(3);
import { isStepCount } from 'ai';
stopWhen: isStepCount(3);
프롬프트와 단계 준비 (Prompts and Step Preparation)
system 을 instructions 로 변경
시스템 지시용 최상위 프롬프트 옵션 이름이 system 에서 instructions 로 변경되었습니다.
const result = await generateText({
model: yourModel,
system: 'You are a helpful assistant.',
prompt: 'Hello!',
});
const result = await generateText({
model: yourModel,
instructions: 'You are a helpful assistant.',
prompt: 'Hello!',
});
이것은 prompt 또는 messages 를 받는 AI SDK 함수(generateText, streamText, generateObject, streamObject, streamUI 포함)에 적용됩니다.
같은 이름 변경이 generateText 와 streamText 의 prepareStep 결과와 experimental_repairToolCall 에 전달되는 옵션에도 적용됩니다:
const result = streamText({
model: yourModel,
prompt: 'Hello!',
prepareStep: () => ({
system: 'Use concise answers for this step.',
}),
});
const result = streamText({
model: yourModel,
prompt: 'Hello!',
prepareStep: () => ({
instructions: 'Use concise answers for this step.',
}),
});
system 옵션은 deprecated 폴백으로 여전히 허용됩니다. instructions 와 system 이 모두 제공되면 instructions 가 우선합니다.
prepareStep 지시 전달 (Carry Forward)
AI SDK 7에서 prepareStep 이 반환한 지시는 prepareStep 이 다른 instructions 또는 system 오버라이드를 반환할 때까지 이후 단계에서 사용됩니다. 이는 prepareStep 이 반환한 messages 가 전달되는 방식과 일치합니다.
AI SDK 6에서 prepareStep 지시 오버라이드는 현재 단계에만 적용되었습니다. 이후 단계는 자체 오버라이드를 반환하지 않는 한 최상위 system 지시로 폴백했어요.
prepareStep 로직이 한 단계 전용 지시 오버라이드에 의존한다면 각 단계에 원하는 지시를 명시적으로 반환하세요:
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,
}),
});
prepareStep 콜백은 현재 단계의 지시 상태인 instructions 와 원래 호출의 최상위 지시 값인 initialInstructions 를 모두 받아요.
tool call 수리 함수가 현재 시스템 지시를 다른 모델 호출로 전달한다면 system 대신 instructions 를 읽고 전달하세요:
const result = await generateText({
model: yourModel,
tools,
prompt: 'Hello!',
experimental_repairToolCall: async ({ system, messages }) => {
return repairWithModel({ system, messages });
},
});
const result = await generateText({
model: yourModel,
tools,
prompt: 'Hello!',
experimental_repairToolCall: async ({ instructions, messages }) => {
return repairWithModel({ instructions, messages });
},
});
generateText, streamText, 에이전트의 수명 주기 콜백 이벤트도 system 대신 instructions 를 사용합니다:
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
experimental_onStart: ({ system }) => {
console.log(system);
},
});
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStart: ({ instructions }) => {
console.log(instructions);
},
});
프롬프트 메시지: prompt 또는 messages 의 시스템 메시지가 기본적으로 거부됨
AI SDK 7은 prompt 또는 messages 필드의 시스템 메시지를 기본적으로 거부합니다. 시스템 지시는 일반적으로 최상위 instructions 옵션으로 전달해야 합니다.
이것은 { role: 'system' } 메시지를 포함하는 오래된 지속 채팅이나 커스텀 프롬프트 배열을 깨뜨릴 수 있습니다:
const result = await generateText({
model: yourModel,
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' },
],
});
가능하면 시스템 지시를 instructions 옵션으로 옮기세요:
const result = await generateText({
model: yourModel,
instructions: 'You are a helpful assistant.',
messages: [{ role: 'user', content: 'Hello!' }],
});
시스템 메시지를 이미 포함하는 기존 채팅 기록을 유지해야 한다면 allowSystemInMessages: true 로 이전 동작에 동의하세요:
const result = await generateText({
model: yourModel,
allowSystemInMessages: true,
messages: persistedMessages,
});
이것은 prompt 또는 messages 를 받는 AI SDK 함수(generateText, streamText, generateObject, streamObject, streamUI 포함)에 적용됩니다.
deprecated된 experimental_prepareStep 옵션 제거
AI SDK 7에서 deprecated된 experimental_prepareStep 옵션이 제거되었습니다. 남은 모든 사용처를 prepareStep 으로 바꾸세요.
이 옵션은 AI SDK 5에서 deprecated되었으므로 이미 prepareStep 으로 마이그레이션했다면 변경이 필요 없어요. 그렇지 않으면 generateText 호출을 업데이트하세요:
const result = await generateText({
model: yourModel,
tools: { weather },
experimental_prepareStep: ({ stepNumber }) => {
console.log('Preparing step', stepNumber);
return {
activeTools: ['weather'],
};
},
});
const result = await generateText({
model: yourModel,
tools: { weather },
prepareStep: ({ stepNumber }) => {
console.log('Preparing step', stepNumber);
return {
activeTools: ['weather'],
};
},
});
prepareStep 메시지 오버라이드 전달 (Carry Forward)
prepareStep 이 messages 를 반환하면 그 메시지는 이후 단계의 기반으로 사용됩니다. 다음 단계는 그 메시지에 이전 단계의 응답 메시지를 더한 것을 받습니다.
AI SDK 6에서 messages 오버라이드는 현재 단계에만 적용되었습니다. 그 동작을 유지하려면 prepareStep 안에서 initialMessages 와 responseMessages 로 현재 단계의 메시지를 재구성하세요:
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 를 onStart 로 변경
generateText, streamText, 에이전트의 생성 시작 콜백 이름이 experimental_onStart 에서 onStart 로 변경되었습니다.
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
experimental_onStart: () => {
console.log('Generation started');
},
});
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStart: () => {
console.log('Generation started');
},
});
experimental_onStepStart 를 onStepStart 로 변경
generateText, streamText, 에이전트의 단계별 시작 콜백 이름이 experimental_onStepStart 에서 onStepStart 로 변경되었습니다.
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
experimental_onStepStart: ({ stepNumber }) => {
console.log(`Step ${stepNumber} started`);
},
});
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStepStart: ({ stepNumber }) => {
console.log(`Step ${stepNumber} started`);
},
});
onFinish 를 onEnd 로 변경
generateText, streamText, 에이전트의 최종 수명 주기 콜백 이름이 onFinish 에서 onEnd 로 변경되었습니다.
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onFinish: ({ text }) => {
console.log(text);
},
});
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onEnd: ({ text }) => {
console.log(text);
},
});
같은 이름 변경이 streamText, Agent.generate(), Agent.stream(), ToolLoopAgent 설정에도 적용됩니다. onFinish 옵션은 deprecated 별칭으로 여전히 허용됩니다. onEnd 와 onFinish 가 모두 제공되면 onEnd 가 우선합니다.
onStepFinish 를 onStepEnd 로 변경
단계별 수명 주기 콜백 이름이 onStepFinish 에서 onStepEnd 로 변경되었습니다.
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStepFinish: ({ stepNumber, usage }) => {
console.log(`Step ${stepNumber} used ${usage.totalTokens} tokens`);
},
});
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
onStepEnd: ({ stepNumber, usage }) => {
console.log(`Step ${stepNumber} used ${usage.totalTokens} tokens`);
},
});
이것은 generateText, streamText, generateObject, streamObject, 에이전트, workflow 에이전트, UI 메시지 스트림 헬퍼에 적용됩니다. 텔레메트리 통합은 onStepEnd 를 구현해야 합니다.
onStepFinish 옵션은 사용자 대상 콜백의 deprecated 별칭으로 여전히 허용됩니다. onStepEnd 와 onStepFinish 가 모두 제공되면 onStepEnd 가 우선합니다.
Embed 콜백
완료된 embed 및 embedMany 작업에 대한 호출별 콜백 옵션 이름이 experimental_onFinish 에서 onEnd 로 변경되었습니다.
const result = await embed({
model: yourEmbeddingModel,
value,
experimental_onFinish(event) {
console.log('Embedding finished:', event.usage.tokens);
},
});
const result = await embed({
model: yourEmbeddingModel,
value,
onEnd(event) {
console.log('Embedding ended:', event.usage.tokens);
},
});
Rerank 콜백
완료된 rerank 작업에 대한 호출별 콜백 옵션 이름이 experimental_onFinish 에서 onEnd 로 변경되었습니다.
const result = await rerank({
model: yourRerankingModel,
documents,
query,
experimental_onFinish(event) {
console.log('Rerank finished:', event.ranking.length);
},
});
const result = await rerank({
model: yourRerankingModel,
documents,
query,
onEnd(event) {
console.log('Rerank ended:', event.ranking.length);
},
});
사용량 및 결과 형태 변경 (Usage and Result Shape Changes)
LanguageModelUsage 에서 cachedInputTokens 와 reasoningTokens 제거
deprecated된 최상위 cachedInputTokens 와 reasoningTokens 필드가 LanguageModelUsage 에서 제거되었습니다.
대신 inputTokenDetails.cacheReadTokens 와 outputTokenDetails.reasoningTokens 를 사용하세요:
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
});
console.log(result.usage.cachedInputTokens);
console.log(result.usage.reasoningTokens);
const result = await generateText({
model: yourModel,
prompt: 'Hello!',
});
console.log(result.usage.inputTokenDetails.cacheReadTokens);
console.log(result.usage.outputTokenDetails.reasoningTokens);
텔레메트리 (Telemetry)
OpenTelemetry가 @ai-sdk/otel 로 이동
OpenTelemetry 스팬 수집이 더 이상 ai 패키지에 내장되지 않습니다. OpenTelemetry 트레이스를 계속 받으려면 새 @ai-sdk/otel 패키지를 설치하고 OpenTelemetry 인스턴스를 전역으로 등록해야 합니다.
pnpm install @ai-sdk/otel
이전에는 experimental_telemetry 가 활성화되면 OpenTelemetry 스팬이 자동으로 방출되었습니다:
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: { isEnabled: true },
});
이제 @ai-sdk/otel 을 설치하고 애플리케이션 시작 시 OpenTelemetry 인스턴스를 한 번 등록해야 합니다. Next.js의 경우 instrumentation.ts 파일에 OpenTelemetry 프로바이더 설정과 함께 넣으세요:
import { registerTelemetry } from 'ai';
import { OpenTelemetry } from '@ai-sdk/otel';
registerTelemetry(new OpenTelemetry());
// ... your OpenTelemetry provider setup (e.g. registerOTel, NodeTracerProvider)
Node.js 애플리케이션(Next.js 없음)의 경우 진입 파일의 최상위에서 통합을 등록하세요.
이것은 experimental_telemetry 를 받는 모든 AI SDK 함수(generateText, streamText, ToolLoopAgent, embed, embedMany, rerank 포함)에 적용됩니다.
통합이 등록되면 기본으로 활성화
AI SDK 6에서 텔레메트리는 opt-in이었습니다. 호출마다 experimental_telemetry: { isEnabled: true } 를 설정해야 이벤트를 방출했습니다. AI SDK 7에서 텔레메트리는 opt-out입니다. 텔레메트리 통합(예: OpenTelemetry 또는 DevToolsTelemetry)을 등록하면 모든 AI SDK 호출이 기본적으로 텔레메트리 이벤트를 방출합니다.
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: { isEnabled: true },
});
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',
});
모든 호출에서 experimental_telemetry: { isEnabled: true } 를 안전하게 제거할 수 있습니다. functionId 나 integrations 같은 다른 필드를 이미 전달하고 있다면 유지하세요. isEnabled: true 만 중복됩니다:
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: {
isEnabled: true,
functionId: 'my-awesome-function',
},
});
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: {
functionId: 'my-awesome-function',
},
});
특정 호출에 대해 텔레메트리를 거부하려면 isEnabled: false 를 설정하세요:
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: { isEnabled: false },
});
전역으로 텔레메트리를 비활성화하려면 어떤 텔레메트리 통합도 등록하지 마세요.
이것은 experimental_telemetry 를 받는 모든 AI SDK 함수(generateText, streamText, ToolLoopAgent, embed, embedMany, rerank 포함)에 적용됩니다.
experimental_telemetry 에서 tracer 속성 제거
experimental_telemetry 의 tracer 속성이 제거되었습니다. 커스텀 OpenTelemetry Tracer 를 전달하고 있었다면 OpenTelemetry 생성자에 전달하세요:
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'),
},
});
import { registerTelemetry } from 'ai';
import { OpenTelemetry } from '@ai-sdk/otel';
import { trace } from '@opentelemetry/api';
registerTelemetry(
new OpenTelemetry({
tracer: trace.getTracer('my-app'),
}),
);
이것은 experimental_telemetry 를 받는 모든 AI SDK 함수(streamText, generateObject, streamObject, embed, embedMany 포함)에 적용됩니다.
커스텀 tracer 를 전달하지 않았다면(기본 전역 tracer에 의존) 변경이 필요 없습니다. OpenTelemetry 는 기본적으로 전역 등록되며 커스텀 tracer가 제공되지 않으면 trace.getTracer('ai') 를 사용합니다.
experimental_telemetry 를 telemetry 로 변경
텔레메트리 옵션이 실험 상태에서 졸업하여 telemetry 로 이름이 변경되었습니다. 이전 이름 experimental_telemetry 는 AI SDK 7에서 deprecated 별칭으로 계속 동작하며 향후 major 릴리스에서 제거됩니다.
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_telemetry: {
functionId: 'story-agent',
},
});
import { generateText } from 'ai';
const result = await generateText({
model: yourModel,
prompt: 'Hello',
telemetry: {
functionId: 'story-agent',
},
});
이것은 텔레메트리 설정을 받는 모든 AI SDK 함수와 에이전트(generateText, streamText, generateObject, streamObject, embed, embedMany, rerank, ToolLoopAgent, WorkflowAgent 포함)에 적용됩니다.
이름 변경 외에는 동작 변경이 없습니다. 점진적으로 마이그레이션할 수 있어요 — deprecated 기간 동안 같은 코드베이스에서 telemetry 와 experimental_telemetry 를 혼용하는 것도 지원됩니다.
onRerankFinish 를 onRerankEnd 로 변경
개별 reranking 모델 호출에 대한 텔레메트리 통합 콜백 이름이 onRerankFinish 에서 onRerankEnd 로 변경되었습니다.
이것은 AI_SDK_TELEMETRY_TRACING_CHANNEL 에 방출되는 type 필드에도 적용됩니다. 트레이싱 채널 구독자는 이제 onRerankFinish 대신 onRerankEnd 를 받습니다.
텔레메트리 통합과 트레이싱 채널 구독자를 onRerankEnd 를 사용하도록 업데이트하세요.
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onRerankFinish(event) {
console.log('Rerank finished:', event.ranking.length);
},
};
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onRerankEnd(event) {
console.log('Rerank ended:', event.ranking.length);
},
};
onEmbedFinish 를 onEmbedEnd 로 변경
개별 embedding 모델 호출에 대한 텔레메트리 통합 콜백 이름이 onEmbedFinish 에서 onEmbedEnd 로 변경되었습니다.
이것은 AI_SDK_TELEMETRY_TRACING_CHANNEL 에 방출되는 type 필드에도 적용됩니다. 트레이싱 채널 구독자는 이제 onEmbedFinish 대신 onEmbedEnd 를 받습니다.
텔레메트리 통합과 트레이싱 채널 구독자를 onEmbedEnd 를 사용하도록 업데이트하세요.
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onEmbedFinish(event) {
console.log('Embedding finished:', event.embeddings.length);
},
};
import type { Telemetry } from 'ai';
const telemetry: Telemetry = {
onEmbedEnd(event) {
console.log('Embedding ended:', event.embeddings.length);
},
};
스트리밍 및 Include 옵션
StreamTextResult.fullStream 을 stream 으로 변경
streamText 가 반환한 전체 이벤트 스트림 이름이 fullStream 에서 stream 으로 변경되었습니다.
const result = streamText({
model: yourModel,
prompt: 'Hello!',
});
for await (const part of result.fullStream) {
console.log(part);
}
const result = streamText({
model: yourModel,
prompt: 'Hello!',
});
for await (const part of result.stream) {
console.log(part);
}
fullStream 속성은 stream 의 deprecated 별칭으로 계속 사용할 수 있습니다.
streamText onChunk 가 모든 스트림 파트를 받음
AI SDK 7에서 streamText 는 스트림이 방출하는 모든 TextStreamPart 에 대해 onChunk 를 호출합니다. AI SDK 6에서 onChunk 는 텍스트 델타, 추론 델타, 소스, tool 호출, tool 입력 델타, tool 결과, 커스텀 파트, 원시 청크 같은 하위 스트림 파트만 받았습니다.
이전 하위 집합을 가정하는 핸들러를 처리하려는 청크 유형을 가드하도록 업데이트하세요:
const result = streamText({
model: yourModel,
prompt: 'Hello',
onChunk({ chunk }) {
if (chunk.type === 'text-delta') {
console.log(chunk.text);
}
},
});
onChunk 는 이제 start, start-step, text-start, text-end, reasoning-start, reasoning-end, tool-input-end, finish-step, finish, abort, error 같은 수명 주기, 경계, 터미널 파트도 받을 수 있습니다.
includeRawChunks 를 include.rawChunks 로 이동
streamText 의 최상위 includeRawChunks 옵션이 AI SDK 7에서 deprecated되었습니다. include 옵션 객체 안의 rawChunks 로 옮기세요.
const result = streamText({
model: yourModel,
prompt: 'Hello',
includeRawChunks: true,
});
const result = streamText({
model: yourModel,
prompt: 'Hello',
include: {
rawChunks: true,
},
});
deprecated된 최상위 옵션은 AI SDK 7에서 계속 동작하므로 점진적으로 마이그레이션할 수 있습니다.
experimental_include 를 include 로 변경
generateText, streamText, ToolLoopAgent 의 experimental_include 옵션이 이제 안정적이며 include 로 이름이 변경되었습니다.
const result = await generateText({
model: yourModel,
prompt: 'Hello',
experimental_include: {
requestBody: false,
},
});
const result = await generateText({
model: yourModel,
prompt: 'Hello',
include: {
requestBody: false,
},
});
deprecated된 experimental_include 이름은 백워드 호환성을 위해 계속 동작합니다. include 와 experimental_include 가 모두 제공되면 include 가 우선합니다.
요청 및 응답 본문이 기본적으로 제외됨
AI SDK 7에서 generateText 와 streamText 는 더 이상 단계 결과에 요청 본문을 기본적으로 포함하지 않습니다. generateText 는 응답 본문도 기본적으로 포함하지 않습니다. 이는 프롬프트나 프로바이더 응답에 이미지나 파일 같은 큰 페이로드가 들어 있을 때 메모리 사용량을 줄여줍니다.
애플리케이션이 result.request.body, step.request.body, result.response.body, step.response.body 를 읽는다면 include 로 opt-in 하세요.
const result = await generateText({
model: yourModel,
prompt: 'Hello',
include: {
requestBody: true,
responseBody: true,
},
});
streamText 의 경우 requestBody 만 사용할 수 있습니다:
const result = streamText({
model: yourModel,
prompt: 'Hello',
include: {
requestBody: true,
},
});
결과 메시지 변경 (Result Message Changes)
단계 응답 메시지가 더 이상 누적되지 않음
AI SDK 7에서 각 StepResult 의 step.response.messages 는 그 특정 단계가 만든 응답 메시지만 포함합니다.
AI SDK 6에서 step.response.messages 는 이전 모든 단계의 응답 메시지를 누적했습니다. 중간 또는 최종 단계에서 step.response.messages 를 읽고 전체 어시스턴트/tool 메시지 기록을 기대한다면 최상위 result.responseMessages 를 사용하세요.
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);
특히 단계 결과에서 응답 메시지를 재구성해야 한다면 단계별 메시지를 평탄화하세요:
const responseMessages = result.steps.flatMap(step => step.response.messages);
전체 응답 메시지 기록을 원할 때는 result.responseMessages 를 선호하세요. 이는 입력 메시지에서 승인된 tool 호출의 tool 결과처럼 첫 번째 모델 단계 전에 만들어진 응답 메시지도 포함합니다.
Tools 및 Tool 실행
Tool 실행 콜백
generateText 와 streamText 의 tool 실행 콜백 옵션 이름이 변경되었습니다:
experimental_onToolCallStart→onToolExecutionStartexperimental_onToolCallFinish→onToolExecutionEnd
이전 이름은 AI SDK 7에서 deprecated 별칭으로 계속 동작하며 향후 major 릴리스에서 제거됩니다. 새 콜백 이름이 제공되지 않을 때만 폴백으로 사용됩니다.
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);
},
});
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);
},
});
컨텍스트: experimental_context 가 tool context 로, 공유 런타임 데이터가 runtimeContext 로 이동
AI SDK 7에서 이전에 experimental_context 로 노출되던 tool 콜백 옵션이 context 로 이름이 변경되었고 이제 안정적입니다.
더 큰 동작 변경은 AI SDK가 이제 다음을 분리한다는 것입니다:
toolsContext에서 tool 콜백으로 전달되는 tool별contextruntimeContext를 통해 흐르는 공유 생성/에이전트 런타임 데이터
AI SDK 6에서 tools는 종종 하나의 범용 런타임 컨텍스트 객체에서 읽었습니다. AI SDK 7에서 각 tool은 자신만의 스코프된 context 를 얻고, tool 이름 키로 된 toolsContext 를 통해 그 값들을 제공합니다.
tool() 은 contextSchema 에서 tool의 context 타입을 추론하므로 각 tool은 특정 tool에 선언된 필드만 봅니다.
AI SDK 6에서 tool 코드는 종종 experimental_context 에 접근해 수동으로 캐스팅했습니다:
const weather = tool({
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }, { experimental_context }) => {
const { weatherApiKey } = experimental_context as {
weatherApiKey: ***
};
return getWeather(location, weatherApiKey);
},
});
AI SDK 7에서 experimental_context 를 context 로 이름을 바꾸고, contextSchema 로 tool별 컨텍스트를 선언하고, toolsContext 를 통해 tool별 값을 전달하세요. 그러면 execute 콜백, 승인 콜백, tool 입력 수명 주기 훅이 타입화된 context 를 자동으로 받습니다:
const weather = tool({
inputSchema: z.object({
location: z.string(),
}),
contextSchema: z.object({
apiKey: ***
}),
execute: async ({ location }, { context: { apiKey } }) => {
return getWeather(location, apiKey);
},
});
const result = await generateText({
model: yourModel,
tools: { weather },
runtimeContext: {
requestId: 'req-123',
},
toolsContext: {
weather: {
apiKey: proces...EY!,
},
},
prepareStep: async ({ runtimeContext, toolsContext }) => {
console.log(runtimeContext.requestId);
console.log(toolsContext.weather.apiKey);
return {};
},
});
prepareStep, 이벤트, 단계 결과에서 보여야 하는 공유 생성 또는 에이전트 상태에는 runtimeContext 를 사용하세요. tool 콜백은 더 이상 그 공유 객체에서 읽지 않습니다. tool의 context 는 이제 toolsContext 의 자체 항목에서 오므로, 그 tool이 contextSchema 에 선언한 필드로 제한됩니다.
잠재적 호환성 문제:
- tool 콜백에서 여전히
experimental_context를 구조 분해한다면context로 이름을 바꾸세요. - 오케스트레이션과 tools 양쪽에 하나의 공유 런타임 객체를 전달하고 있었다면
runtimeContext와toolsContext로 분리하세요. - tool별 값을 일치하는 tool 이름 아래
toolsContext로 옮기세요. generateText,streamText,ToolLoopAgent에서 공유 최상위context사용처를runtimeContext로 바꾸세요.prepareStep사용처를context에서runtimeContext로 바꾸세요.- tool 콜백이
contextSchema에 선언되지 않은 필드에 접근하면 TypeScript가 이제 오류를 보고합니다. 그 필드를 해당 tool의 스키마에 추가하세요. experimental_context또는context가unknown이라고 가정한 헬퍼 타입이나 래퍼가 있다면 제네릭CONTEXT타입을 받도록 업데이트하세요.- 최소 하나의 tool이
contextSchema를 선언하면toolsContext가 필수가 되고 실제로 컨텍스트 데이터를 선언하는 tools만 포함합니다. - 모든 tool 콜백이 동일한 전체 런타임 객체를 본다고 의존하고 있었다면 공유 단계 데이터를
runtimeContext로 옮기거나 각 tool의toolsContext항목에 필요한 tool별 데이터를 명시적으로 제공하세요.
deprecated된 needsApproval 을 toolApproval 로 마이그레이션
tool() 및 dynamicTool() 의 needsApproval 속성은 generateText, streamText, ToolLoopAgent 용으로 AI SDK 7에서 deprecated되었습니다.
승인 로직을 호출 또는 에이전트의 toolApproval 설정으로 옮기세요. 이렇게 하면 승인 정책이 생성 또는 에이전트 설정과 가까워지고 요청별로 다르게 할 수 있습니다.
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 },
});
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',
},
});
needsApproval: true 를 사용하고 있었다면 toolApproval: { myTool: 'user-approval' } 로 마이그레이션하세요. needsApproval 함수를 사용하고 있었다면 그 로직을 tool별 SingleToolApprovalFunction 또는 제네릭 toolApproval 콜백으로 옮기세요. 이 지침은 generateText, streamText, ToolLoopAgent 에 적용됩니다.
deprecated된 experimental_activeTools 옵션 제거
AI SDK 7에서 deprecated된 experimental_activeTools 옵션이 제거되었습니다. 남은 모든 사용처를 activeTools 로 바꾸세요.
이 옵션은 AI SDK 5에서 deprecated되었으므로 이미 activeTools 로 마이그레이션했다면 변경이 필요 없어요. 그렇지 않으면 generateText 와 streamText 호출을 모두 업데이트하세요:
const result = await generateText({
model: yourModel,
tools: { weather },
experimental_activeTools: ['weather'],
});
const result = await generateText({
model: yourModel,
tools: { weather },
activeTools: ['weather'],
});
deprecated된 ToolCallOptions 타입 제거
AI SDK 7에서 deprecated된 ToolCallOptions 타입이 제거되었습니다. 남은 모든 사용처를 ToolExecutionOptions 로 바꾸세요.
AI SDK 6에서 이미 deprecated 이름에서 벗어났다면 변경이 필요 없습니다. 그렇지 않으면 import와 타입 참조를 업데이트하세요:
import { ToolCallOptions } from 'ai';
function executeWithOptions(options: ToolCallOptions) {
// ...
}
import { ToolExecutionOptions } from 'ai';
function executeWithOptions(options: ToolExecutionOptions) {
// ...
}
UI 메시지 (UI Messages)
deprecated된 isToolOrDynamicToolUIPart 함수 제거
AI SDK 7에서 deprecated된 isToolOrDynamicToolUIPart 함수가 제거되었습니다. 남은 모든 사용처를 isToolUIPart 로 바꾸세요.
AI SDK 6에서 이미 deprecated 이름에서 벗어났다면 변경이 필요 없습니다. 그렇지 않으면 import와 호출을 업데이트하세요:
import { isToolOrDynamicToolUIPart } from 'ai';
if (isToolOrDynamicToolUIPart(part)) {
console.log('Tool part found');
}
import { isToolUIPart } from 'ai';
if (isToolUIPart(part)) {
console.log('Tool part found');
}
Tool 및 메시지 콘텐츠 파트
deprecated된 media 콘텐츠 파트 타입 제거
AI SDK 7에서 { type: 'media' } 의 deprecated된 tool 결과 콘텐츠 파트가 제거되었습니다.
이미지를 포함한 모든 인라인 파일 콘텐츠에는 { type: 'file-data' } 를 사용하세요.
Tool 결과 콘텐츠: image-* 및 file-* 변형에서 file 로 마이그레이션
toModelOutput 결과의 모든 image-* 및 레거시 file-* 콘텐츠 파트 타입은 최상위 FilePart 형태를 반영하는 단일 정식 file 변형을 위해 AI SDK 7에서 deprecated되었습니다. 자동 마이그레이션이 런타임에 적용되므로 기존 tool 출력은 코드 변경 없이 계속 동작합니다. 그러나 새 형태로 업데이트하는 것이 권장됩니다.
새 형태는 태그된 data 판별 유니언을 갖고 항상 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 } }
이미지는 이미지 미디어 타입을 가진 파일일 뿐이므로 image-* 별칭은 같은 형태로 접힙니다. mediaType: 'image'(또는 더 구체적인 image/* 하위 타입)를 전달하세요:
{ 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 } }
-id 콘텐츠 파트 타입(file-id 및 image-file-id)도 일반적으로 전체 ProviderReference(예: { openai: 'file_123', anthropic: 'file_abc' } 같은 프로바이더 대 파일 ID 맵)를 갖는 reference 데이터 형태를 위해 deprecated되었습니다. 이를 통해 같은 논리적 파일을 프로바이더 전반에서 재사용할 수 있습니다. 단일 ID -id 변형은 런타임이 ID가 속한 프로바이더를 알아야 했습니다. 명시적 참조 형태가 그 모호성을 제거합니다:
{ 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 } } }
새 file 변형의 mediaType 은 전체 IANA 타입(예: 'image/png')이나 최상위 세그먼트(예: 'image', 'audio', 'video', 'text')를 받습니다. 최상위 세그먼트만 제공되면 가능한 경우 인라인 바이트에서 하위 타입을 자동 감지합니다. 단일 정식 file 변형을 처리하도록 파싱/검증과 판별 유니언을 업데이트하세요.
메시지 파트: deprecated된 image 파트에서 마이그레이션
{ type: 'image', image, mediaType? } 사용자 메시지 콘텐츠 파트가 deprecated되었습니다. 이미지 mediaType 과 함께 { type: 'file', data, mediaType } 을 사용하세요.
{ type: 'image', image: bytes }
{ type: 'file', mediaType: 'image', data: bytes }
FilePart 의 mediaType 은 이제 전체 IANA 타입(예: 'image/png')이나 최상위 세그먼트(예: 'image')를 받습니다. 최상위 세그먼트만 제공되면 가능한 경우 인라인 바이트에서 하위 타입을 자동 감지합니다.
메시지 파트: 새 reasoning-file 콘텐츠 타입 처리
일부 모델은 이제 일반 출력 파일과는 별도로 추론 트레이스의 일부로 파일을 반환할 수 있습니다. 이전에 file 타입을 사용하던 이러한 파일은 이제 별개의 reasoning-file 타입에 있습니다.
모든 배타적 파트 처리를 type: 'reasoning-file' 을 지원하도록 업데이트하세요(TypeScript 유니언, switch 문, 런타임 검증기, 렌더러, 직렬화기).
또한 result.files 또는 step.files 에서 생성된 파일을 읽는 코드를 감사하세요. 추론에 참조된 파일은 이제 content / reasoning 에서 reasoning-file 파트로 표현됩니다. 실제로 모델이 추론에서 나중에 일반 콘텐츠로 출력하는 같은 파일을 참조하므로 업데이트가 거의 필요하지 않을 것입니다. reasoning-file 을 별개 타입으로 지원하기 전에는 이로 인해 같은 파일이 result.files 나 step.files 에 중복으로 나타났습니다.
추론 (Reasoning)
추론 구성: 겹치는 설정 제거
새 최상위 reasoning 옵션은 추론 노력을 제어하는 프로바이더 중립적 방식입니다.
최상위 reasoning 옵션으로 마이그레이션할 때 providerOptions 에서 겹치는 추론 설정을 제거하세요.
둘 다 존재하면 providerOptions 의 프로바이더 특화 추론 설정이 우선하며, 새 최상위 reasoning 구성을 조용히 우회할 수 있습니다.
다중 단계 결과 형태
generateText 와 streamText 의 usage 가 이제 모든 단계 포함
generateText 와 streamText 결과의 usage 속성은 이제 모든 단계에 걸친 총 토큰 사용량을 반환합니다. 이는 이전에 totalUsage 가 나타내던 것과 일치합니다.
이전 usage 동작을 읽으려면 finalStep.usage 를 사용하세요. 이는 최종 단계의 토큰 사용량만 반환합니다:
const result = await generateText({
model: yourModel,
prompt: 'Write a haiku, then revise it.',
stopWhen: stepCountIs(2),
});
console.log(result.usage);
console.log(result.totalUsage);
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 는 deprecated되었습니다. result.totalUsage 를 result.usage 로 바꾸세요.
generateText 및 streamText 결과 속성이 이제 모든 단계 포함
generateText 와 streamText 결과의 최상위 content, toolCalls, staticToolCalls, dynamicToolCalls, toolResults, staticToolResults, dynamicToolResults, files, sources, warnings 속성은 이제 모든 단계에 걸쳐 누적된 값을 반환합니다.
AI SDK 6에서 이 속성들은 최종 단계의 값만 반환했습니다. 이전 동작을 읽으려면 finalStep 을 사용하세요:
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);
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
streamText 의 경우 최종 단계 전용 값이 필요할 때 finalStep 을 먼저 await 하세요:
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
최종 단계 결과 속성이 finalStep 으로 이동
generateText 와 streamText 의 최상위 reasoning, reasoningText, request, response, providerMetadata 결과 속성은 AI SDK 7에서 deprecated되었습니다.
최종 단계 추론이나 최종 단계 메타데이터가 필요할 때 result.finalStep 을 사용하세요:
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);
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);
streamText 의 경우 finalStep 을 먼저 await 하세요:
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);
deprecated된 최상위 별칭은 AI SDK 7에서 계속 동작하므로 점진적으로 마이그레이션할 수 있습니다.
generateText 와 streamText onEnd 결과 속성 변경
generateText, streamText, 에이전트의 onEnd 콜백은 generateText 및 streamText 결과와 동일한 결과 속성 변경을 따릅니다:
usage는 이제 모든 단계의 사용량을 포함합니다.totalUsage는 deprecated되었으며usage를 사용하세요.content,toolCalls,toolResults,files,sources,warnings는 이제 모든 단계의 값을 포함합니다.- 최종 단계 전용 속성은
finalStep에 있습니다. 최상위reasoning,reasoningText,request,response,providerMetadata속성은 deprecated되었습니다.
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);
},
});
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);
},
});
deprecated된 최상위 별칭은 onEnd 이벤트에서 AI SDK 7에서 계속 동작하므로 점진적으로 마이그레이션할 수 있습니다.
스트림 응답 헬퍼
streamText 응답 헬퍼 deprecated — 상태 비저장 헬퍼 사용
streamText 결과의 toUIMessageStream, toUIMessageStreamResponse, pipeUIMessageStreamToResponse, toTextStreamResponse, pipeTextStreamToResponse 메서드는 이제 deprecated되었습니다. v7에서 계속 동작하며(deprecation 경고 포함) 다음 major 릴리스에서 제거됩니다.
동등한 상태 비저장 헬퍼는 최상위 'ai' export에 있습니다. 직접 사용해서 같은 변환이 streamText 결과뿐 아니라 어떤 stream / textStream 위에서도 구성될 수 있게 하세요.
UI 메시지 스트림
const result = streamText({ model, prompt });
const uiStream = result.toUIMessageStream({
originalMessages,
generateMessageId,
onFinish,
});
import { streamText, toUIMessageStream } from 'ai';
const result = streamText({ model, prompt });
const uiStream = toUIMessageStream({
stream: result.stream,
generateMessageId,
originalMessages,
onFinish,
});
UI 메시지 스트림 Response
return result.toUIMessageStreamResponse({ originalMessages });
import { createUIMessageStreamResponse, toUIMessageStream } from 'ai';
const uiStream = toUIMessageStream({
stream: result.stream,
generateMessageId,
originalMessages,
onFinish,
});
return createUIMessageStreamResponse({
stream: uiStream,
});
UI 메시지 스트림을 Node.js 응답으로 파이핑
result.pipeUIMessageStreamToResponse(response, { originalMessages });
import { pipeUIMessageStreamToResponse, toUIMessageStream } from 'ai';
const uiStream = toUIMessageStream({
stream: result.stream,
generateMessageId,
originalMessages,
onFinish,
});
pipeUIMessageStreamToResponse({
stream: uiStream,
response,
});
텍스트 스트림 Response
return result.toTextStreamResponse();
import { createTextStreamResponse, toTextStream } from 'ai';
const textStream = toTextStream({
stream: result.stream,
});
return createTextStreamResponse({ stream: textStream });
텍스트 스트림을 Node.js 응답으로 파이핑
result.pipeTextStreamToResponse(response);
import { pipeTextStreamToResponse, toTextStream } from 'ai';
const textStream = toTextStream({
stream: result.stream,
});
pipeTextStreamToResponse({ response, stream: textStream });
MCP 패키지
MCP Transport: redirect 기본값이 'follow' 에서 'error' 로 변경
MCPTransportConfig (HTTP 및 SSE transport 모두가 사용)의 redirect 옵션이 이제 기본값이 'follow' 대신 'error' 입니다. 이는 MCP 서버가 요청을 의도하지 않은 호스트로 리다이렉트할 수 있는 서버 측 요청 위조(SSRF) 공격을 방지하기 위해 HTTP 리다이렉트가 기본적으로 거부된다는 뜻입니다.
MCP 서버가 HTTP 리다이렉트에 의존한다면 transport 구성에 명시적으로 redirect: 'follow' 를 설정하세요:
const mcpClient = await createMCPClient({
transport: {
type: 'http',
url: 'https://your-server.com/mcp',
},
});
const mcpClient = await createMCPClient({
transport: {
type: 'http',
url: 'https://your-server.com/mcp',
redirect: 'follow',
},
});
사용 중인 MCP 서버가 리다이렉트를 발행하지 않는다면 변경이 필요 없습니다. 새 기본값이 더 안전하니까요.
Vue 패키지
Chat 클래스 deprecated — useChat 컴포저블 권장
@ai-sdk/vue 에서 export되는 Chat 클래스는 새 useChat 컴포저블을 위해 AI SDK 7에서 deprecated되었습니다. useChat 는 messages, status, error 에 대한 반응형 refs를 노출하고 init 객체가 바뀌면 기본 채팅을 자동으로 재생성합니다. 따라서 반응형 입력(라우트 파라미터, 선택된 모델 등)이 수동 오케스트레이션 없이 흐릅니다.
<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>
<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>
init을 반응형으로 만들려면(입력이 바뀔 때 채팅 재생성) getter나 ref를 전달하세요:
const { messages, sendMessage } = useChat(() => ({
id: chatId.value,
transport: new DefaultChatTransport({
api: `/api/chats/${chatId.value}`,
body: { model: model.value },
}),
}));
Chat 클래스는 deprecated export로 계속 동작하므로 점진적으로 마이그레이션할 수 있습니다.
OpenAI 프로바이더
Responses 추론 요약이 기본으로 상세(Detailed)
OpenAI Responses 프로바이더의 경우 reasoning 또는 providerOptions.openai.reasoningEffort 를 'none' 이 아닌 값으로 설정하면 providerOptions.openai.reasoningSummary 가 기본값 'detailed' 가 됩니다.
추론 요약을 비활성화로 유지하려면 providerOptions.openai.reasoningSummary 를 null 로 설정하세요.
Anthropic 프로바이더
providerMetadata.anthropic.cacheCreationInputTokens 제거
providerMetadata.anthropic 의 Anthropic 특화 cacheCreationInputTokens 필드가 generateText 와 streamText(그리고 @ai-sdk/google-vertex/anthropic 서브-프로바이더)의 응답에서 제거되었습니다. 이는 표준 프로바이더 중립 usage 객체에 이미 있는 정보를 중복한 것입니다.
캐시에 쓰여진 토큰 수를 읽으려면 result.usage.inputTokenDetails.cacheWriteTokens 를, 캐시에서 제공된 토큰 수를 읽으려면 result.usage.inputTokenDetails.cacheReadTokens 를 사용하세요:
const result = await generateText({
model: anthropic('claude-sonnet-4-5'),
messages: [
/* ... messages with cacheControl ... */
],
});
console.log(result.providerMetadata?.anthropic?.cacheCreationInputTokens);
const result = await generateText({
model: anthropic('claude-sonnet-4-5'),
messages: [
/* ... messages with cacheControl ... */
],
});
console.log(result.usage.inputTokenDetails.cacheWriteTokens);
원시 Anthropic 형태의 사용량 페이로드(예: cache_creation_input_tokens, cache_read_input_tokens, cache_creation, service_tier 등)가 필요하다면 result.finalStep.providerMetadata?.anthropic?.usage 에 변경 없이 여전히 사용할 수 있습니다.
Google 프로바이더
이름 변경된 타입, 클래스, 함수: GenerativeAI 접두어 제거
@ai-sdk/google 의 모든 GoogleGenerativeAI 를 포함한 타입, 클래스, 함수는 단순히 Google 을 사용하도록 이름이 변경되었습니다. 예: createGoogleGenerativeAI → createGoogle, GoogleGenerativeAIProvider → GoogleProvider.
이전 이름은 deprecated 별칭으로 계속 동작하지만, 현재 참조하고 있다면 새 이름으로 마이그레이션해야 합니다.
주요 진입점인 google 상수는 변경 없이 유지되므로, 프로바이더에서 그것만 사용한다면 변경이 필요 없습니다.
xAI 프로바이더
기본 모델이 이제 Responses API를 사용
AI SDK 7에서 xai(modelId)(및 xai.languageModel(modelId))는 기본적으로 Chat Completions API 대신 xAI Responses API를 사용합니다. 두 API 모두 AI SDK 6에서 xai.chat(modelId) 및 xai.responses(modelId) 로 이미 사용 가능했습니다. AI SDK 7은 xai(modelId) 가 기본으로 사용하는 것만 변경합니다. Chat Completions API를 계속 사용하려면 xai.chat(modelId) 를 사용하세요.
// used the Chat Completions API
const model = xai('grok-4.3');
// 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)
아래 명령으로 마이그레이션 스킬을 추가하고 에이전트를 안내하세요:
npx skills add vercel/ai --skill migrate-ai-sdk-v6-to-v7
더 알아보기 (Learn more)
- Versioning
- Migrate AI SDK 6.x to 7.0
- Migrate AI SDK 5.x to 6.0
- Migrate Your Data to AI SDK 5.0
- Migrate AI SDK 4.x to 5.0
- Migrate AI SDK 4.1 to 4.2
- Migrate AI SDK 4.0 to 4.1
- Migrate AI SDK 3.4 to 4.0
- Migrate AI SDK 3.3 to 3.4
- Migrate AI SDK 3.2 to 3.3
- Migrate AI SDK 3.1 to 3.2
- Migrate AI SDK 3.0 to 3.1