Skip to main content
Prerequisite: You need an AI Gateway endpoint before continuing. Create one using the dashboard quickstart or follow the manual setup guide.
The Vercel AI SDK provides a unified interface for building AI applications. It works seamlessly with the ngrok AI Gateway, giving you provider failover, key rotation, and observability while using Vercel’s powerful streaming and UI components.

Installation

npm install ai @ai-sdk/openai

Basic usage

Point the OpenAI provider at your AI Gateway endpoint:
import { generateText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";

const openai = createOpenAI({
  baseURL: "https://your-ai-subdomain.ngrok.app/v1",
  apiKey: process.env.OPENAI_API_KEY,
});

const { text } = await generateText({
  model: openai("gpt-4o"),
  prompt: "What is the meaning of life?",
});

Streaming responses

The AI Gateway fully supports streaming. Use streamText for real-time responses:
import { streamText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";

const openai = createOpenAI({
  baseURL: "https://your-ai-subdomain.ngrok.app/v1",
  apiKey: process.env.OPENAI_API_KEY,
});

const result = streamText({
  model: openai("gpt-4o"),
  prompt: "Write a poem about AI gateways.",
});

for await (const textPart of result.textStream) {
  process.stdout.write(textPart);
}

Chat interface

Build chat applications with the useChat hook:
app/page.tsx
"use client";

import { useChat } from "ai/react";

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: "/api/chat",
  });

  return (
    <div>
      {messages.map((m) => (
        <div key={m.id}>
          {m.role}: {m.content}
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}
app/api/chat/route.ts
import { streamText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";

const openai = createOpenAI({
  baseURL: "https://your-ai-subdomain.ngrok.app/v1",
  apiKey: process.env.OPENAI_API_KEY,
});

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = streamText({
    model: openai("gpt-4o"),
    messages,
  });

  return result.toDataStreamResponse();
}

Using different providers

The AI Gateway routes based on the model name. Use provider prefixes to be explicit:
import { generateText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";

const gateway = createOpenAI({
  baseURL: "https://your-ai-subdomain.ngrok.app/v1",
  apiKey: "unused", // Gateway handles auth
});

// Use different providers through the same gateway
const openaiResult = await generateText({ model: gateway("openai:gpt-4o"), prompt: "Hello" });
const anthropicResult = await generateText({ model: gateway("anthropic:claude-3-5-sonnet-latest"), prompt: "Hello" });

Automatic model selection

Let the gateway choose the best model with ngrok/auto:
import { generateText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";

const gateway = createOpenAI({
  baseURL: "https://your-ai-subdomain.ngrok.app/v1",
  apiKey: "unused",
});

const { text } = await generateText({
  model: gateway("ngrok/auto"),  // Gateway selects based on your strategy
  prompt: "Explain quantum computing",
});
Configure your selection strategy in the Traffic Policy:
traffic-policy.yaml
on_http_request:
  - type: ai-gateway
    config:
      providers:
        - id: openai
          api_keys:
            - value: ${secrets.get('openai', 'api-key')}
        - id: anthropic
          api_keys:
            - value: ${secrets.get('anthropic', 'api-key')}
      model_selection:
        strategy:
          - "ai.models.sortBy(m, m.pricing.input)"  # Cheapest first

Environment variables

Set up your environment:
.env.local
# Your AI Gateway endpoint
AI_GATEWAY_URL=https://your-ai-subdomain.ngrok.app/v1

# Optional: API key if using passthrough mode
OPENAI_API_KEY=sk-...
const openai = createOpenAI({
  baseURL: process.env.AI_GATEWAY_URL,
  apiKey: process.env.OPENAI_API_KEY ?? "unused",
});

Tool calling

The AI Gateway supports function/tool calling:
import { generateText, tool } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
import { z } from "zod";

const openai = createOpenAI({
  baseURL: "https://your-ai-subdomain.ngrok.app/v1",
  apiKey: process.env.OPENAI_API_KEY,
});

const { text, toolCalls } = await generateText({
  model: openai("gpt-4o"),
  tools: {
    weather: tool({
      description: "Get the weather in a location",
      parameters: z.object({
        location: z.string().describe("The location to get weather for"),
      }),
      execute: async ({ location }) => {
        return { temperature: 72, condition: "sunny" };
      },
    }),
  },
  prompt: "What's the weather in San Francisco?",
});

Error handling

Handle errors gracefully:
import { generateText, APICallError } from "ai";

try {
  const { text } = await generateText({
    model: openai("gpt-4o"),
    prompt: "Hello",
  });
} catch (error) {
  if (error instanceof APICallError) {
    console.error("API Error:", error.message);
    console.error("Status:", error.statusCode);
  }
}
With the AI Gateway’s failover, many errors are handled automatically by retrying with different providers or keys.

Next steps