Skip to content
Development
Skill

/tanstack-ai

TanStack AI (alpha) provider-agnostic type-safe chat with streaming for OpenAI, Anthropic, Gemini, Ollama. Use for chat APIs, React/Solid frontends with useChat/ChatClient, isomorphic tools, tool approval flows, agent loops, multimodal inputs, or troubleshooting streaming and

From plugin
claude-skills
241183 skills42 agents62 commands2 MCP

Claude Code

$ npx -y skills add secondsky/claude-skills --skill tanstack-ai --agent claude-code

SKILL.md

tanstack-ai.SKILL.md
name: tanstack-ai
description: "TanStack AI (alpha) provider-agnostic type-safe chat with streaming for OpenAI, Anthropic, Gemini, Ollama. Use for chat APIs, React/Solid frontends with useChat/ChatClient, isomorphic tools, tool approval flows, agent loops, multimodal inputs, or troubleshooting streaming and tool definitions."

metadata:
  keywords:
    - TanStack AI
    - "@tanstack/ai"
    - "@tanstack/ai-react"
    - "@tanstack/ai-client"
    - "@tanstack/ai-solid"
    - "@tanstack/ai-openai"
    - "@tanstack/ai-anthropic"
    - "@tanstack/ai-gemini"
    - "@tanstack/ai-ollama"
    - toolDefinition
    - client tools
    - server tools
    - tool approval
    - agent loop
    - streaming
    - SSE
    - connection adapters
    - multimodal
    - type-safe models
    - TanStack Start
    - Next.js API
    - toStreamResponse
    - fetchServerSentEvents
    - chat
    - useChat
    - ChatClient
    - needsApproval

license: MIT

TanStack AI (Provider-Agnostic LLM SDK)

**Status**: Production Ready ✅ **Last Updated**: 2025-12-09 **Dependencies**: Node.js 20+, TypeScript 5+; React 19+ for `@tanstack/ai-react`; Solid 1.8+ for `@tanstack/ai-solid` **Latest Versions**: @tanstack/ai@latest (alpha), @tanstack/ai-react@latest, @tanstack/ai-client@latest, adapters: @tanstack/ai-openai@latest @tanstack/ai-anthropic@latest @tanstack/ai-gemini@latest @tanstack/ai-ollama@latest

---

Quick Start (7 Minutes)

1) Install core + adapter

pnpm add @tanstack/ai @tanstack/ai-react @tanstack/ai-openai
# swap adapters as needed: @tanstack/ai-anthropic @tanstack/ai-gemini @tanstack/ai-ollama
pnpm add zod              # recommended for tool schemas

**Why this matters:**

  • Core is framework-agnostic; React binding just wraps the headless client. citeturn1search3
  • Adapters abstract provider quirks so you can change models without rewriting code. citeturn1search3

2) Ship a streaming chat endpoint (Next.js or TanStack Start)

// app/api/chat/route.ts (Next.js) or src/routes/api/chat.ts (TanStack Start)
import { chat, toStreamResponse } from '@tanstack/ai'
import { openai } from '@tanstack/ai-openai'
import { tools } from '@/tools/definitions' // definitions only

export async function POST(request: Request) {
  const { messages, conversationId } = await request.json()
  const stream = chat({
    adapter: openai(),
    messages,
    model: 'gpt-4o',
    tools,
  })
  return toStreamResponse(stream)
}

**CRITICAL:**

  • Pass tool **definitions** to the server so the LLM can request them; implementations live in their runtimes. citeturn0search7
  • Always stream; chunked responses keep UIs responsive and reduce token waste. citeturn0search1

3) Wire the client with `useChat` + SSE

// components/Chat.tsx
import { useChat, fetchServerSentEvents } from '@tanstack/ai-react'
import { clientTools } from '@tanstack/ai-client'
import { updateUIDef } from '@/tools/definitions'

const updateUI = updateUIDef.client(({ message }) => {
  alert(message)
  return { success: true }
})

export function Chat() {
  const tools = clientTools(updateUI)
  const { messages, sendMessage, isLoading, approval } = useChat({
    connection: fetchServerSentEvents('/api/chat'),
    tools,
  })

  return (
    <form onSubmit={e => { e.preventDefault(); sendMessage(e.currentTarget.prompt.value) }}>
      <textarea name="prompt" disabled={isLoading} />
      {approval?.pending && (
        <button type="button" onClick={() => approval.approve()}>
          Approve tool
        </button>
      )}
    </form>
  )
}

**CRITICAL:**

  • Use `fetchServerSentEvents` (or matching adapter) to mirror the streaming response. citeturn0search0
  • Keep client tool names identical to definitions to avoid “tool not found” errors. citeturn0search7

---

The 4-Step Setup Process

Step 1: Choose provider + model safely

  • Add the correct adapter and set the matching API key (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, or Ollama host).
  • Prefer per-model option typing from adapters to avoid invalid options (e.g., vision-only fields). citeturn1search3

Step 2: Define tools once, implement per runtime

// tools/definitions.ts
import { z, toolDefinition } from '@tanstack/ai'

export const getWeatherDef = toolDefinition({
  name: 'getWeather',
  description: 'Get current weather for a city',
  inputSchema: z.object({ city: z.string() }),
  needsApproval: true,
})

export const getWeather = getWeatherDef.server(async ({ city }) => {
  const data = await fetch(`https://api.weather.gov/points?q=${city}`).then(r => r.json())
  return { summary: data.properties?.relativeLocation?.properties?.city ?? city }
})

export const showToast = getWeatherDef.client(({ city }) => {
  console.log(`Showing toast for ${city}`)
  return { acknowledged: true }
})

**Key Points:**

  • `needsApproval: true` forces explicit user approval for sensitive actions. citeturn0search1
  • Keep tools single-purpose and idempotent; return structured objects instead of throwing errors. citeturn0search1

Step 3: Create connection adapter + chat options

  • Server: `toStreamResponse(stream)` for HTTP streaming; `toServerSentEventsStream` helper for Server-Sent Events. citeturn0search3turn0search4
  • Client: `fetchServerSentEvents('/api/chat')` or a custom adapter for websockets if needed. citeturn0search0
  • Configure `agentLoopStrategy` (e.g., `maxIterations(8)`) to cap tool recursion. citeturn1search4

Step 4: Add observability + guardrails

  • Log tool executions and stream chunks for debugging; alpha exposes hooks while devtools are in progress. citeturn0search1
  • Validate inputs with Zod; fail fast and return typed error objects.
  • Enforce timeouts on external API calls inside tools to prevent stuck agent loops.

---

Critical Rules

Always Do

✅ Stream responses; avoid waiting for full completions. citeturn0search1 ✅ Pass **definitions** to the server and **implem

Read more
@secondsky
Ships withclaude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

241183 skills42 agents2 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
241
Star history of secondsky/claude-skills on GitHub, a chart by star-history.com

Other skills on claude-skills.

aceternity-ui

aceternity-ui

100+ animated React components (Aceternity UI) for Next.js with Tailwind. Use for hero sections, parallax, 3D effects, or…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about tanstack-ai.

Which coding agents can use tanstack-ai?
tanstack-ai installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.