TanStack
TanStack

AI

RC

The headless agent framework. Bring your own stack.

TanStack AI is a pluggable AI ecosystem that makes it easy for you to build AI features into your apps. It offers a toolkit that allows you to provide tools to the LLMs, interrupt the chat for user approval, run agents inside of sandboxes, build headless UI for your chats, stream the data from your server to your client, and connect to any AG-UI protocol compatible server or client. No opinions on how you should add AI into your apps: you bring your own existing infrastructure, we offer you the pluggable APIs to build on top of.

Docs
A client graph shows eight UI adapters converging on the TanStack AI Client over AG-UI, then reaching an agent runtime in TypeScript, Python, Go, or PHP, and interchangeable model providers.
client graph
chat runtime

Two files

Own both sides of the AI interaction.

One route on the server, one hook in the client, and the transport between them is yours. Nothing here is a wrapper around a service we run.

server · routes/api.chat.ts

import { chat, toServerSentEventsResponse } from '@tanstack/ai'

import { openRouterText } from '@tanstack/ai-openrouter'

import { createFileRoute } from '@tanstack/react-router'

 

export const Route = createFileRoute('/api/chat')({

server: {

handlers: {

POST: async ({ request }) => {

const { messages } = await request.json()

 

const stream = chat({

adapter: openRouterText('anthropic/claude-sonnet-4.5'),

messages,

tools: [lookupInvoice],

})

 

// your route, your auth, your deploy target

return toServerSentEventsResponse(stream)

},

},

},

})

client · chat.tsx

import { useChat, fetchServerSentEvents } from '@tanstack/ai-react'

 

export function Chat() {

const { messages, sendMessage, interrupts } = useChat({

connection: fetchServerSentEvents('/api/chat'),

})

 

// typed state and events. no components, no styles.

return (

<>

{messages.map((message) => (

<Bubble key={message.id} {...message} />

))}

 

{/* the loop paused. you decide when it continues. */}

{interrupts.map((interrupt) => (

<button key={interrupt.id}

onClick={() => interrupt.resolveInterrupt(true)}>

Approve {interrupt.toolName}

</button>

))}

</>

)

}

Swap React for any other framework and keep your server-side code identical.

Isomorphic tools

Define your agent tools once, re-use them on the server and client.

Our chat() function allows you to define custom functions the LLM provider can call (tools) and you define the input and output to these functions once and re-use them across server and client by providing the specific implementations. Our library automatically calls these tools, stops and asks for approvals if needed, updates the input to the tools if the user changes it after the approval is granted and handles all the back and forth between the LLM provider and your app under the hood. You only define the tool, we handle the rest.

tool contract

const lookupInvoice = toolDefinition({

  name: 'lookup_invoice',

  inputSchema: z.object({ id: z.string() }),

  outputSchema: invoiceSchema,

  needsApproval: true,

})

lookupInvoice.server(async ({ id }) => {

  return db.invoices.update({

    where: { id },

    data: { lastViewedAt: new Date() },

  })

})

The server implementation uses the same typed id to update a row in your database. The model never sees your credentials.

provider capability types

selected model

any of 300+ models

textreasoningtoolsimagemedia

Types narrow to this exact model: its options, its capabilities, its input modalities. Pass an image to a text-only model and it fails at compile time, not in production.

Typesafe models

Swap an LLM provider. Keep the typesafety.

OpenRouter, OpenAI, Anthropic, Gemini, Vertex, Bedrock, Mistral, Groq, Grok, Ollama, Cohere, Perplexity, BytePlus, ElevenLabs, fal.ai, Lovable, LLM Gateway, and Vercel AI Gateway ship as official adapters, and openaiCompatible covers any endpoint that speaks the same shape, including a model on your own hardware. See the adapter docs for more. Every model from every provider is typesafe. When you need to send custom configuration for a specific model, send images, files and audio, or native tools like web search, every model is type-constrained and if it does not accept those options natively you learn about it at compile-time.

Open protocol

AG-UI compliant, in both directions.

