Skip to main content
The Vercel AI Chatbot supports multiple AI model providers through Vercel AI Gateway. You can add custom models, configure model-specific features, and create specialized models for different tasks.

Model configuration

All available chat models are defined in lib/ai/models.ts:
lib/ai/models.ts
export const DEFAULT_CHAT_MODEL = "openai/gpt-4.1-mini";

export type ChatModel = {
  id: string;
  name: string;
  provider: string;
  description: string;
};

export const chatModels: ChatModel[] = [
  // Anthropic
  {
    id: "anthropic/claude-haiku-4.5",
    name: "Claude Haiku 4.5",
    provider: "anthropic",
    description: "Fast and affordable, great for everyday tasks",
  },
  // OpenAI
  {
    id: "openai/gpt-4.1-mini",
    name: "GPT-4.1 Mini",
    provider: "openai",
    description: "Fast and cost-effective for simple tasks",
  },
  // Google
  {
    id: "google/gemini-2.5-flash-lite",
    name: "Gemini 2.5 Flash Lite",
    provider: "google",
    description: "Ultra fast and affordable",
  },
  // Reasoning models
  {
    id: "anthropic/claude-3.7-sonnet-thinking",
    name: "Claude 3.7 Sonnet",
    provider: "reasoning",
    description: "Extended thinking for complex problems",
  },
];

Model ID format

Model IDs follow the Vercel AI Gateway format: provider/model-name
"anthropic/claude-haiku-4.5"
"anthropic/claude-3.7-sonnet-thinking"

Adding a custom model

1

Add model to configuration

Add your model to the chatModels array in lib/ai/models.ts:
lib/ai/models.ts
export const chatModels: ChatModel[] = [
  // ... existing models
  {
    id: "openai/gpt-5-turbo",
    name: "GPT-5 Turbo",
    provider: "openai",
    description: "Latest OpenAI model with improved reasoning",
  },
];
2

Verify model availability

The model will automatically appear in the model selector UI. The allowedModelIds Set is generated from the chatModels array:
lib/ai/models.ts
export const allowedModelIds = new Set(chatModels.map((m) => m.id));
3

Configure provider settings (optional)

If your model requires special configuration, modify lib/ai/providers.ts:
lib/ai/providers.ts
export function getLanguageModel(modelId: string) {
  // Add custom logic for your model
  if (modelId === "openai/gpt-5-turbo") {
    return gateway.languageModel(modelId, {
      // Custom configuration
    });
  }
  
  return gateway.languageModel(modelId);
}

Model providers

The chatbot uses Vercel AI Gateway to route requests to different model providers:
lib/ai/providers.ts
import { gateway } from "@ai-sdk/gateway";
import {
  customProvider,
  extractReasoningMiddleware,
  wrapLanguageModel,
} from "ai";

export function getLanguageModel(modelId: string) {
  const isReasoningModel =
    modelId.endsWith("-thinking") ||
    (modelId.includes("reasoning") && !modelId.includes("non-reasoning"));

  if (isReasoningModel) {
    const gatewayModelId = modelId.replace(/-thinking$/, "");
    
    return wrapLanguageModel({
      model: gateway.languageModel(gatewayModelId),
      middleware: extractReasoningMiddleware({ tagName: "thinking" }),
    });
  }

  return gateway.languageModel(modelId);
}

Reasoning models

Models with extended thinking capabilities are detected automatically and configured with reasoning middleware:
  • Models ending in -thinking
  • Models containing reasoning (but not non-reasoning)
These models extract reasoning traces with the <thinking> tag.

Specialized models

The chatbot uses different models for specific tasks:

Title generation

lib/ai/providers.ts
export function getTitleModel() {
  return gateway.languageModel("google/gemini-2.5-flash-lite");
}
Used in app/(chat)/actions.ts to generate chat titles from user messages.

Artifact generation

lib/ai/providers.ts
export function getArtifactModel() {
  return gateway.languageModel("anthropic/claude-haiku-4.5");
}
Used for creating and updating documents, generating suggestions, and other artifact-related tasks.
Use faster, more affordable models for simple tasks like title generation and suggestions to reduce costs while maintaining quality.

