# Tanstack Ai

> Build AI-powered chat applications with TanStack AI and React. Use when working with @tanstack/ai, @tanstack/ai-react, @tanstack/ai-client, or any TanStack AI packages. Covers useChat hook, streaming, tools (server/client/hybrid), tool approval, structured outputs, multimodal content, adapters (OpenAI, Anthropic, Gemini, Ollama, Grok), agentic cycles, devtools, and type safety patterns. Triggers…

- **Type:** Skill
- **Install:** `agentstack add skill-fellipeutaka-leon-tanstack-ai`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [fellipeutaka](https://agentstack.voostack.com/s/fellipeutaka)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [fellipeutaka](https://github.com/fellipeutaka)
- **Source:** https://github.com/fellipeutaka/leon/tree/main/skills/tanstack-ai

## Install

```sh
agentstack add skill-fellipeutaka-leon-tanstack-ai
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# TanStack AI (React)

AI chat framework with isomorphic tools, streaming, and full type safety.

## Packages

- `@tanstack/ai` — core: `chat()`, `toolDefinition()`, `toServerSentEventsResponse()`, `maxIterations()`
- `@tanstack/ai-react` — React: `useChat()` hook, re-exports connection adapters
- `@tanstack/ai-client` — headless: `ChatClient`, `clientTools()`, `createChatClientOptions()`, `InferChatMessages`
- `@tanstack/ai-{openai,anthropic,gemini,ollama,grok,openrouter,fal}` — adapter packages

## Quick Start

### Install

```bash
npm install @tanstack/ai @tanstack/ai-react @tanstack/ai-openai
```

### Server (Next.js API Route)

```typescript
import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";

export async function POST(request: Request) {
  const { messages } = await request.json();
  const stream = chat({
    adapter: openaiText("gpt-5.2"),
    messages,
  });
  return toServerSentEventsResponse(stream);
}
```

### Client (React)

```typescript
import { useState } from "react";
import { useChat, fetchServerSentEvents } from "@tanstack/ai-react";

export function Chat() {
  const [input, setInput] = useState("");
  const { messages, sendMessage, isLoading } = useChat({
    connection: fetchServerSentEvents("/api/chat"),
  });

  return (
    
      {messages.map((message) => (
        
          {message.role}:
          {message.parts.map((part, idx) => {
            if (part.type === "text") return {part.content};
            if (part.type === "thinking") return {part.content};
            return null;
          })}
        
      ))}
       { e.preventDefault(); sendMessage(input); setInput(""); }}>
         setInput(e.target.value)} disabled={isLoading} />
        Send
      
    
  );
}
```

## useChat Hook

```typescript
const {
  messages,          // UIMessage[] — current messages
  sendMessage,       // (content: string | MultimodalContent) => Promise
  append,            // (message: ModelMessage | UIMessage) => Promise
  isLoading,         // boolean
  error,             // Error | undefined
  stop,              // () => void — cancel current stream
  reload,            // () => Promise — regenerate last response
  clear,             // () => void — clear all messages
  setMessages,       // (messages: UIMessage[]) => void
  addToolResult,     // (result: { toolCallId, tool, output, state? }) => Promise
  addToolApprovalResponse, // (response: { id, approved }) => Promise
} = useChat({
  connection: fetchServerSentEvents("/api/chat"),
  tools?,             // client tool implementations
  initialMessages?,   // UIMessage[]
  id?,                // string — unique chat instance id
  body?,              // additional body params sent with every request
  onResponse?,        // (response) => void
  onChunk?,           // (chunk) => void
  onFinish?,          // (message) => void
  onError?,           // (error) => void
});
```

## Message Structure

Messages use `UIMessage` with a `parts` array:

```typescript
interface UIMessage {
  id: string;
  role: "user" | "assistant";
  parts: (TextPart | ThinkingPart | ToolCallPart | ToolResultPart)[];
}
```

Render parts by type:
- `part.type === "text"` — `part.content` (string)
- `part.type === "thinking"` — `part.content` (model reasoning, UI-only, not sent back)
- `part.type === "tool-call"` — `part.name`, `part.input`, `part.output`, `part.state`
- `part.type === "tool-result"` — `part.output`, `part.state`

## Connection Adapters

```typescript
import { fetchServerSentEvents, fetchHttpStream, stream } from "@tanstack/ai-react";

