Skip to content
Fabrik UI

Providers

Connect to OpenAI, Anthropic, Google, or any LLM via AI SDK

Providers are server-side adapters that translate between Fabrik's stream protocol and a specific LLM API. Each provider reads its API key from environment variables by default.

The AI SDK adapter is the primary way to connect Fabrik to any LLM. It supports 53+ models through the unified AI SDK interface — OpenAI, Anthropic, Google, Groq, Mistral, Cohere, and more.

pnpm add @fabrik-sdk/ui ai @ai-sdk/google zod motion

Google Gemini

app/api/chat/route.ts
import { aiSdk } from "@fabrik-sdk/ui/ai-sdk"
import { handler } from "@fabrik-sdk/ui/server"
import { google } from "@ai-sdk/google"

export const POST = handler({
  provider: aiSdk({ model: google("gemini-3-flash-preview") }),
})
.env.local
GOOGLE_GENERATIVE_AI_API_KEY=AI...

OpenAI

pnpm add @ai-sdk/openai
app/api/chat/route.ts
import { aiSdk } from "@fabrik-sdk/ui/ai-sdk"
import { handler } from "@fabrik-sdk/ui/server"
import { openai } from "@ai-sdk/openai"

export const POST = handler({
  provider: aiSdk({ model: openai("gpt-4o") }),
})
.env.local
OPENAI_API_KEY=sk-...

Anthropic

pnpm add @ai-sdk/anthropic
app/api/chat/route.ts
import { aiSdk } from "@fabrik-sdk/ui/ai-sdk"
import { handler } from "@fabrik-sdk/ui/server"
import { anthropic } from "@ai-sdk/anthropic"

export const POST = handler({
  provider: aiSdk({ model: anthropic("claude-sonnet-4-20250514") }),
})
.env.local
ANTHROPIC_API_KEY=sk-ant-...

AI SDK environment variables

AI SDK packageEnvironment variable
@ai-sdk/openaiOPENAI_API_KEY
@ai-sdk/anthropicANTHROPIC_API_KEY
@ai-sdk/googleGOOGLE_GENERATIVE_AI_API_KEY

The AI SDK adapter wraps any AI SDK LanguageModel, giving you access to providers like Groq, Mistral, Cohere, and more. See the AI SDK docs for the full list of supported providers.

Lightweight Alternatives

Fabrik also ships native adapters that talk directly to each LLM API without the AI SDK dependency. These are useful when you want a minimal dependency footprint.

OpenAI (native)

app/api/chat/route.ts
import { openai } from "@fabrik-sdk/ui/openai"
import { handler } from "@fabrik-sdk/ui/server"

export const POST = handler({
  provider: openai({ model: "gpt-4o" }),
})
.env.local
OPENAI_API_KEY=sk-...

Options

OptionTypeDefault
modelstring"gpt-4o"
apiKeystringprocess.env.OPENAI_API_KEY
baseUrlstringOpenAI default

Anthropic (native)

app/api/chat/route.ts
import { anthropic } from "@fabrik-sdk/ui/anthropic"
import { handler } from "@fabrik-sdk/ui/server"

export const POST = handler({
  provider: anthropic({ model: "claude-sonnet-4-20250514" }),
})
.env.local
ANTHROPIC_API_KEY=sk-ant-...

Options

OptionTypeDefault
modelstring"claude-sonnet-4-20250514"
apiKeystringprocess.env.ANTHROPIC_API_KEY

Google Gemini (native)

app/api/chat/route.ts
import { google } from "@fabrik-sdk/ui/google"
import { handler } from "@fabrik-sdk/ui/server"

export const POST = handler({
  provider: google({ model: "gemini-2.0-flash" }),
})
.env.local
GOOGLE_AI_API_KEY=AI...

Options

OptionTypeDefault
modelstring"gemini-2.0-flash"
apiKeystringprocess.env.GOOGLE_AI_API_KEY

Custom provider

Build your own provider by implementing the Provider interface:

lib/my-provider.ts
import type { Provider, StreamOptions, StreamEvent } from "@fabrik-sdk/ui"

export function myProvider(): Provider {
  return {
    name: "my-provider",
    async *stream(options: StreamOptions): AsyncIterable<StreamEvent> {
      yield { type: "start", runId: "run-1" }
      yield { type: "text", delta: "Hello from custom provider!" }
      yield { type: "done" }
    },
  }
}

A provider must yield StreamEvent objects. At minimum: start, then content events, then done.

Client-side adapter

On the client, use the server() adapter to connect to your API route:

app/page.tsx
import { Fabrik, Chat } from "@fabrik-sdk/ui/react"
import { server } from "@fabrik-sdk/ui/server"

const provider = server({ url: "/api/chat" })

This adapter POSTs messages and reads the SSE response stream. It works with any of the server-side providers above — the client code never changes when you switch LLMs.

On this page