Docs menu

Vercel AI SDK

Both wires. State: verified against the provider packages' source.

Install#

bash
npm install ai @ai-sdk/openai-compatible     # OpenAI wire
npm install ai @ai-sdk/anthropic             # Anthropic wire

Configure — OpenAI wire#

@ai-sdk/openai-compatible reads no environment variables, so baseURL and apiKey are always passed explicitly. includeUsage: true asks for usage on streamed responses (Sator sends it regardless, but the option keeps the SDK expecting it):

ts
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
import { generateText, streamText } from 'ai';

const sator = createOpenAICompatible({
  name: 'sator',
  baseURL: 'https://sator-api.princep.org/v1',
  apiKey: process.env.SATOR_API_KEY,
  includeUsage: true,
});

const { text, usage } = await generateText({
  model: sator('deepseek-v4-flash'),
  prompt: 'Say hi',
});
console.log(text, usage);

const result = streamText({ model: sator('deepseek-v4-flash'), prompt: 'Count to five' });
for await (const delta of result.textStream) process.stdout.write(delta);

Configure — Anthropic wire#

This is the one client that takes /v1 on the Anthropic wire. @ai-sdk/anthropic's default base URL is https://api.anthropic.com/v1 and it appends only /messages to whatever you give it, so a custom host needs the /v1 spelled out:

ts
import { createAnthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';

const sator = createAnthropic({
  baseURL: 'https://sator-api.princep.org/v1',
  apiKey: process.env.SATOR_API_KEY,
});

const { text, usage } = await generateText({
  model: sator('deepseek-v4-flash'),
  prompt: 'Say hi',
});
console.log(text, usage);

apiKey is sent as x-api-key, which Sator accepts.

Verify#

Either sample prints a short reply and a usage object with non-zero token counts. The request appears in your dashboard.

Troubleshooting#

  • 404 on the OpenAI wirebaseURL is missing its /v1.
  • 404 on the Anthropic wirebaseURL is missing its /v1 — yes, here it is needed; see above.
  • No usage on streams — set includeUsage: true on createOpenAICompatible.
  • @ai-sdk/openai instead of openai-compatible — works too: @ai-sdk/openai defaults to the Responses API, which Sator serves stateless. @ai-sdk/openai-compatible remains the simpler choice for the Chat wire.