// SSE (recommended — auto-reconnection)
fetchServerSentEvents("/api/chat", { headers: { Authorization: "Bearer token" } })

// HTTP stream (NDJSON)
fetchHttpStream("/api/chat")

// Custom
stream(async (messages, data, signal) => { /* return async iterable */ })
```

## Adapters

Model passed to adapter factory — one function per activity for tree-shaking:

```typescript
import { openaiText } from "@tanstack/ai-openai";       // openaiText('gpt-5.2')
import { anthropicText } from "@tanstack/ai-anthropic";  // anthropicText('claude-sonnet-4-5')
import { geminiText } from "@tanstack/ai-gemini";        // geminiText('gemini-2.5-pro')
import { ollamaText } from "@tanstack/ai-ollama";        // ollamaText('llama3')
import { grokText } from "@tanstack/ai-grok";            // grokText('grok-4')
import { openRouterText } from "@tanstack/ai-openrouter"; // openRouterText('openai/gpt-5')
```

## Tools Overview

Two-step process: define schema with `toolDefinition()`, then implement with `.server()` or `.client()`.

```typescript
import { toolDefinition } from "@tanstack/ai";
import { z } from "zod";

const getWeatherDef = toolDefinition({
  name: "get_weather",
  description: "Get current weather for a location",
  inputSchema: z.object({ location: z.string() }),
  outputSchema: z.object({ temperature: z.number(), conditions: z.string() }),
  needsApproval: false, // optional
});

// Server implementation — runs on server with DB/API access
const getWeather = getWeatherDef.server(async ({ location }) => {
  const data = await fetchWeather(location);
  return { temperature: data.temp, conditions: data.conditions };
});

// Client implementation — runs in browser for UI/localStorage
const getWeatherClient = getWeatherDef.client((input) => {
  return { temperature: 72, conditions: "cached" };
});
```

For detailed tool patterns (server, client, hybrid, approval, agentic cycle), see [references/tools.md](references/tools.md).

## Type Safety

Use `clientTools()` + `createChatClientOptions()` + `InferChatMessages` for full type inference:

```typescript
import { clientTools, createChatClientOptions, type InferChatMessages } from "@tanstack/ai-client";

const tools = clientTools(updateUI, saveToStorage); // no 'as const' needed
const chatOptions = createChatClientOptions({
  connection: fetchServerSentEvents("/api/chat"),
  tools,
});
type ChatMessages = InferChatMessages;

// In component:
const { messages } = useChat(chatOptions);
// messages typed — part.name is discriminated union, part.input/output typed from Zod schemas
```

## Devtools

```bash
npm install -D @tanstack/react-ai-devtools @tanstack/react-devtools
```

```tsx
import { TanStackDevtools } from "@tanstack/react-devtools";
import { aiDevtoolsPlugin } from "@tanstack/react-ai-devtools";

```

## Additional Guides

- **Server setup patterns** (Next.js, TanStack Start): see [references/server-setup.md](references/server-setup.md)
- **Tool system** (server, client, hybrid, approval, agentic cycle): see [references/tools.md](references/tools.md)
- **Advanced features** (multimodal, structured outputs, runtime adapter switching): see [references/advanced.md](references/advanced.md)

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [fellipeutaka](https://github.com/fellipeutaka)
- **Source:** [fellipeutaka/leon](https://github.com/fellipeutaka/leon)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-fellipeutaka-leon-tanstack-ai
- Seller: https://agentstack.voostack.com/s/fellipeutaka
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
