new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

AI SDK · Core · all subjects

ai sdk core apis

1042 notes in this subject, read out of this brain and free to use. This is page 1 of 18.

Anthropic thinking option

The `thinking` option enables Anthropic's extended reasoning feature, giving Claude models a dedicated thinking phase before responding. It is configured as an object: `{ type: 'enabled', budgetTokens: number }`. The `budgetTokens` value sets the upper limit on tokens the model can use for internal reasoning. Higher budgets allow deeper reasoning but increase latency and cost. Thinking is supported on `claude-opus-4-20250514`, `claude-sonnet-4-20250514`, and `claude-sonnet-4-5-20250929` models.

Anthropic speed option example

Example showing how to use the `speed` option with `claude-opus-4-6`: ```ts import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; import { generateText } from 'ai'; const { text } = await generateText({ model: anthropic('claude-opus-4-6'), prompt: 'Write a short poem about the sea.', providerOptions: { anthropic: { speed: 'fast', // 'fast' | 'standard' } satisfies AnthropicLanguageModelOptions, }, }); ```

OpenAI reasoningEffort option

The `reasoningEffort` option for OpenAI reasoning models (e.g., `o3`, `o4-mini`, `gpt-5.2`) controls how much internal reasoning the model performs before responding. Supported values are: `'none'` (no reasoning, GPT-5.1 models only), `'minimal'` (bare-minimum reasoning), `'low'` (fast, concise reasoning), `'medium'` (balanced, default), `'high'` (thorough reasoning), and `'xhigh'` (maximum reasoning, GPT-5.1-Codex-Max only). The `'none'` and `'xhigh'` values are only supported on specific models.

Provider options with AI Gateway example

Example showing how to use provider options with the AI Gateway: ```ts import type { OpenAILanguageModelResponsesOptions } from '@ai-sdk/openai'; import { generateText } from 'ai'; const result = await generateText({ model: 'openai/gpt-5.2', // AI Gateway model string prompt: 'What are the implications of quantum computing for cryptography?', providerOptions: { openai: { reasoningEffort: 'high', reasoningSummary: 'detailed', } satisfies OpenAILanguageModelResponsesOptions, }, }); ```

Combining Anthropic provider options example

Example showing how to combine multiple Anthropic provider options in a single call: ```ts import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; import { generateText } from 'ai'; const result = await generateText({ model: anthropic('claude-opus-4-20250514'), prompt: 'Explain the Riemann hypothesis in simple terms.', providerOptions: { anthropic: { thinking: { type: 'enabled', budgetTokens: 8000 }, effort: 'medium', } satisfies AnthropicLanguageModelOptions, }, }); ```

Anthropic effort option example

Example showing how to use the `effort` option with Anthropic: ```ts import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; import { generateText } from 'ai'; const { text, usage } = await generateText({ model: anthropic('claude-opus-4-20250514'), prompt: 'How many people will live in the world in 2040?', providerOptions: { anthropic: { effort: 'low', // 'low' | 'medium' | 'high' } satisfies AnthropicLanguageModelOptions, }, }); ```

Combining gateway and provider-specific options example

Example showing how to combine gateway-specific options with provider-specific options in the same call: ```ts import type { AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; import type { GatewayProviderOptions } from '@ai-sdk/gateway'; import { generateText } from 'ai'; const result = await generateText({ model: 'anthropic/claude-sonnet-4', prompt: 'Explain quantum computing', providerOptions: { // Gateway-specific: control routing gateway: { order: ['vertex', 'anthropic'], } satisfies GatewayProviderOptions, // Provider-specific: enable reasoning anthropic: { thinking: { type: 'enabled', budgetTokens: 12000 }, } satisfies AnthropicLanguageModelOptions, }, }); ```

OpenAI reasoningSummary option

The `reasoningSummary` option surfaces the model's thought process when using reasoning models. Supported values are: `'auto'` (condensed summary of reasoning) and `'detailed'` (comprehensive reasoning output). When `reasoningEffort` is set to a value other than `'none'`, the OpenAI Responses provider defaults `reasoningSummary` to `'detailed'`. Set `reasoningSummary: null` to omit reasoning summaries.

