Vercel AI SDK

`generateText`, `streamText`, `generateObject`, `tool()` against EU models.

CleverRouter ships a Vercel AI SDK provider so you can stay inside the ai package's ergonomics — generateText, streamText, generateObject, tool() — and target EU-hosted models.

At a glance

Installbun add @cleverrouter/sdk@alpha ai @ai-sdk/openai-compatible
ImportcreateCleverRouterAI from @cleverrouter/sdk/ai-sdk
Default model in our examplesmistral/mistral-small-3.2

Setup

provider.ts
import { createCleverRouterAI } from '@cleverrouter/sdk/ai-sdk';

export const cr = createCleverRouterAI({
  apiKey: process.env.CLEVERROUTER_API_KEY!,
  // optional defaults applied to every call:
  provider: 'scaleway',
  strategy: 'fastest',
});

generateText

generate.ts
import { generateText } from 'ai';
import { cr } from './provider';

const { text, usage } = await generateText({
  model: cr('mistral/mistral-small-3.2'),
  prompt: 'Why pick an EU-hosted gateway?',
});

console.log(text);
console.log(usage); // { promptTokens, completionTokens, totalTokens }

streamText

stream.ts
import { streamText } from 'ai';
import { cr } from './provider';

const result = await streamText({
  model: cr('mistral/mistral-small-3.2'),
  prompt: 'Write a haiku about Berlin.',
});

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

For Next.js, return the stream straight back:

app/api/chat/route.ts
import { streamText } from 'ai';
import { cr } from '@/lib/cr';

export async function POST(req: Request) {
  const { messages } = await req.json();
  const result = await streamText({
    model: cr('mistral/mistral-small-3.2'),
    messages,
  });
  return result.toAIStreamResponse();
}

generateObject with Zod

generate-object.ts
import { generateObject } from 'ai';
import { z } from 'zod';
import { cr } from './provider';

const { object } = await generateObject({
  model: cr('mistral/mistral-small-3.2'),
  schema: z.object({
    city: z.string(),
    country: z.string(),
    population: z.number().int(),
  }),
  prompt: 'Tell me about Paris.',
});

console.log(object.city, object.country, object.population);

tool() calling

tools.ts
import { generateText, tool } from 'ai';
import { z } from 'zod';
import { cr } from './provider';

const { text } = await generateText({
  model: cr('mistral/mistral-large-2'),
  prompt: 'Weather in Paris and Berlin right now?',
  tools: {
    getWeather: tool({
      description: 'Current weather for a city.',
      parameters: z.object({
        city: z.string(),
        unit: z.enum(['c', 'f']).default('c'),
      }),
      execute: async ({ city, unit }) => {
        // Your data source.
        return { city, temp: 19, unit };
      },
    }),
  },
});

Per-call routing

The provider function (cr('model-id')) accepts options:

const { text } = await generateText({
  model: cr('mistral/mistral-small-3.2', {
    provider: 'tensorix',
    strategy: 'cheapest',
  }),
  prompt: 'Hi.',
});

Those options become X-CleverRouter-* headers under the hood.

Why a dedicated provider?

@ai-sdk/openai-compatible works on its own too, but the CleverRouter provider adds: typed strategy/provider options, automatic Retry-After handling, and SDK-version telemetry tags so you don't have to wire those manually.