Vercel AI SDK
Integrate nRouter with Vercel AI SDK in Next.js and React apps. Stream completions, utilize guardrails, and track costs while routing to any major AI model.
Last updated
The Vercel AI SDK provides a unified TypeScript interface for building interactive AI applications across Next.js, React, Svelte, and Node.js. Through its official @ai-sdk/openai provider adapter, you can point the Vercel AI SDK directly at nRouter (https://api.nrouter.ai/v1) without rewriting application logic.
By routing Vercel AI SDK requests through nRouter, full-stack applications immediately benefit from enterprise gateway capabilities: pre-execution prompt injection defense, server-side content moderation, semantic response caching, transparent model fallbacks, and real-time cost attribution down to the exact fraction of a cent.
Prerequisites & Installation
The Vercel AI SDK requires Node.js 18 or higher. It is optimized for the Next.js App Router but works in any modern JavaScript runtime supporting web standard fetch and streams.
Install the core SDK along with the OpenAI provider adapter and Zod for schema validation:
npm install ai @ai-sdk/openai zodIf you use pnpm, yarn, or bun:
pnpm add ai @ai-sdk/openai zod
# or
yarn add ai @ai-sdk/openai zod
# or
bun add ai @ai-sdk/openai zodSetup & Configuration
Store your nRouter virtual API key in your project's .env.local file. Never prefix your server-side API key with NEXT_PUBLIC_ to avoid exposing credentials to client web browsers:
# .env.local
NROUTER_API_KEY="sk-nrouter-your-virtual-key"Initializing the Provider
Create a shared provider instance that points to the nRouter gateway:
// lib/ai.ts
import { createOpenAI } from "@ai-sdk/openai";
export const nrouter = createOpenAI({
apiKey: process.env.NROUTER_API_KEY,
baseURL: "https://api.nrouter.ai/v1",
});Configuration Parameters
The createOpenAI factory accepts several parameters to tune network behavior and gateway directives:
| Parameter | Type | Default | Description |
|---|---|---|---|
baseURL | string | https://api.nrouter.ai/v1 | nRouter unified API endpoint. Must end with /v1. |
apiKey | string | process.env.OPENAI_API_KEY | Your nRouter virtual key (sk-nrouter-...). |
headers | Record<string, string> | {} | Custom headers sent on every request (e.g. x-nr-routing). |
fetch | typeof fetch | globalThis.fetch | Custom fetch implementation for corporate proxies or HTTP agents. |
// lib/ai-advanced.ts
import { createOpenAI } from "@ai-sdk/openai";
export const nrouter = createOpenAI({
apiKey: process.env.NROUTER_API_KEY,
baseURL: "https://api.nrouter.ai/v1",
headers: {
"x-nr-routing": "latency",
},
fetch: (url, options) => {
return fetch(url, {
...options,
// Configure keepalive and connection reuse
keepalive: true,
});
},
});Implementation Patterns
1. Generating Text (Route Handler)
For synchronous, non-streaming server tasks like summarization, classification, or background jobs:
// app/api/generate/route.ts
import { NextResponse } from "next/server";
import { generateText } from "ai";
import { nrouter } from "@/lib/ai";
export async function POST(req: Request) {
try {
const { prompt } = await req.json();
const { text, usage } = await generateText({
model: nrouter("claude-sonnet-4-5-20250929"),
prompt,
maxTokens: 1024,
});
return NextResponse.json({
text,
tokens: {
prompt: usage.promptTokens,
completion: usage.completionTokens,
},
});
} catch (error: any) {
return NextResponse.json(
{ error: error.message || "Generation failed" },
{ status: 500 }
);
}
}2. Real-time Streaming with streamText
Stream tokens to web clients with low time-to-first-token (TTFT) using Next.js App Router:
// app/api/chat/route.ts
import { streamText } from "ai";
import { nrouter } from "@/lib/ai";
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: nrouter("gpt-5.4-mini"),
messages,
});
return result.toDataStreamResponse();
}3. Client Interface with useChat
Connect your React user interface to the streaming route handler using the useChat hook:
// app/chat/page.tsx
"use client";
import { useChat } from "ai/react";
export default function ChatPage() {
const { messages, input, handleInputChange, handleSubmit, isLoading, error } = useChat({
api: "/api/chat",
});
return (
<div className="flex flex-col h-screen max-w-2xl mx-auto p-4">
<div className="flex-1 overflow-y-auto space-y-4 mb-4">
{messages.map((m) => (
<div
key={m.id}
className={`p-3 rounded-lg ${
m.role === "user" ? "bg-blue-600 text-white ml-auto" : "bg-zinc-800 text-zinc-100"
} max-w-[80%]`}
>
<div className="text-xs opacity-70 mb-1">{m.role}</div>
<div className="whitespace-pre-wrap">{m.content}</div>
</div>
))}
{isLoading && <div className="text-sm text-zinc-400">Streaming tokens...</div>}
{error && <div className="text-sm text-red-500">Error: {error.message}</div>}
</div>
<form onSubmit={handleSubmit} className="flex gap-2">
<input
value={input}
onChange={handleInputChange}
placeholder="Ask anything..."
className="flex-1 px-4 py-2 border rounded-md dark:bg-zinc-900"
/>
<button
type="submit"
disabled={isLoading}
className="px-4 py-2 bg-blue-600 text-white rounded-md disabled:opacity-50"
>
Send
</button>
</form>
</div>
);
}4. Tool Calling with Server-side Guardrail Defense
Define client tools using Zod. nRouter evaluates safety guardrails before the tool executes:
// app/api/tools/route.ts
import { generateText, tool } from "ai";
import { z } from "zod";
import { nrouter } from "@/lib/ai";
export async function POST(req: Request) {
const { query } = await req.json();
const { text } = await generateText({
model: nrouter("gpt-5.5"),
prompt: query,
tools: {
getWeather: tool({
description: "Retrieve real-time weather conditions for a given city.",
parameters: z.object({
city: z.string().describe("City name"),
unit: z.enum(["celsius", "fahrenheit"]).default("celsius"),
}),
execute: async ({ city, unit }) => {
return { temperature: unit === "celsius" ? 21 : 70, condition: "Sunny", city };
},
}),
},
});
return Response.json({ text });
}Production Best Practices
Deterministic Routing & Fallback Headers
Ensure high availability and cost control by setting routing preferences:
import { generateText } from "ai";
import { nrouter } from "@/lib/ai";
const { text } = await generateText({
// Specify fallback chain: tries primary model, falls back to secondary
model: nrouter("gpt-5.4-mini,claude-haiku-4-5-20251001"),
prompt: "Summarize this technical document...",
headers: {
"x-nr-routing": "latency",
},
});x-nr-routing: latency: Directs requests to the fastest operational cloud endpoint.x-nr-routing: cost: Selects the lowest-cost provider endpoint.- Model Fallback List: In case of upstream provider outages, nRouter automatically cascades down your comma-separated list of models.
Per-Request Gateway Overrides
Pass nRouter-specific flags via the body option on generateText or streamText:
const result = await streamText({
model: nrouter("gpt-5.5"),
messages,
body: {
nrouter_prompt_template_id: "tmpl_support_triage_v2",
nrouter_prompt_variables: { locale: "en-US", tier: "enterprise" },
nrouter_cache: true,
},
});Runtime Selection in Next.js
You can deploy route handlers to either the Edge Runtime or Node.js Runtime. When operating in high-concurrency environments, Edge Runtime delivers minimal cold starts:
// app/api/chat/route.ts
export const runtime = "edge"; // or 'nodejs' (default)Troubleshooting & Error Handling
nRouter returns standard HTTP status codes. Inspect the error response when calls fail:
Common Error Codes
| Status | Error Code | Root Cause | Solution |
|---|---|---|---|
400 | guardrail_blocked | Prompt injection, PII, or forbidden keywords detected | Inspect incoming messages; adjust guardrail thresholds in the nRouter dashboard. |
401 | authentication_error | Missing or invalid NROUTER_API_KEY | Verify .env.local contains a valid virtual key starting with sk-nrouter-. |
402 | insufficient_credits | Zero credit balance or virtual key budget reached | Refill organization credits or increase key spend ceilings. |
429 | rate_limit_exceeded | Account RPM/TPM ceiling hit | Exponential backoff on retries; request quota increases in settings. |
500 / 503 | service_unavailable | Upstream model provider outage | Add secondary fallback models in the model string. |
Error Catching in Route Handlers
// app/api/chat/route.ts
import { streamText } from "ai";
import { nrouter } from "@/lib/ai";
export async function POST(req: Request) {
try {
const { messages } = await req.json();
const result = streamText({
model: nrouter("gpt-5.4-mini"),
messages,
onError({ error }) {
console.error("Stream generation error:", error);
},
});
return result.toDataStreamResponse();
} catch (error: any) {
if (error.status === 400 && error.message?.includes("guardrail")) {
return new Response("Request flagged by organization safety policy", { status: 400 });
}
if (error.status === 402) {
return new Response("Billing budget exceeded. Please contact admin.", { status: 402 });
}
return new Response(error.message || "Internal server error", { status: 500 });
}
}Next Steps
- Node.js SDK Guide — Official native TypeScript SDK with conversation memory
- Python & LangChain — Multi-agent and chain workflows in Python
- Chat Completions API — Direct HTTP wire specifications
LlamaIndex
Connect LlamaIndex to nRouter for retrieval-augmented generation (RAG) and agent workflows. Configure LLM and embedding endpoints with enterprise guardrails.
CrewAI
Connect CrewAI multi-agent systems to nRouter using OpenAI-compatible endpoints. Enable resilient model routing, automated fallbacks, and usage monitoring.