Anthropic speed option for claude-opus-4-6

For the `claude-opus-4-6` model, the `speed` option enables approximately 2.5x faster output token speeds. Supported values are: `'fast'` and `'standard'`.

Anthropic thinking example

Example showing how to enable Anthropic thinking with `generateText`: ```ts import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; import { generateText } from 'ai'; const { text, reasoning, reasoningText } = await generateText({ model: anthropic('claude-opus-4-20250514'), prompt: 'How many people will live in the world in 2040?', providerOptions: { anthropic: { thinking: { type: 'enabled', budgetTokens: 12000 }, } satisfies AnthropicLanguageModelOptions, }, }); console.log('Reasoning:', reasoningText); console.log('Answer:', text); ```

providerOptions parameter

Provider options are passed via the `providerOptions` property on functions like `generateText` and `streamText`. They allow passing provider-specific configuration beyond standard settings shared by all providers. Provider options are namespaced by provider name (e.g., `openai`, `anthropic`), allowing multiple provider options in a single call with only the matching active provider's options being used.

OpenAI reasoningSummary streaming example

Example showing how to use `reasoningSummary` with `streamText`: ```ts import { openai, type OpenAILanguageModelResponsesOptions, } from '@ai-sdk/openai'; import { streamText } from 'ai'; const result = streamText({ model: openai('gpt-5.2'), prompt: 'Tell me about the Mission burrito debate in San Francisco.', providerOptions: { openai: { reasoningSummary: 'detailed', // 'auto' | 'detailed' } satisfies OpenAILanguageModelResponsesOptions, }, }); for await (const part of result.stream) { if (part.type === 'reasoning') { console.log(`Reasoning: ${part.textDelta}`); } else if (part.type === 'text-delta') { process.stdout.write(part.textDelta); } } ```

Provider options with AI Gateway

Provider options work the same way when using the Vercel AI Gateway. Use the underlying provider name (e.g., `openai`, `anthropic`) as the key, not `gateway`. The AI Gateway forwards these options to the target provider automatically. Gateway-specific options (like routing and fallbacks) can be combined with provider-specific options in the same call under separate keys in the `providerOptions` object.

OpenAI reasoningSummary non-streaming example

Example showing how to use `reasoningSummary` with `generateText`: ```ts import { openai, type OpenAILanguageModelResponsesOptions, } from '@ai-sdk/openai'; import { generateText } from 'ai'; const result = await generateText({ model: openai('gpt-5.2'), prompt: 'Tell me about the Mission burrito debate in San Francisco.', providerOptions: { openai: { reasoningSummary: 'auto', } satisfies OpenAILanguageModelResponsesOptions, }, }); console.log('Reasoning:', result.finalStep.reasoning); ```

Anthropic effort option

The `effort` option provides a simpler way to control reasoning depth without specifying a token budget. It affects thinking, text responses, and function calls. Supported values are: `'low'` (minimal reasoning, fastest responses), `'medium'` (balanced reasoning), and `'high'` (thorough reasoning, default).

OpenAI textVerbosity option

The `textVerbosity` option controls the length and detail of the model's text response independently of reasoning. Supported values are: `'low'` (terse, minimal responses), `'medium'` (balanced detail, default), and `'high'` (verbose, comprehensive responses).

Type safety for provider options

Each provider exports a type for its options that can be used with `satisfies` to get autocomplete and catch typos at build time. OpenAI exports `OpenAILanguageModelResponsesOptions` and Anthropic exports `AnthropicLanguageModelOptions`. These types should be imported from `@ai-sdk/openai` and `@ai-sdk/anthropic` respectively.

OpenAI reasoningEffort example with generateText

