AgentStack
SKILL verified MIT Self-run

Tanstack Ai

skill-fellipeutaka-leon-tanstack-ai · by fellipeutaka

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…

No reviews yet
0 installs
1 views
0.0% view→install

Install

$ agentstack add skill-fellipeutaka-leon-tanstack-ai

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-fellipeutaka-leon-tanstack-ai)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
8d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Tanstack Ai? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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

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

Server (Next.js API Route)

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)

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

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:

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

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:

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().

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:

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

npm install -D @tanstack/react-ai-devtools @tanstack/react-devtools
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.

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

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.