Model grouping

Models are grouped by provider for display in the UI:
lib/ai/models.ts
export const modelsByProvider = chatModels.reduce(
  (acc, model) => {
    if (!acc[model.provider]) {
      acc[model.provider] = [];
    }
    acc[model.provider].push(model);
    return acc;
  },
  {} as Record<string, ChatModel[]>
);
This creates groups like:
  • anthropic: Claude models
  • openai: GPT models
  • google: Gemini models
  • reasoning: Extended thinking models
  • xai: Grok models

Reasoning model configuration

Reasoning models receive special configuration in the chat API:
app/(chat)/api/chat/route.ts
const isReasoningModel =
  selectedChatModel.endsWith("-thinking") ||
  (selectedChatModel.includes("reasoning") &&
    !selectedChatModel.includes("non-reasoning"));

const result = streamText({
  model: getLanguageModel(selectedChatModel),
  system: systemPrompt({ selectedChatModel, requestHints }),
  messages: modelMessages,
  experimental_activeTools: isReasoningModel
    ? [] // Disable tools for reasoning models
    : ["getWeather", "createDocument", "updateDocument", "requestSuggestions"],
  providerOptions: isReasoningModel
    ? {
        anthropic: {
          thinking: { type: "enabled", budgetTokens: 10_000 },
        },
      }
    : undefined,
});

Reasoning configuration options

Budget tokens

Set the maximum tokens allocated for reasoning traces (default: 10,000)

Tool availability

Tools are disabled for reasoning models to prevent distraction during deep analysis

Reasoning extraction

The extractReasoningMiddleware extracts <thinking> tags and exposes them separately from the final response

Test environment models

For testing, you can use mock models:
lib/ai/providers.ts
export const myProvider = isTestEnvironment
  ? (() => {
      const {
        artifactModel,
        chatModel,
        reasoningModel,
        titleModel,
      } = require("./models.mock");
      return customProvider({
        languageModels: {
          "chat-model": chatModel,
          "chat-model-reasoning": reasoningModel,
          "title-model": titleModel,
          "artifact-model": artifactModel,
        },
      });
    })()
  : null;

Provider-specific features

Anthropic extended thinking

Claude models with -thinking suffix support extended reasoning:
const result = streamText({
  model: getLanguageModel("anthropic/claude-3.7-sonnet-thinking"),
  providerOptions: {
    anthropic: {
      thinking: {
        type: "enabled",
        budgetTokens: 10_000, // Adjust based on complexity
      },
    },
  },
});

Streaming reasoning to UI

Reasoning traces are streamed separately from the main response:
app/(chat)/api/chat/route.ts
dataStream.merge(
  result.toUIMessageStream({ sendReasoning: isReasoningModel })
);
The UI displays reasoning in a collapsible section using the MessageReasoning component.

Model selection UI

Users can switch models using the ModelSelector component:
components/ai-elements/model-selector.tsx
import { chatModels, modelsByProvider } from "@/lib/ai/models";

export function ModelSelector() {
  return (
    <Select>
      {Object.entries(modelsByProvider).map(([provider, models]) => (
        <SelectGroup key={provider}>
          <SelectLabel>{provider}</SelectLabel>
          {models.map((model) => (
            <SelectItem key={model.id} value={model.id}>
              {model.name}
              <span className="text-muted-foreground">{model.description}</span>
            </SelectItem>
          ))}
        </SelectGroup>
      ))}
    </Select>
  );
}

Best practices

Choose appropriate models: Use smaller, faster models (like Haiku or Flash) for simple tasks and larger models (like Sonnet or Pro) for complex reasoning.
Cost optimization: Configure different models for different use cases:
  • Title generation: Fast, cheap models
  • Document creation: Balanced models
  • Complex reasoning: Premium models
Test thoroughly: Always test new models in a development environment before deploying to production. Different models may have different capabilities and limitations.
Monitor your usage in the Vercel AI Gateway dashboard to track costs and performance across different models.

Build docs developers (and LLMs) love