- OpenAIUpdated
- OpenAI: AdvancedNew
- AnthropicUpdated
- Anthropic: AdvancedNew
- Google GeminiUpdated
- Google Gemini: AdvancedNew
- Google Vertex AIUpdated
- OllamaUpdated
- Grok (xAI)Updated
- GroqUpdated
- MistralUpdated
- CohereUpdated
- TypeSafeUpdated
- OllayaUpdated
- ElevenLabsUpdated
- fal.aiUpdated
- ReactorUpdated
- World LabsUpdated
- OpenRouter AdapterUpdated
- OpenRouter: AdvancedNew
- Perplexity SearchUpdated
- Vercel AI GatewayUpdated
- Lovable AI GatewayUpdated
- OpenAI-CompatibleUpdated
- OpenAI-Compatible: AdvancedNew
- LLM GatewayUpdated
- CloudflareUpdated
- Neon AI GatewayNew
- Claude CodeUpdated
- CodexUpdated
- OpenCodeUpdated
- Grok BuildUpdated
- ACP-CompatibleUpdated
- Amazon BedrockUpdated
- BytePlusUpdated
- BytePlus: AdvancedNew
Cloudflare
@cloudflare/tanstack-ai is the community Cloudflare package. It provides:
- Workers AI models, which run on the Cloudflare network.
- AI Gateway routing to OpenAI, Anthropic, Gemini, Grok, and OpenRouter, with caching, rate limits, and one bill.
Cloudflare maintains this package. TanStack AI also has its own Cloudflare adapter, @tanstack/ai-cloudflare. See the Cloudflare adapter page.
1. Install#
npm i @cloudflare/tanstack-ai @tanstack/aipnpm add @cloudflare/tanstack-ai @tanstack/aiyarn add @cloudflare/tanstack-ai @tanstack/aibun add @cloudflare/tanstack-ai @tanstack/ai2. Set up access#
Inside a Cloudflare Worker, use the env.AI binding. You need no API key.
Outside a Worker, use the REST credentials. Put them in the environment of your server:
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_API_KEY=your-api-key3. Stream a chat#
import { chat, toHttpResponse } from "@tanstack/ai";
import { createWorkersAiChat } from "@cloudflare/tanstack-ai";
import { env } from "./env";
const adapter = createWorkersAiChat(
"@cf/meta/llama-4-scout-17b-16e-instruct",
{ binding: env.AI },
);
const response = chat({
adapter,
stream: true,
messages: [{ role: "user", content: "Hello!" }],
threadId: "thread-1",
});
const httpResponse = toHttpResponse(response);Return httpResponse from your Worker. Outside a Worker, pass the account ID and the API key:
import { createWorkersAiChat } from "@cloudflare/tanstack-ai";
const adapter = createWorkersAiChat(
"@cf/meta/llama-4-scout-17b-16e-instruct",
{
accountId: "your-account-id",
apiKey: "your-api-key",
},
);Images#
import { generateImage } from "@tanstack/ai";
import { createWorkersAiImage } from "@cloudflare/tanstack-ai";
import { env } from "./env";
const adapter = createWorkersAiImage(
"@cf/stabilityai/stable-diffusion-xl-base-1.0",
{ binding: env.AI },
);
const result = await generateImage({
adapter,
prompt: "a cat in space",
threadId: "thread-1",
});
console.log(result.images[0]?.b64Json);Transcription#
import { generateTranscription } from "@tanstack/ai";
import { createWorkersAiTranscription } from "@cloudflare/tanstack-ai";
import { env, audioArrayBuffer } from "./env";
const adapter = createWorkersAiTranscription(
"@cf/openai/whisper-large-v3-turbo",
{ binding: env.AI },
);
const result = await generateTranscription({
adapter,
audio: audioArrayBuffer,
threadId: "thread-1",
});
console.log(result.text);
console.log(result.segments);Transcription models: @cf/openai/whisper, @cf/openai/whisper-tiny-en, @cf/openai/whisper-large-v3-turbo, and @cf/deepgram/nova-3.
Speech#
import { generateSpeech } from "@tanstack/ai";
import { createWorkersAiTts } from "@cloudflare/tanstack-ai";
import { env } from "./env";
const adapter = createWorkersAiTts("@cf/deepgram/aura-2-en", {
binding: env.AI,
});
const result = await generateSpeech({
adapter,
text: "Hello world",
threadId: "thread-1",
});
console.log(result.audio);Summarization#
import { summarize, type AnySummarizeAdapter } from "@tanstack/ai";
import { createWorkersAiSummarize } from "@cloudflare/tanstack-ai";
import { env } from "./env";
const adapter: AnySummarizeAdapter = createWorkersAiSummarize("@cf/facebook/bart-large-cnn", {
binding: env.AI,
});
const result = await summarize({
adapter,
text: "Long article here...",
threadId: "thread-1",
});
console.log(result.summary);AI Gateway#
Send requests through AI Gateway to get caching, rate limits, and one bill. It works for Workers AI and for other providers.
Workers AI through the gateway:
import { createWorkersAiChat } from "@cloudflare/tanstack-ai";
import { env } from "./env";
const adapter = createWorkersAiChat(
"@cf/meta/llama-4-scout-17b-16e-instruct",
{
binding: env.AI.gateway("my-gateway-id"),
apiKey: env.WORKERS_AI_TOKEN,
},
);Other providers through the gateway. For other providers, also install their TanStack AI packages:
npm i @tanstack/ai-openai @tanstack/ai-anthropic @tanstack/ai-gemini @tanstack/ai-grok @tanstack/ai-openrouterpnpm add @tanstack/ai-openai @tanstack/ai-anthropic @tanstack/ai-gemini @tanstack/ai-grok @tanstack/ai-openrouteryarn add @tanstack/ai-openai @tanstack/ai-anthropic @tanstack/ai-gemini @tanstack/ai-grok @tanstack/ai-openrouterbun add @tanstack/ai-openai @tanstack/ai-anthropic @tanstack/ai-gemini @tanstack/ai-grok @tanstack/ai-openrouterInstall only the providers that you use. In a Worker, use the binding:
import {
createOpenAiChat,
createAnthropicChat,
createGeminiChat,
createGrokChat,
createOpenRouterChat,
} from "@cloudflare/tanstack-ai";
import { env } from "./env";
const openai = createOpenAiChat("gpt-4o", {
binding: env.AI.gateway("my-gateway-id"),
});
const anthropic = createAnthropicChat("claude-sonnet-4-5", {
binding: env.AI.gateway("my-gateway-id"),
});
const grok = createGrokChat("grok-4.3", {
binding: env.AI.gateway("my-gateway-id"),
});
const openrouter = createOpenRouterChat("openai/gpt-4o", {
binding: env.AI.gateway("my-gateway-id"),
});Outside a Worker, use the credentials:
import { createOpenAiChat } from "@cloudflare/tanstack-ai";
const adapter = createOpenAiChat("gpt-4o", {
accountId: "your-account-id",
gatewayId: "your-gateway-id",
cfApiKey: "your-cf-api-key",
apiKey: "provider-api-key",
});Cache options#
The binding mode and the credentials mode both take cache options:
import { createOpenAiChat } from "@cloudflare/tanstack-ai";
import { env } from "./env";
const adapter = createOpenAiChat("gpt-4o", {
binding: env.AI.gateway("my-gateway-id"),
skipCache: false,
cacheTtl: 3600,
customCacheKey: "my-key",
metadata: { user: "test" },
});Models and options#
Configuration modes#
Workers AI has four modes:
| Mode | Config | What it does |
|---|---|---|
| Plain binding | { binding: env.AI } | Direct access, no gateway. |
| Plain REST | { accountId, apiKey } | REST API, no gateway. |
| Gateway binding | { binding: env.AI.gateway(id) } | Through AI Gateway, with the binding. |
| Gateway REST | { accountId, gatewayId, ... } | Through AI Gateway, with REST. |
Other providers (OpenAI, Anthropic, Gemini, Grok, OpenRouter) work only in the gateway modes.
Capabilities#
| Provider | Chat | Summarize | Images | Transcription | Speech |
|---|---|---|---|---|---|
| Workers AI | Yes | Yes | Yes | Yes | Yes |
| OpenAI | Yes | Yes | Yes | Yes | Yes |
| Anthropic | Yes | Yes | No | No | No |
| Gemini | Yes | Yes | Yes | No | Yes |
| Grok | Yes | Yes | Yes | No | No |
| OpenRouter | Yes | Yes | Yes | No | No |
Workers AI factories#
- createWorkersAiChat(model, config): chat and structured output.
- createWorkersAiImage(model, config): images.
- createWorkersAiTranscription(model, config): speech to text (Whisper, Deepgram).
- createWorkersAiTts(model, config): text to speech (Deepgram Aura).
- createWorkersAiSummarize(model, config): summarization (BART-large-CNN).
Gateway provider factories#
- OpenAI: createOpenAiChat(model, config), createOpenAiSummarize, createOpenAiImage, createOpenAiTranscription, createOpenAiTts.
- Anthropic: createAnthropicChat(model, config), createAnthropicSummarize.
- Gemini: createGeminiChat(model, config), createGeminiSummarize, createGeminiImage, createGeminiTts.
- Grok: createGrokChat(model, config), createGrokSummarize, createGrokImage.
- OpenRouter: createOpenRouterChat(model, config), createOpenRouterSummarize, createOpenRouterImage.
The source and the issues are on GitHub.