This guide shows you how to route the Vercel AI SDK through the to11 gateway using the OpenAI provider with a custom base URL.
These examples use the AI SDK 5+ API (inputSchema, message.parts, toUIMessageStreamResponse). On AI SDK 4 the option and method names differ.
Installation
npm install ai@^5 @ai-sdk/openai @ai-sdk/react
Configuration
Create an OpenAI provider instance pointing at the to11 gateway:
import { createOpenAI } from "@ai-sdk/openai";
const to11 = createOpenAI({
baseURL: "https://gw.to11.ai/v1",
apiKey: "<your OpenAI API key>", // provider credential, forwarded upstream
headers: {
"x-to11-authorization": "Bearer <your to11 API key>", // to11 auth — Settings → API keys
"x-to11-project-id": "<your project id>",
},
});
Generate text
import { generateText } from "ai";
const { text } = await generateText({
model: to11("gpt-4o"),
prompt: "Hello from to11!",
});
console.log(text);
Stream text
import { streamText } from "ai";
const result = streamText({
model: to11("gpt-4o"),
prompt: "Count to 10",
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}
Use with Next.js
In a Next.js route handler:
// app/api/chat/route.ts
import { streamText, convertToModelMessages, type UIMessage } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
const to11 = createOpenAI({
baseURL: "https://gw.to11.ai/v1",
apiKey: process.env.OPENAI_API_KEY!,
headers: {
"x-to11-authorization": `Bearer ${process.env.TO11_API_KEY!}`,
"x-to11-project-id": process.env.TO11_PROJECT_ID!,
},
});
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: to11("gpt-4o"),
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse();
}
On the client side, the useChat hook posts to /api/chat by default. Manage the input yourself and send messages with sendMessage:
// components/chat.tsx
"use client";
import { useChat } from "@ai-sdk/react";
import { useState } from "react";
export default 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) =>
part.type === "text" ? <span key={i}>{part.text}</span> : null,
)}
</div>
))}
<form
onSubmit={(e) => {
e.preventDefault();
sendMessage({ text: input });
setInput("");
}}
>
<input value={input} onChange={(e) => setInput(e.target.value)} />
</form>
</div>
);
}
The to11 gateway routes based on the model field. You can target Anthropic models through the same OpenAI provider:
const { text } = await generateText({
model: to11("claude-sonnet-4-6"),
prompt: "Hello from to11!",
});
The gateway translates the OpenAI-format request to Anthropic format and returns the response in OpenAI format, so the Vercel AI SDK works without changes.
import { generateText, tool } from "ai";
import { z } from "zod";
const { text, toolCalls } = await generateText({
model: to11("gpt-4o"),
prompt: "What's the weather in Paris?",
tools: {
getWeather: tool({
description: "Get current weather for a location",
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
return { temperature: 18, unit: "celsius", location };
},
}),
},
});