Skip to content

Chapter 10 · Reasoning Models ​

Chapter goals:

  • Understand the internal "reasoning" (thinking) phase of language models and its impact on answer quality
  • Master the cross-provider portable top-level reasoning parameter and its six tiers
  • Learn to separately handle reasoning and text-delta stream parts in streamText
  • Understand the precedence rules between reasoning and providerOptions
  • Know how to migrate from provider-specific configs to the portable reasoning parameter

10.1 What Is the Reasoning Phase ​

Many language models perform an internal "reasoning" phase (also called "thinking") before producing their final response. AI SDK provides a top-level reasoning parameter on both generateText and streamText to control this behavior across all providers in a portable way.

10.2 Basic Usage ​

ts
import { generateText, createGateway } from 'ai';

// Method 1: Vercel AI Gateway
const gateway = createGateway({ apiKey: process.env.AI_GATEWAY_API_KEY ?? '' });

const { text, reasoning, reasoningText } = await generateText({
  model: gateway('anthropic/claude-sonnet-4.6'),
  reasoning: 'medium',
  prompt: 'How many people will live in the world in 2040?',
});

// Method 2: Custom OpenAI-compatible Provider (choose one)
// import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
// const myProvider = createOpenAICompatible({
//   name: 'my-provider',
//   baseURL: process.env.OPENAI_COMPATIBLE_BASE_URL ?? '',
//   apiKey: process.env.OPENAI_COMPATIBLE_API_KEY ?? '',
// });
// const model = myProvider('claude-sonnet-4.6'); // Use your server's actual model name

The reasoning parameter accepts the following values:

ValueBehavior
'provider-default'Use the provider's default reasoning behavior (the default when omitted)
'none'Disable reasoning
'minimal'Minimal reasoning
'low'Fast, concise reasoning
'medium'Balanced reasoning
'high'Thorough reasoning
'xhigh'Maximum reasoning

10.3 Streaming Output ​

The reasoning parameter works identically in streamText. Stream parts are divided into reasoning and text-delta categories, which can be handled separately:

ts
import { streamText, createGateway } from 'ai';

const gateway = createGateway({ apiKey: process.env.AI_GATEWAY_API_KEY ?? '' });

const result = streamText({
  model: gateway('google/gemini-3-flash-preview'),
  reasoning: 'high',
  prompt: 'Explain the Riemann hypothesis in simple terms.',
});

for await (const part of result.stream) {
  if (part.type === 'reasoning') {
    process.stdout.write(part.textDelta);
  } else if (part.type === 'text-delta') {
    process.stdout.write(part.textDelta);
  }
}

10.4 Precedence Rules ​

The top-level reasoning parameter and provider-specific providerOptions never merge. If you set reasoning-related options in providerOptions, they take full effect and the top-level reasoning parameter is ignored:

ts
import { generateText, createGateway } from 'ai';

const { text } = await generateText({
  model: gateway('anthropic/claude-sonnet-4.6'),
  reasoning: 'low', // Ignored because providerOptions takes precedence
  providerOptions: {
    anthropic: {
      thinking: { type: 'enabled', budgetTokens: 2000 },
    },
  },
  prompt: 'Solve this math problem.',
});

10.5 Migration from Provider-Specific Configs ​

Anthropic ​

Previously configured via thinking:

ts
const { text } = await generateText({
  model: gateway('anthropic/claude-sonnet-4.6'),
  providerOptions: {
    anthropic: {
      thinking: { type: 'enabled', budgetTokens: 12000 },
    },
  },
  prompt: 'How many people will live in the world in 2040?',
});

Migrate to the portable parameter:

ts
const { text } = await generateText({
  model: gateway('anthropic/claude-sonnet-4.6'),
  reasoning: 'medium', // Replaces budgetTokens: 12000
  prompt: 'How many people will live in the world in 2040?',
});

Google ​

Previously configured via includeThoughts:

ts
const { text } = await generateText({
  model: gateway('google/gemini-3-flash-preview'),
  providerOptions: {
    google: { thinkingConfig: { includeThoughts: true } },
  },
  prompt: 'Explain the Riemann hypothesis in simple terms.',
});
ts
const { text } = await generateText({
  model: gateway('google/gemini-3-flash-preview'),
  reasoning: 'medium',
  providerOptions: {
    google: { thinkingConfig: { includeThoughts: true } }, // Non-reasoning options stay in providerOptions
  },
  prompt: 'Explain the Riemann hypothesis in simple terms.',
});

OpenAI ​

Previously configuring both reasoningEffort and reasoningSummary:

ts
const { text } = await generateText({
  model: gateway('openai/o3'),
  providerOptions: {
    openai: { reasoningEffort: 'high' },
  },
  prompt: 'Explain quantum entanglement.',
});
ts
const { text } = await generateText({
  model: gateway('openai/o3'),
  reasoning: 'high', // Replaces providerOptions.openai.reasoningEffort
  providerOptions: {
    openai: { reasoningSummary: 'auto' }, // Provider-specific features unrelated to reasoning strength stay in providerOptions
  },
  prompt: 'Explain quantum entanglement.',
});

Note: providerOptions can still be used alongside reasoning for provider-specific features unrelated to reasoning strength. But if providerOptions contains reasoning-strength/budget settings (e.g., reasoningEffort, thinking, thinkingConfig.thinkingBudget), they完全优先 and the top-level reasoning parameter is ignored.

Chapter Summary ​

  • Many models have an internal "reasoning" phase before producing the final response; AI SDK unifies control via the top-level reasoning parameter
  • Six tiers: none / minimal / low / medium / high / xhigh, plus provider-default
  • In streaming, reasoning parts and text-delta parts can be handled separately
  • providerOptions reasoning settings完全优先 over the top-level reasoning; they do not merge
  • Each provider maps reasoning to its native API; unsupported providers emit an unsupported warning
  • When migrating, keep provider-specific non-reasoning options in providerOptions; switch reasoning strength to the portable parameter

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. When omitting the reasoning parameter, what is the model's default behavior?

2. When providerOptions sets openai.reasoningEffort, what happens to reasoning: 'low' at the top level?

3. In which scenarios should you continue using providerOptions instead of the top-level reasoning parameter?

4. What happens when a reasoning-unsupported provider (e.g., Mistral) receives the reasoning parameter?

🛠️ Hands-On Exercises ​

  1. Call generateText on the same math problem with reasoning: 'low', 'medium', and 'high'; compare the returned reasoning text length and answer quality.
  2. Implement a terminal program with streamText + reasoning: 'high': print the reasoning section with a gray prefix, and the main text normally (refer to the stream part handling in 10.3).
  3. Migrate old code using providerOptions.anthropic.thinking.budgetTokens to the top-level reasoning parameter, and write a comment explaining what scenarios still require keeping providerOptions.

Next: Chapter 11 · Embeddings and Reranking