Adding AI features to a web application often starts with a simple requirement: send a prompt to a model and display its response. The work becomes more complicated when you need streaming responses, different AI providers, structured output, and reliable error handling.
Each provider can have its own API, authentication requirements, request format, and response structure. If the application communicates directly with provider-specific APIs throughout the codebase, switching models can require changes in several places.
TanStack AI offers a different approach. It provides a TypeScript SDK with a common API for connecting to supported AI providers. You can handle chat requests, stream responses to the browser, and change the provider adapter without rebuilding the entire application around a different API.
This article explains how to integrate TanStack AI into a React application, stream model responses, switch between providers, and prepare the integration for production.
What Is TanStack AI?
TanStack AI is a TypeScript SDK for building AI-powered applications. It supports streaming chat, tool calling, structured outputs, and other AI activities through provider adapters.
Its architecture separates three main responsibilities:
- The core SDK manages chat execution, messages, streaming, and tools.
- Provider adapters connect the application to specific AI services.
- Client packages handle the interaction between the server and the user interface.
For example, an application can use an OpenAI adapter for text generation today and evaluate an Anthropic or Gemini adapter later. The provider-specific connection changes, while much of the surrounding application logic can remain the same.
TanStack AI supports providers including OpenAI, Anthropic, Google Gemini, OpenRouter, and Ollama. The available features depend on the selected adapter and model.
It is important to understand that a common API does not make every model identical. Different models can support different context sizes, tool-calling capabilities, input formats, and output limits.
Why Use TanStack AI Instead of Calling Provider APIs Directly?
Calling a provider API directly can be a reasonable choice for a small application with one model and a limited feature set.
However, as the application grows, provider-specific code can spread across API handlers, error handling, message processing, and streaming logic.
TanStack AI helps centralize these responsibilities.
| Area | Direct provider integration | TanStack AI |
|---|---|---|
| Provider communication | Implement each provider's API separately | Use supported provider adapters |
| Streaming | Handle provider-specific stream formats | Use the SDK's streaming interface |
| TypeScript support | Define types around each API | Use shared typed APIs and adapter-specific types |
| Provider switching | Update provider-specific integration code | Replace the adapter and validate compatibility |
| Tool calling | Implement provider-specific tool handling | Use the SDK's tool system where supported |
| Framework integration | Build your own client-side integration | Use framework packages such as the React client |
| Control over requests | Direct access to provider APIs | Some details are managed by the SDK and adapter |
TanStack AI does not eliminate the need to understand the underlying provider. It reduces the amount of provider-specific plumbing that application developers need to maintain.
Step 1: Install TanStack AI
For a React application that uses an OpenAI model, install the core package, React integration, and OpenAI adapter.
npm install @tanstack/ai @tanstack/ai-react @tanstack/ai-openaiThese packages have separate responsibilities:
@tanstack/aiprovides the core chat and streaming functionality.@tanstack/ai-reactprovides React hooks for managing chat state.@tanstack/ai-openaiprovides the OpenAI adapter.
You also need a compatible server environment and a valid provider API key.
Keep the installed package versions compatible. Before upgrading, review the documentation for the specific version used by your application because APIs and provider capabilities can change.
Step 2: Configure the Provider on the Server
The server should communicate with the AI provider so that provider credentials do not need to be exposed to browser code.
Store the API key in an environment variable:
OPENAI_API_KEY=your_server_side_api_keyDo not commit a real key to source control. For local development, keep secret files out of version control and use your hosting platform's secret management for production.
Next, create a server endpoint that accepts a chat request and returns a stream.
The following example uses a standard Web Request and Response API, making the handler suitable for a server route that supports these interfaces.
import {
chat,
chatParamsFromRequest,
toServerSentEventsResponse
} from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
export async function POST(request: Request) {
const { messages, threadId, runId } =
await chatParamsFromRequest(request);
const stream = chat({
adapter: openaiText("gpt-5.2"),
messages,
threadId,
runId
});
return toServerSentEventsResponse(stream);
}The model identifier is an example. Replace it with a model supported by your account and the installed adapter.
Here is what happens in the handler:
chatParamsFromRequest()reads the chat parameters sent by the client.openaiText()configures the provider adapter and model.chat()starts the model interaction and returns a stream.toServerSentEventsResponse()converts the stream into an HTTP response that the client can consume.
The framework-specific route file depends on your application. In TanStack Start, place the handler in an appropriate server route and follow the routing conventions of your installed version.
The example shows the core integration. A production endpoint must also enforce authentication where needed, validate requests, apply rate limits, and handle provider errors appropriately.
Step 3: Build a React Chat Interface
Once the server endpoint is available, the React client can send messages and display responses as they arrive.
TanStack AI provides the useChat hook and a transport function for consuming server-sent events.
import { useState } from "react";
import {
useChat,
fetchServerSentEvents
} from "@tanstack/ai-react";
export default function ChatPage() {
const [input, setInput] = useState("");
const {
messages,
sendMessage,
isLoading,
stop
} = useChat({
connection: fetchServerSentEvents("/api/chat")
});
function handleSubmit(
event: React.FormEvent<HTMLFormElement>
) {
event.preventDefault();
const message = input.trim();
if (!message || isLoading) {
return;
}
sendMessage({ text: message });
setInput("");
}
return (
<main>
<h1>AI Assistant</h1>
<section aria-live="polite">
{messages.map((message, index) => (
<div key={message.id ?? index}>
<strong>{message.role}</strong>
{message.parts?.map((part, partIndex) => {
if (part.type !== "text") {
return null;
}
return (
<p key={partIndex}>
{part.content}
</p>
);
})}
</div>
))}
</section>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(event) =>
setInput(event.target.value)
}
placeholder="Ask a question..."
disabled={isLoading}
/>
<button
type="submit"
disabled={isLoading || !input.trim()}
>
Send
</button>
{isLoading && (
<button
type="button"
onClick={stop}
>
Stop
</button>
)}
</form>
</main>
);
}
Join the conversation! Your thoughts help the community grow.