Example showing how to use `reasoningEffort` with `generateText`: ```ts import { openai, type OpenAILanguageModelResponsesOptions, } from '@ai-sdk/openai'; import { generateText } from 'ai'; const result = await generateText({ model: openai('gpt-5.2'), prompt: 'Invent a new holiday and describe its traditions.', providerOptions: { openai: { reasoningEffort: 'low', // 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' } satisfies OpenAILanguageModelResponsesOptions, }, }); console.log('Text:', result.text); console.log('Usage:', result.usage); console.log( 'Reasoning tokens:', result.finalStep.providerMetadata?.openai?.reasoningTokens, ); ```

Combining OpenAI provider options example

Example showing how to combine multiple OpenAI provider options in a single call: ```ts import { openai, type OpenAILanguageModelResponsesOptions, } from '@ai-sdk/openai'; import { generateText } from 'ai'; const result = await generateText({ model: openai('gpt-5.2'), prompt: 'What are the implications of quantum computing for cryptography?', providerOptions: { openai: { reasoningEffort: 'high', reasoningSummary: 'detailed', } satisfies OpenAILanguageModelResponsesOptions, }, }); ```

OpenAI textVerbosity example

Example showing how to use `textVerbosity` with `generateText`: ```ts import { openai, type OpenAILanguageModelResponsesOptions, } from '@ai-sdk/openai'; import { generateText } from 'ai'; const result = await generateText({ model: openai('gpt-5-mini'), prompt: 'Write a poem about a boy and his first pet dog.', providerOptions: { openai: { textVerbosity: 'low', // 'low' | 'medium' | 'high' } satisfies OpenAILanguageModelResponsesOptions, }, }); ```

isStepCount import and usage

The isStepCount function is imported from the 'ai' package and is used to specify a stopping condition for model generation based on the number of steps. For example, isStepCount(5) allows the model to generate for up to 5 steps before stopping.

streamText basic configuration

The streamText function accepts a configuration object with at minimum a model provider and messages array. Messages are passed as ModelMessage[] (not UIMessage), which can be obtained by calling convertToModelMessages on UIMessage[] to strip UI-specific metadata like timestamps and sender information.

ModelMessage type for LLM input

ModelMessage is the message format expected by language models. Unlike UIMessage, it does not include metadata like timestamps or sender information. The convertToModelMessages function transforms UIMessage[] into ModelMessage[] format.

isStepCount utility function

The isStepCount function is imported from the 'ai' package and creates a stopping condition. isStepCount(n) returns true when n steps have been completed, causing generation to stop at that point.

createGateway creates Vercel AI Gateway provider instance

The createGateway function from the 'ai' package creates a provider instance for the Vercel AI Gateway. It accepts a configuration object with an apiKey property. Once created, it can be called with a model string like gateway('anthropic/claude-sonnet-4.5') to get a specific model.

stopWhen with isStepCount for multi-step tool calls

To enable multi-step tool calls, pass stopWhen: isStepCount(n) to streamText where n is the maximum number of steps. isStepCount is imported from 'ai'. This allows the model to continue generating after tool results to provide a final answer.

streamText imports and basic usage in Expo

The streamText function is imported from the 'ai' package. It accepts a configuration object with at minimum a model provider and messages array. Call streamText with model and messages properties, then pass its returned stream to toUIMessageStream and return with createUIMessageStreamResponse.

UIMessage type and convertToModelMessages

Messages in useChat are typed as UIMessage[]. Use convertToModelMessages to convert UIMessage array to format expected by streamText before passing to the model.

createUIMessageStreamResponse for streaming responses

createUIMessageStreamResponse is used to wrap a stream and return it from an API route. It accepts a stream from toUIMessageStream and optional headers like 'Content-Type': 'application/octet-stream' and 'Content-Encoding': 'none'.

streamText function - return value

The streamText function returns a StreamTextResult object. This result includes a stream property containing the text generation stream. To convert this for UI consumption, pass result.stream to toUIMessageStream and then to createUIMessageStreamResponse.

createGateway function - API key configuration

The createGateway function creates a gateway provider instance for accessing models through Vercel AI Gateway. It accepts a configuration object with an apiKey property. The function is imported from the 'ai' package and is part of the default global provider configuration.

isStepCount function