The client sends AG-UI requests and consumes AG-UI events, with no proprietary stream format and no translation layer in between. That is what makes the agent on the other end replaceable: point the same client at a Python, Go, or PHP AG-UI runtime and it keeps working. The transport is yours too, whether that is SSE, HTTP streams, XHR, RPC, a raw async iterable, or a fetcher you wrote. Nothing to sign up for, no key to hand over, no traffic through us.

AG-UI sits between your web app and your AI endpoint, with traffic in both directions. The server then talks to a provider such as OpenAI or Anthropic.

CLIENT

your web app

AG-UI

communication protocol

Server

your ai endpoint

Provider

openai, anthropic

More than just a chat function

Sandboxes, code mode, MCP, memory, compaction, skills and more.

We offer more than just a simple chat interface. We allow you to build any AI feature you might need, from automated AI workflows in CI, to web apps consuming LLM providers, chatbots and more.

Code Mode

@tanstack/ai-code-mode

You provide a special tool to the LLM provider that allows it to chain tools (functions) into a single executable script and call it in a local or remote isolate, producing results that it further processes. It writes code and calls it.

01

Coding-agent harnesses

@tanstack/ai-sandbox

Run Claude Code, Codex, OpenCode, Grok Build, or any ACP agent as a chat backend, inside a local process, Docker, Daytona, Vercel, Sprites, or Cloudflare sandbox. Their tool activity streams back as AG-UI events your UI already renders.

02

MCP + MCP Apps

@tanstack/ai-mcp

A host-side MCP client with a type-generating CLI, provider-routed mcpTool(), and interactive ui:// widgets rendered from tool results across multiple servers.

03

Memory + compaction

@tanstack/ai-memory · @tanstack/ai-compaction

memoryMiddleware recalls across sessions through Redis, mem0, Honcho, or Hindsight adapters. Compaction keeps long threads inside the model window so the agent does not lose the thread as context grows.

04

Durability + persistence

@tanstack/ai-persistence · @tanstack/ai-durable-stream

Persistence keeps an authoritative server thread, resumes a stream through a dropped connection, and survives a reload. Durability lets a run continue after a process restart.

05

Beyond chat

Need to generate images, video, audio and more? We have you covered.

We equally care about every generation, not just text. We offer you a whole suite of utilities to generate images, video, speech, transcription, music and realtime voice with full observability and cost tracking.

Text, objects, reasoning

chat · outputSchema · summarize

Generate an output from an AI that matches your validation schema exactly using structured output.

01

Speech, transcription, music

generateSpeech · generateTranscription · generateAudio

Six speech formats with speed control, transcription with word timestamps and diarization, plus music and sound effects.

02

Realtime voice

openaiRealtimeToken · RealtimeClient

OpenAI, Grok, and ElevenLabs with VAD modes and tool calling inside a live session.

03

Images + video

generateImage · generateVideo

Generate images and videos, edit existing generations and show progress updates to your users with ease.

04

Devtools

Full observability of every action with our devtools

Our devtools show you every detail about every part of your system, whether you are generating images, video or using chat you can see every action that happened on both the server and the client and easily debug what is going on on both sides.

tanstack devtools · ai

hooks

Support Chat

useChat · 12 msgs

Image Studio

useGenerateImage

Invoice Extract

useObject

Call Notes

useTranscription

run timeline

thread_7f2 · run_3

user turn"refund the duplicate charge"
memory recall3 facts injected · 214 tokens
tool calllookupInvoice { id: "inv_8841" }
tool result{ total: 4200, status: "paid" }
interruptchargeCard · awaiting approval
finish reasoninterrupt · run resumable

Partners

Gold
CodeRabbit
Cloudflare
Vercel
Railway
Netlify
Render
Lovable
Silver
OpenRouter
WorkOS
SerpApi
Clerk
AG Grid
Bronze
Electric
Unkey
Prisma
Sentry
OSS Sponsors

Sponsors get special perks like private discord channels, priority issue requests, and direct support!