The Grok text and summarization adapters provide access to xAI's Responses API for grok-4.3 and grok-build-0.1, plus Grok Imagine image generation and Grok Imagine video generation.
npm install @tanstack/ai-groknpm install @tanstack/ai-grokimport { chat } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages: [{ role: "user", content: "Hello!" }],
});import { chat } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages: [{ role: "user", content: "Hello!" }],
});import { chat } from "@tanstack/ai";
import { createGrokText } from "@tanstack/ai-grok";
const adapter = createGrokText("grok-build-0.1", process.env.XAI_API_KEY!);
const stream = chat({
adapter,
messages: [{ role: "user", content: "Hello!" }],
});import { chat } from "@tanstack/ai";
import { createGrokText } from "@tanstack/ai-grok";
const adapter = createGrokText("grok-build-0.1", process.env.XAI_API_KEY!);
const stream = chat({
adapter,
messages: [{ role: "user", content: "Hello!" }],
});import { createGrokText, type GrokTextConfig } from "@tanstack/ai-grok";
const config: Omit<GrokTextConfig, "apiKey"> = {
baseURL: "https://api.x.ai/v1", // Optional, this is the default
};
const adapter = createGrokText("grok-build-0.1", process.env.XAI_API_KEY!, config);import { createGrokText, type GrokTextConfig } from "@tanstack/ai-grok";
const config: Omit<GrokTextConfig, "apiKey"> = {
baseURL: "https://api.x.ai/v1", // Optional, this is the default
};
const adapter = createGrokText("grok-build-0.1", process.env.XAI_API_KEY!, config);import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages,
});
return toServerSentEventsResponse(stream);
}import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages,
});
return toServerSentEventsResponse(stream);
}import { chat, toServerSentEventsResponse, toolDefinition } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
import { z } from "zod";
const getWeatherDef = toolDefinition({
name: "get_weather",
description: "Get the current weather",
inputSchema: z.object({
location: z.string(),
}),
});
const getWeather = getWeatherDef.server(async ({ location }) => {
// Fetch weather data
return { temperature: 72, conditions: "sunny" };
});
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages,
tools: [getWeather],
});
return toServerSentEventsResponse(stream);
}import { chat, toServerSentEventsResponse, toolDefinition } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
import { z } from "zod";
const getWeatherDef = toolDefinition({
name: "get_weather",
description: "Get the current weather",
inputSchema: z.object({
location: z.string(),
}),
});
const getWeather = getWeatherDef.server(async ({ location }) => {
// Fetch weather data
return { temperature: 72, conditions: "sunny" };
});
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages,
tools: [getWeather],
});
return toServerSentEventsResponse(stream);
}Grok supports xAI Responses API options. Sampling parameters live here too — temperature, top_p, and max_output_tokens — rather than as root-level props on chat():
import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages,
modelOptions: {
temperature: 0.7,
top_p: 0.9,
max_output_tokens: 1024,
store: false,
include: ["reasoning.encrypted_content"],
},
});
return toServerSentEventsResponse(stream);
}import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { grokText } from "@tanstack/ai-grok";
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = chat({
adapter: grokText("grok-build-0.1"),
messages,
modelOptions: {
temperature: 0.7,
top_p: 0.9,
max_output_tokens: 1024,
store: false,
include: ["reasoning.encrypted_content"],
},
});
return toServerSentEventsResponse(stream);
}If you previously passed temperature / topP / maxTokens at the root of chat(), see Moving Sampling Options into modelOptions.
Summarize long text content:
import { summarize } from "@tanstack/ai";
import { grokSummarize } from "@tanstack/ai-grok";
const result = await summarize({
adapter: grokSummarize("grok-4.3"),
text: "Your long text to summarize...",
maxLength: 100,
style: "concise", // "concise" | "bullet-points" | "paragraph"
});
console.log(result.summary);import { summarize } from "@tanstack/ai";
import { grokSummarize } from "@tanstack/ai-grok";
const result = await summarize({
adapter: grokSummarize("grok-4.3"),
text: "Your long text to summarize...",
maxLength: 100,
style: "concise", // "concise" | "bullet-points" | "paragraph"
});
console.log(result.summary);Generate images with Grok 2 Image:
import { generateImage } from "@tanstack/ai";
import { grokImage } from "@tanstack/ai-grok";
const result = await generateImage({
adapter: grokImage("grok-2-image-1212"),
prompt: "A futuristic cityscape at sunset",
numberOfImages: 1,
});
console.log(result.images);import { generateImage } from "@tanstack/ai";
import { grokImage } from "@tanstack/ai-grok";
const result = await generateImage({
adapter: grokImage("grok-2-image-1212"),
prompt: "A futuristic cityscape at sunset",
numberOfImages: 1,
});
console.log(result.images);The grok-imagine models (grok-imagine-image, grok-imagine-image-quality) are aspect-ratio sized — size takes an aspectRatio_resolution template like "16:9_2k" (the _2k suffix is optional):
import { generateImage } from "@tanstack/ai";
import { grokImage } from "@tanstack/ai-grok";
const result = await generateImage({
adapter: grokImage("grok-imagine-image"),
prompt: "A futuristic cityscape at sunset",
size: "16:9_2k",
});import { generateImage } from "@tanstack/ai";
import { grokImage } from "@tanstack/ai-grok";
const result = await generateImage({
adapter: grokImage("grok-imagine-image"),
prompt: "A futuristic cityscape at sunset",
size: "16:9_2k",
});The grok-imagine models accept image prompt parts for image-conditioned generation via xAI's /v1/images/edits endpoint — up to 3 source images, addressed by xAI in the order they appear in the prompt. Per xAI's docs there is no in-prompt referencing syntax; write the prompt naturally and your text is sent verbatim:
import { generateImage } from "@tanstack/ai";
import { grokImage } from "@tanstack/ai-grok";
const result = await generateImage({
adapter: grokImage("grok-imagine-image"),
prompt: [
{
type: "text",
content: "Render the product in the style of the second image",
},
{
type: "image",
source: { type: "url", value: "https://example.com/product.png" },
},
{
type: "image",
source: { type: "url", value: "https://example.com/style.png" },
},
],
});import { generateImage } from "@tanstack/ai";
import { grokImage } from "@tanstack/ai-grok";
const result = await generateImage({
adapter: grokImage("grok-imagine-image"),
prompt: [
{
type: "text",
content: "Render the product in the style of the second image",
},
{
type: "image",
source: { type: "url", value: "https://example.com/product.png" },
},
{
type: "image",
source: { type: "url", value: "https://example.com/style.png" },
},
],
});URL sources are fetched by xAI's servers, so they must be publicly reachable; use a data source for private images. grok-2-image-1212 is text-to-image only — image prompt parts are a compile-time type error and throw at runtime.
Generate short video clips (1–15 seconds, with audio) with the Grok Imagine video models via xAI's asynchronous jobs/polling API.
Available models:
Text-to-video with the base grok-imagine-video model:
import { generateVideo, getVideoJobStatus } from "@tanstack/ai";
import { grokVideo } from "@tanstack/ai-grok";
const adapter = grokVideo("grok-imagine-video");
// 1. Create the job
const { jobId } = await generateVideo({
adapter,
prompt: "A red panda balancing on a bamboo stalk in the rain",
size: "16:9_720p", // "aspectRatio" or "aspectRatio_resolution"
duration: 5, // integer seconds, 1–15
});
// 2. Poll until complete, then read the video URL
let status = await getVideoJobStatus({ adapter, jobId });
while (status.status !== "completed" && status.status !== "failed") {
await new Promise((r) => setTimeout(r, 5000));
status = await getVideoJobStatus({ adapter, jobId });
}
console.log(status.url); // hosted .mp4 URLimport { generateVideo, getVideoJobStatus } from "@tanstack/ai";
import { grokVideo } from "@tanstack/ai-grok";
const adapter = grokVideo("grok-imagine-video");
// 1. Create the job
const { jobId } = await generateVideo({
adapter,
prompt: "A red panda balancing on a bamboo stalk in the rain",
size: "16:9_720p", // "aspectRatio" or "aspectRatio_resolution"
duration: 5, // integer seconds, 1–15
});
// 2. Poll until complete, then read the video URL
let status = await getVideoJobStatus({ adapter, jobId });
while (status.status !== "completed" && status.status !== "failed") {
await new Promise((r) => setTimeout(r, 5000));
status = await getVideoJobStatus({ adapter, jobId });
}
console.log(status.url); // hosted .mp4 URLFor image-to-video (required for grok-imagine-video-1.5, optional for grok-imagine-video), include an image prompt part as the starting frame and describe the desired motion in the text part. URL sources are fetched by xAI's servers (so they must be publicly reachable); use a data source for a base64 starting frame:
import { generateVideo } from "@tanstack/ai";
import { grokVideo } from "@tanstack/ai-grok";
const { jobId } = await generateVideo({
adapter: grokVideo("grok-imagine-video-1.5"),
prompt: [
{
type: "text",
content: "Make the waterfall crash down and slowly pan out the camera",
},
{
type: "image",
source: { type: "url", value: "https://example.com/waterfall-still.png" },
},
],
size: "16:9_720p",
duration: 10,
});import { generateVideo } from "@tanstack/ai";
import { grokVideo } from "@tanstack/ai-grok";
const { jobId } = await generateVideo({
adapter: grokVideo("grok-imagine-video-1.5"),
prompt: [
{
type: "text",
content: "Make the waterfall crash down and slowly pan out the camera",
},
{
type: "image",
source: { type: "url", value: "https://example.com/waterfall-still.png" },
},
],
size: "16:9_720p",
duration: 10,
});Like the Grok Imagine image models, sizing is aspect-ratio based: the size option takes an aspectRatio_resolution template. Supported aspect ratios are 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, and 2:3; supported resolutions are 480p, 720p, and 1080p (e.g. "9:16_1080p"). The resolution suffix is optional.
When the job completes, the adapter reports usage on the result: usage.unitsBilled carries the billed seconds of video and usage.cost the exact cost in USD, both as returned by the xAI API.
See Video Generation for the full jobs/polling flow, streaming mode, and the useGenerateVideo hook.
Generate speech with Grok TTS:
import { generateSpeech } from "@tanstack/ai";
import { grokSpeech } from "@tanstack/ai-grok";
const result = await generateSpeech({
adapter: grokSpeech("grok-tts"),
text: "Hello from Grok!",
voice: "default",
format: "mp3",
});
console.log(result.audio); // Base64-encoded audioimport { generateSpeech } from "@tanstack/ai";
import { grokSpeech } from "@tanstack/ai-grok";
const result = await generateSpeech({
adapter: grokSpeech("grok-tts"),
text: "Hello from Grok!",
voice: "default",
format: "mp3",
});
console.log(result.audio); // Base64-encoded audioTranscribe audio with Grok STT:
import { generateTranscription } from "@tanstack/ai";
import { grokTranscription } from "@tanstack/ai-grok";
import { audioFile } from "./audio";
const result = await generateTranscription({
adapter: grokTranscription("grok-stt"),
audio: audioFile,
});
console.log(result.text);import { generateTranscription } from "@tanstack/ai";
import { grokTranscription } from "@tanstack/ai-grok";
import { audioFile } from "./audio";
const result = await generateTranscription({
adapter: grokTranscription("grok-stt"),
audio: audioFile,
});
console.log(result.text);Grok also exposes a Realtime voice adapter (grokRealtime) and a token issuer (grokRealtimeToken) for low-latency voice conversations. See Realtime Voice Chat for the end-to-end flow.
Set your API key in environment variables:
XAI_API_KEY=xai-...XAI_API_KEY=xai-...The Grok text and summarize adapters use xAI's Responses API (/v1/responses). Requests default to store: false and include encrypted reasoning content with include: ["reasoning.encrypted_content"]; both can be overridden through modelOptions.
The shared Responses implementation supports streaming text, reasoning events, structured output via text.format, and user-defined function tools.
Creates a Grok text adapter using environment variables.
Parameters:
Returns: A Grok text adapter instance.
Creates a Grok text adapter with an explicit API key.
Parameters:
Returns: A Grok text adapter instance.
Creates a Grok summarization adapter using environment variables.
Returns: A Grok summarize adapter instance.
Creates a Grok summarization adapter with an explicit API key.
Returns: A Grok summarize adapter instance.
Creates a Grok image generation adapter.
Creates a Grok video generation adapter (experimental) for the Grok Imagine video models ('grok-imagine-video', 'grok-imagine-video-1.5').
Creates a Grok text-to-speech adapter.
Creates a Grok speech-to-text adapter.
Realtime voice adapter and token issuer. See Realtime Voice Chat for usage.
Grok does not currently expose provider-specific tool factories. Define your own tools with toolDefinition() from @tanstack/ai.
See Tools for the general tool-definition flow, or Provider Tools for other providers' native-tool offerings.