The isStepCount function creates a stopping condition for multi-step tool calls. It takes a number parameter representing the maximum number of steps to allow. For example, isStepCount(5) allows the model to perform up to 5 steps of generation and tool calling before stopping.

streamText function - basic parameters

The streamText function accepts a configuration object with the following key parameters: model (a model provider instance), messages (a ModelMessage[] array), and optional tools and stopWhen settings. The messages parameter expects ModelMessage[] type, which differs from UIMessage by excluding metadata like timestamps.

ModelMessage type definition

ModelMessage is a message type used internally by models for generation. Unlike UIMessage, it does not include UI-specific metadata such as timestamps or sender information. The streamText function requires messages to be in ModelMessage[] format.

stopWhen parameter - default behavior

By default, stopWhen is set to isStepCount(1), meaning generation stops after the first step when there are tool results. This prevents the model from automatically processing tool results and continuing generation.

stopWhen parameter - enabling multi-step tool calls

To enable multi-step tool calls, change the stopWhen condition from its default isStepCount(1) to a higher value like isStepCount(5). This allows the model to automatically process tool results and continue generating until the specified step count is reached, enabling complex multi-turn tool interactions.

onStepEnd callback in streamText

The streamText function accepts an onStepEnd callback property that is called after each step of generation. The callback receives an object with a toolResults property containing an array of results from tool executions in that step.

ModelMessage type for conversation history

ModelMessage is a type imported from the 'ai' package used to represent messages in conversation history. Messages have a role property (either 'user' or 'assistant') and a content property containing the message text.

Example: Multi-step tool calls with stopWhen and onStepEnd

import { streamText, isStepCount } from 'ai'; const result = streamText({ model: __MODEL__, messages, tools: { /* tools defined here */ }, stopWhen: isStepCount(5), onStepEnd: async ({ toolResults }) => { if (toolResults.length) { console.log(JSON.stringify(toolResults, null, 2)); } }, }); This example shows how to enable multi-step tool calls that allow the agent to process results and make additional calls until the step limit is reached.

Example: Basic streamText chat with readline

import { ModelMessage, streamText } from 'ai'; import 'dotenv/config'; import * as readline from 'node:readline/promises'; const terminal = readline.createInterface({ input: process.stdin, output: process.stdout, }); const messages: ModelMessage[] = []; async function main() { while (true) { const userInput = await terminal.question('You: '); messages.push({ role: 'user', content: userInput }); const result = streamText({ model: __MODEL__, messages, }); let fullResponse = ''; process.stdout.write('\nAssistant: '); for await (const delta of result.textStream) { fullResponse += delta; process.stdout.write(delta); } process.stdout.write('\n\n'); messages.push({ role: 'assistant', content: fullResponse }); } } main().catch(console.error); This example shows a basic interactive chat interface using streamText that maintains conversation history and streams responses in real-time.

isStepCount function for step limiting

The isStepCount function is imported from the 'ai' package and takes a number parameter to specify the maximum number of steps (generations) allowed before stopping. For example, isStepCount(5) allows up to 5 steps in a single streamText call.

textStream property for iterating over generated text

The result object from streamText has a textStream property that is an async iterable. It yields delta strings representing chunks of the generated text, allowing real-time output streaming to be consumed piece by piece.

streamText function imports from ai package

The streamText function is imported from the 'ai' package and is used to create streaming text responses. It accepts a configuration object containing a model provider, messages, and optional additional settings to customize the model's behavior.

sendMessage function in useChat hook

The sendMessage function from useChat takes an object with a 'text' property containing the message text. It sends the message to the configured chat API route (default /api/chat).

Message parts array structure

Each message in useChat contains a parts array that represents everything the model generated in its response. Parts are ordered and can include different types such as 'text' parts containing text content, 'tool-{toolName}' parts for tool invocations, and potentially other content types.

TanStack Start useChat hook example

