Skip to content

Vercel

The Vercel AI SDK is a TypeScript toolkit for building AI-powered applications. It defines a Language Model Specification that standardizes how applications interact with LLMs across providers. The Strands Agents SDK includes a VercelModel adapter that wraps any Language Model Specification v3 (LanguageModelV3) provider for use as a Strands model provider.

This means you can bring models from the entire Vercel AI SDK ecosystem - including @ai-sdk/openai, @ai-sdk/anthropic, @ai-sdk/amazon-bedrock, @ai-sdk/google, and many more - directly into Strands agents.

Install the Strands Harness SDK along with the Vercel AI SDK provider package for the model you want to use:

Terminal window
# OpenAI
npm install @strands-agents/sdk @ai-sdk/openai
# Amazon Bedrock
npm install @strands-agents/sdk @ai-sdk/amazon-bedrock
# Anthropic
npm install @strands-agents/sdk @ai-sdk/anthropic
# Google Generative AI
npm install @strands-agents/sdk @ai-sdk/google

The @ai-sdk/provider package (which defines the LanguageModelV3 interface) is listed as an optional peer dependency of @strands-agents/sdk and will be installed automatically with any @ai-sdk/* provider.

For community providers like Ollama, install the community package directly:

Terminal window
npm install @strands-agents/sdk ai-sdk-ollama

Create a LanguageModelV3 instance from any Vercel provider and wrap it with VercelModel:

import { Agent } from '@strands-agents/sdk'
import { VercelModel } from '@strands-agents/sdk/models/vercel'
import { openai } from '@ai-sdk/openai'
const agent = new Agent({
model: new VercelModel({ provider: openai('gpt-4o') }),
})
const result = await agent.invoke('Hello!')
console.log(result)
import { Agent } from '@strands-agents/sdk'
import { VercelModel } from '@strands-agents/sdk/models/vercel'
import { bedrock } from '@ai-sdk/amazon-bedrock'
const agent = new Agent({
model: new VercelModel({
provider: bedrock('us.anthropic.claude-sonnet-4-20250514-v1:0'),
}),
})
const result = await agent.invoke('Hello!')
console.log(result)
import { Agent } from '@strands-agents/sdk'
import { VercelModel } from '@strands-agents/sdk/models/vercel'
import { anthropic } from '@ai-sdk/anthropic'
const agent = new Agent({
model: new VercelModel({ provider: anthropic('claude-sonnet-4-20250514') }),
})
const result = await agent.invoke('Hello!')
console.log(result)
import { Agent } from '@strands-agents/sdk'
import { VercelModel } from '@strands-agents/sdk/models/vercel'
import { google } from '@ai-sdk/google'
const agent = new Agent({
model: new VercelModel({ provider: google('gemini-2.5-flash') }),
})
const result = await agent.invoke('Hello!')
console.log(result)
import { Agent } from '@strands-agents/sdk'
import { VercelModel } from '@strands-agents/sdk/models/vercel'
import { ollama } from 'ai-sdk-ollama'
const agent = new Agent({
model: new VercelModel({ provider: ollama('llama3.1') }),
})
const result = await agent.invoke('Hello!')
console.log(result)

VercelModel accepts configuration directly alongside the provider option. These include all LanguageModelV3CallOptions settings (temperature, topP, topK, penalties, stop sequences, seed, etc.) plus the base Strands model config fields.

const model = new VercelModel({
provider: openai('gpt-4o'),
maxTokens: 1000,
temperature: 0.7,
topP: 0.9,
})
const agent = new Agent({ model })
const result = await agent.invoke('Write a short poem')
console.log(result)
ParameterDescriptionExample
modelIdOverride the model ID (defaults to the provider’s model ID)'gpt-4o'
maxTokensMaximum tokens to generate1000
temperatureControls randomness0.7
topPNucleus sampling0.9
topKTop-k sampling40
presencePenaltyEncourages new topics0.5
frequencyPenaltyReduces repetition0.5
stopSequencesCustom stop sequences['END']
seedDeterministic generation42

When new fields are added to the Language Model Specification, they become available in the config automatically.

The adapter supports streaming text, reasoning content, and tool use:

const agent = new Agent({
model: new VercelModel({ provider: openai('gpt-4o') }),
})
for await (const event of agent.stream('Tell me a story')) {
if (
event.type === 'modelContentBlockDeltaEvent' &&
event.delta.type === 'textDelta'
) {
process.stdout.write(event.delta.text)
}
}

The adapter supports structured output through the underlying provider’s native capabilities. Define a Zod schema, pass it as structuredOutputSchema, and read validated output from result.structuredOutput:

import { Agent } from '@strands-agents/sdk'
import { VercelModel } from '@strands-agents/sdk/models/vercel'
import { openai } from '@ai-sdk/openai'
import { z } from 'zod'
const MovieReview = z.object({
title: z.string().describe('Movie title'),
rating: z.number().min(1).max(10).describe('Rating from 1-10'),
genre: z.string().describe('Primary genre'),
sentiment: z.enum(['positive', 'negative', 'neutral']).describe('Overall sentiment'),
summary: z.string().describe('Brief summary of the review'),
})
const agent = new Agent({
model: new VercelModel({ provider: openai('gpt-4o') }),
structuredOutputSchema: MovieReview,
})
const result = await agent.invoke(
`Just watched "The Matrix" - what an incredible sci-fi masterpiece!
The groundbreaking visual effects and philosophical themes make this
a must-watch. Keanu Reeves delivers a solid performance. 9/10!`
)
const review = result.structuredOutput as z.infer<typeof MovieReview>
console.log(`Movie: ${review.title}`)
console.log(`Rating: ${review.rating}/10`)
console.log(`Sentiment: ${review.sentiment}`)

For schema patterns, error handling, and per-invocation overrides, see Structured Output.

Because VercelModel wraps the same @ai-sdk/* provider you already use, Strands is additive to a Vercel AI SDK app rather than a replacement. Keep your provider packages and your client, and run the Strands agent server-side in an App Router route handler: you get the agent loop, tools, sessions, and hooks around the model you were already calling.

Build the agent with VercelModel and stream its events back to the client. Strands requires Node 22+, so run the handler on the Node.js runtime, not the Edge runtime:

app/api/chat/route.ts
import { Agent } from '@strands-agents/sdk'
import { VercelModel } from '@strands-agents/sdk/models/vercel'
import { openai } from '@ai-sdk/openai'
// Strands needs the Node.js runtime (Node 22+), not Edge.
export const runtime = 'nodejs'
export async function POST(req: Request) {
const { prompt } = await req.json()
const agent = new Agent({
model: new VercelModel({ provider: openai('gpt-4o') }),
})
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
// Each event serializes to wire-safe JSON — its toJSON() drops the live
// agent reference and keeps only the serializable fields.
for await (const event of agent.stream(prompt, { cancelSignal: req.signal })) {
controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`))
}
controller.close()
},
})
return new Response(stream, {
headers: { 'Content-Type': 'text/event-stream' },
})
}

Passing cancelSignal: req.signal stops the agent when the client disconnects.

Reading the stream directly means switching on each event’s type. The events you care about for a chat UI are modelStreamUpdateEvent (streamed text and reasoning deltas), toolStreamUpdateEvent (tool progress), and agentResultEvent (the final result):

const res = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ prompt }),
})
const reader = res.body!.getReader()
const decoder = new TextDecoder()
for (;;) {
const { value, done } = await reader.read()
if (done) break
for (const line of decoder.decode(value).split('\n\n')) {
if (!line.startsWith('data: ')) continue
const event = JSON.parse(line.slice(6))
if (event.type === 'modelStreamUpdateEvent') {
const inner = event.event
if (inner.type === 'modelContentBlockDeltaEvent' && inner.delta.type === 'textDelta') {
appendToMessage(inner.delta.text) // render the streamed text
}
} else if (event.type === 'agentResultEvent') {
// event.result is the final AgentResult
}
}
}

See Streaming for the full event union, and Agent Loop for tools, sessions, and lifecycle hooks you can add around the model.

The VercelModel adapter handles:

  • Streaming text, reasoning, and tool use (both incremental and complete tool call events)
  • Message formatting: text, images, documents, video, tool use/results, and reasoning blocks
  • Tool specification and tool choice mapping
  • Usage and token tracking including cache read/write tokens
  • Error classification: maps provider errors to ModelThrottledError, ContextWindowOverflowError, and ModelError

Any package that implements the LanguageModelV3 interface works with VercelModel. This includes both official Vercel AI SDK providers and community providers.

ProviderPackage
OpenAI@ai-sdk/openai
Amazon Bedrock@ai-sdk/amazon-bedrock
Anthropic@ai-sdk/anthropic
Google Generative AI@ai-sdk/google
Google Vertex@ai-sdk/google-vertex
Azure OpenAI@ai-sdk/azure
Mistral@ai-sdk/mistral
Cohere@ai-sdk/cohere
xAI Grok@ai-sdk/xai
DeepSeek@ai-sdk/deepseek
Groq@ai-sdk/groq
ProviderPackage
Ollamaai-sdk-ollama

If you see warnings about @ai-sdk/provider, install it explicitly:

Terminal window
npm install @ai-sdk/provider

Authentication is handled by the underlying Vercel provider package. Refer to the specific provider’s documentation for credential setup - for example, @ai-sdk/openai reads OPENAI_API_KEY from the environment, and @ai-sdk/amazon-bedrock uses the standard AWS credential chain.