This example demonstrates useChat hook usage: ```tsx import { useChat } from '@ai-sdk/react'; import { useState } from 'react'; function Chat() { const [input, setInput] = useState(''); const { messages, sendMessage } = useChat(); return ( <div> {messages.map(message => ( <div key={message.id}> {message.role === 'user' ? 'User: ' : 'AI: '} {message.parts.map((part, i) => { switch (part.type) { case 'text': return <div key={`${message.id}-${i}`}>{part.text}</div>; case 'tool-weather': return ( <pre key={`${message.id}-${i}`}> {JSON.stringify(part, null, 2)} </pre> ); } })} </div> ))} <form onSubmit={e => { e.preventDefault(); sendMessage({ text: input }); setInput(''); }} > <input value={input} placeholder="Say something..." onChange={e => setInput(e.currentTarget.value)} /> </form> </div> ); } ```

convertToModelMessages converts UIMessage to ModelMessage

The convertToModelMessages function converts a UIMessage[] array into a ModelMessage[] array. UIMessage includes metadata like timestamps and sender information, while ModelMessage does not include this metadata. This conversion is necessary because streamText expects ModelMessage[] as input.

TanStack Start route handler with streamText example

This example shows a complete route handler for streaming text: ```tsx import { streamText, UIMessage, convertToModelMessages, createUIMessageStreamResponse, toUIMessageStream, } from 'ai'; __PROVIDER_IMPORT__; import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/api/chat')({ server: { handlers: { POST: async ({ request }) => { const { messages }: { messages: UIMessage[] } = await request.json(); const result = streamText({ model: __MODEL__, messages: await convertToModelMessages(messages), }); return createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }), }); }, }, }, }); ```

generateText example for DevTools

Example showing a basic generateText call that DevTools will capture: ```ts import { generateText } from 'ai'; const result = await generateText({ model: openai('gpt-4o'), prompt: 'What cities are in the United States?', }); ``` Once DevToolsTelemetry is registered, this call is automatically captured and visible in the DevTools UI.

Output schema definition with Output.object()

Define structured output schemas using Output.object() with a Zod schema. This enforces that the agent generates output matching the specified schema structure.

stopWhen accepts array of conditions

The stopWhen option can accept an array of multiple conditions that are combined. For example: stopWhen: [isStepCount(20), yourCustomCondition()]

Agent.generate() method for one-time text generation

Use agent.generate({ prompt: 'text' }) to invoke one-time text generation. Returns a result object with a text property containing the generated response.

prepareStep callback for step-level configuration

The prepareStep callback is called before each generation step and receives runtimeContext. It can return model call settings such as temperature that apply only to the current step. Later steps use the agent's top-level setting unless they return another override.

runtimeContext flows through agent loop

The runtimeContext is the agent's shared runtime state that flows through the agent loop and is available in prepareStep lifecycle callbacks and final results. Pass it via the runtimeContext parameter in agent.generate() or agent.stream().

Default stopWhen condition is 20 steps

By default, agents run for a maximum of 20 steps using the condition stopWhen: isStepCount(20). Each step represents one generation that results in either text or a tool call.

Agent.stream() method for streaming responses

Use agent.stream({ prompt: 'text' }) to get streaming responses. Returns a result object with a textStream async iterable. Iterate using for await (const chunk of result.textStream).

ToolLoopAgent accepts generateText and streamText configuration

The ToolLoopAgent accepts all the same settings as generateText and streamText functions, including model, instructions, tools, and other generation options.

ToolLoopAgent handles agent loop automatically

The ToolLoopAgent provides a structured way to encapsulate LLM configuration, tools, and behavior into reusable components. It handles the agent loop for you, allowing the LLM to call tools multiple times in sequence to accomplish complex tasks.

ToolLoopAgent class basic instantiation

Create an agent by instantiating the ToolLoopAgent class with a model, instructions, and tools configuration. Example: new ToolLoopAgent({ model: __MODEL__, instructions: 'You are a helpful assistant.', tools: { /* tools */ } })

createAgentUIStreamResponse() for API route responses

Use createAgentUIStreamResponse({ agent: myAgent, uiMessages: messages }) to create API responses for client applications. Typically used in API routes like app/api/chat/route.ts to handle chat interface requests.

Give your agent this brain