mcpField
T
tanstack-ai

tanstack-ai

github.com/secondsky開発240235 回インストール5 週間前に更新
リポジトリ

tanstack-ai について

tanstack-aiは、特定プロバイダーに依存しないLLMチャットアプリをTypeScriptで構築するためのスキルです。ストリーミング、型付きツール、アダプター、ReactやSolidのクライアント構成を扱います。

主な機能

  1. 01プロバイダーアダプターの選択
  2. 02チャットレスポンスのストリーミング
  3. 03型付きツール定義と検証
  4. 04クライアント・サーバーツールの構成
  5. 05エージェントループの上限と承認

活用シーン

  1. 01ストリーミング対応チャット画面の構築
  2. 02サーバーのデータ取得ツールとUI操作の連携
  3. 03機密性の高いツール呼び出しへの承認追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/secondsky/claude-skills --skill tanstack-ai

インストール後、Claude Code で/tanstack-aiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
api-chat-route.ts
tool-definitions.ts
references/
adapter-matrix.md
react-integration.md
start-vs-next-routing.md
streaming-troubleshooting.md
tanstack-ai-cheatsheet.md
tool-patterns.md
type-safety.md
scripts/
check-ai-env.sh

詳細

TanStack AI(プロバイダーに依存しない LLM SDK)

ステータス: 本番環境で利用可能 ✅
最終更新日: 2025-12-09
依存関係: Node.js 20 以降、TypeScript 5 以降、@tanstack/ai-react には React 19 以降、@tanstack/ai-solid には Solid 1.8 以降
最新バージョン: @tanstack/ai@latest(alpha)、@tanstack/ai-react@latest、@tanstack/ai-client@latest、アダプター: @tanstack/ai-openai@latest @tanstack/ai-anthropic@latest @tanstack/ai-gemini@latest @tanstack/ai-ollama@latest


クイックスタート(7 分)

1) コアとアダプターをインストールする
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

重要な理由:

  • コアはフレームワークに依存しません。React バインディングはヘッドレスクライアントをラップするだけです。 citeturn1search3
  • アダプターがプロバイダー固有の差異を抽象化するため、コードを書き換えずにモデルを変更できます。 citeturn1search3
2) ストリーミングチャットエンドポイントを構築する(Next.js または 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)
}

重要:

  • LLM がツールを呼び出せるよう、ツールの定義をサーバーに渡してください。実装は各ランタイムに配置します。 citeturn0search7
  • 常にストリーミングしてください。チャンク化されたレスポンスは UI の応答性を保ち、トークンの無駄を減らします。 citeturn0search1
3) 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>
  )
}

重要:

  • ストリーミングレスポンスに対応させるため、fetchServerSentEvents(または対応するアダプター)を使用してください。 citeturn0search0
  • 「tool not found」エラーを避けるため、クライアントのツール名を定義と一致させてください。 citeturn0search7

4 ステップのセットアップ手順

ステップ 1: プロバイダーとモデルを安全に選択する
  • 適切なアダプターを追加し、対応する API キー(OPENAI_API_KEY、ANTHROPIC_API_KEY、GEMINI_API_KEY、または Ollama のホスト)を設定します。
  • 無効なオプション(例: ビジョン専用のフィールド)を避けるため、アダプターが提供するモデルごとのオプション型を優先して使用します。 citeturn1search3
ステップ 2: ツールを一度定義し、ランタイムごとに実装する
// 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 }
})

重要なポイント:

  • needsApproval: true を設定すると、機密性の高いアクションにユーザーの明示的な承認が必要になります。 citeturn0search1
  • ツールは単一の目的に絞って冪等にし、エラーをスローするのではなく、構造化されたオブジェクトを返します。 citeturn0search1
ステップ 3: 接続アダプターとチャットオプションを作成する
  • サーバー: HTTP ストリーミングには toStreamResponse(stream) を、Server-Sent Events には toServerSentEventsStream ヘルパーを使用します。 citeturn0search3turn0search4
  • クライアント: fetchServerSentEvents('/api/chat') を使用します。必要に応じて、WebSocket 用のカスタムアダプターを使用します。 citeturn0search0
  • agentLoopStrategy(例: maxIterations(8))を設定して、ツールの再帰を制限します。 citeturn1search4
ステップ 4: 可観測性とガードレールを追加する
  • デバッグ用にツールの実行とストリームのチャンクをログに記録します。alpha ではフックが利用できますが、開発者ツールは現在開発中です。 citeturn0search1
  • Zod で入力を検証し、速やかに失敗させて、型付きのエラーオブジェクトを返します。
  • エージェントループが停止しなくなるのを防ぐため、ツール内の外部 API 呼び出しにタイムアウトを設定します。

重要なルール

必ず行うこと

✅ レスポンスをストリーミングし、全体の完了を待たないでください。 citeturn0search1
✅ サーバーには定義を、適切なランタイムには実装を渡してください。 citeturn0search7
✅ プロバイダー間で型安全性を保つため、ツールの入力と出力には Zod スキーマを使用してください。 citeturn0search1
✅ 予期しないツール呼び出しが続くのを防ぐため、maxIterations でエージェントループを制限してください。 citeturn1search4
✅ 破壊的な操作や請求に影響するツールには needsApproval を必須にしてください。 citeturn0search1

絶対に行わないこと

❌ 1 回のリクエストでプロバイダーアダプターを混在させないでください。呼び出しごとにアダプターを 1 つインスタンス化してください。
❌ ツールから生のエラーをスローしないでください。構造化されたエラーペイロードを返してください。
❌ クライアントのツール実装をサーバーに送信しないでください(定義のみ)。
❌ モデルの機能をハードコードしないでください。モデルごとのオプションにはアダプターの型定義を使用してください。 citeturn0search1
❌ API キーの確認を省略しないでください。サーバーで役立つメッセージを表示して速やかに失敗させてください。 citeturn0search1


既知の問題の予防

このスキルは、ドキュメント化されている 3 件の問題を防ぎます。

Issue #1:「tool not found」/ツールのサイレントな失敗

発生する理由:定義が chat() に渡されておらず、実装だけがローカルに存在しています。
予防策:定義を個別にエクスポートしてサーバーの tools 配列に含め、名前を一貫させてください。 citeturn0search7

Issue #2:UI でストリーミングが停止する

発生する理由:サーバーのレスポンス形式とクライアントアダプターが一致していません(HTTP チャンク転送と SSE の不一致)。
予防策:サーバーでは toStreamResponse を使用し、クライアントでは fetchServerSentEvents(または対応するアダプター)を使用してください。 citeturn0search1turn0search0

Issue #3:モデルオプションの検証エラー

発生する理由:プロバイダー固有のオプション(例:ビジョン関連のパラメーター)が、サポートされていないモデルに送信されています。
予防策:アダプターが提供する型を使用し、モデルごとのオプション型を利用して、無効なフィールドをコンパイル時に検出してください。 citeturn1search3


設定ファイルのリファレンス

.env.local(完全な例)
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=
GEMINI_API_KEY=
OLLAMA_HOST=http://localhost:11434
AI_STREAM_STRATEGY=immediate

これらの設定を使用する理由:

  • アクティブでないプロバイダーは空のままにし、誤って複数のプロバイダーを呼び出さないようにします。
  • AI_STREAM_STRATEGY はサンプルクライアントによって読み込まれ、チャンク戦略(即時またはバッファリング)を選択します。

一般的なパターン

パターン 1:ツールに上限を設けたエージェントサイクル
import { chat, maxIterations } from '@tanstack/ai'
import { openai } from '@tanstack/ai-openai'

const stream = chat({
  adapter: openai(),
  messages,
  tools,
  agentLoopStrategy: maxIterations(8), // hard cap
})

使用する場面:LLM がツール間を再帰的に呼び出す可能性のあるあらゆるフロー(検索 → 要約 → 詳細取得)。 citeturn1search4

パターン 2:サーバーツールとクライアントツールの併用
// server: data fetch
const fetchUser = fetchUserDef.server(async ({ id }) => db.user.find(id))

// client: UI update
const highlightUser = highlightUserDef.client(({ id }) => {
  document.querySelector(`#user-${id}`)?.classList.add('ring')
  return { highlighted: true }
})

chat({ tools: [fetchUser, highlightUser] })

使用する場面:モデルが 1 つのループ内でデータ取得と UI 状態の変更の両方を行う必要がある場合。 citeturn0search1


バンドルされたリソースの使用

スクリプト(scripts/)
  • scripts/check-ai-env.sh — 開発サーバーの実行前に、必要なプロバイダーキーが設定されていることを確認します。

使用例:

./scripts/check-ai-env.sh
リファレンス(references/)
  • references/tanstack-ai-cheatsheet.md — サーバー/クライアント/ツールのパターンを簡潔にまとめ、トラブルシューティングのヒントも記載しています。

Claude がこれらを読み込む場面:ツールのルーティングやストリーミングの問題をデバッグするとき、または正確な API 呼び出しを確認するときです。

アセット(assets/)
  • assets/api-chat-route.ts — ストリーミングとツールに対応した、コピーして使える API ルートのテンプレートです。
  • assets/tool-definitions.ts — 承認機能と zod スキーマを含む、すぐに使える toolDefinition の例です。

リファレンスを読み込むタイミング

具体的な実装シナリオに応じて、リファレンスファイルを読み込んでください。

  • アダプターの比較:OpenAI、Anthropic、Gemini、Ollama のアダプターから選択するとき、またはプロバイダー固有の動作をデバッグするときは、references/adapter-matrix.md を読み込みます。

  • React 統合の詳細:useChat フックを実装するとき、React コンポーネントで SSE ストリームを処理するとき、またはクライアント側のツール状態を管理するときは、references/react-integration.md を読み込みます。

  • ルーティングの設定:Next.js と TanStack Start のどちらかで API ルートを設定するとき、またはストリーミングレスポンスの設定をトラブルシューティングするときは、references/start-vs-next-routing.md を読み込みます。

  • ストリーミングの問題:SSE 接続の問題、チャンク配信の問題、HTTP ストリーミングの設定をデバッグするときは、references/streaming-troubleshooting.md を読み込みます。

  • クイックリファレンス:API パターン、ツール定義の構文、または迅速なトラブルシューティングのヒントを簡潔に確認するときは、references/tanstack-ai-cheatsheet.md を読み込みます。

  • ツールのアーキテクチャ:複雑なクライアント/サーバー間のツールワークフロー、承認フロー、またはハイブリッドなツールパターンを実装するときは、references/tool-patterns.md を読み込みます。

  • 型安全性の詳細:モデルごとのオプション型、マルチモーダル入力を扱うとき、またはアダプター間の型エラーをデバッグするときは、references/type-safety.md を読み込みます。


高度なトピック

モデルごとの型安全性
  • アダプターの型定義を使用して、モデルごとに有効なオプションを選択し、chat() で汎用的な any オプションを使用しないでください。 citeturn1search3
  • マルチモーダルモデルでは、正しい MIME タイプを指定した parts を送信してください。サポートされていないモダリティはコンパイル時に検出されます。 citeturn1search3
ツール承認の UX
  • useChat の approval オブジェクトを通じて提供されます。承認/拒否の UI を表示し、ツール呼び出しごとに判断を永続化してください。 citeturn0search1
  • 監査可能なアクションでは、ツール入力と併せて承認の判断を記録してください。
接続アダプター
  • 最小限のセットアップには fetchServerSentEvents(SSE)を使用し、WebSocket や HTTP チャンク転送にはカスタムアダプターに切り替えます。 citeturn0search0
  • タイピングインジケーター UI で各チャンクを出力するには、クライアントで ImmediateStrategy を使用します。 citeturn0search0

依存関係

必須:

  • @tanstack/ai@latest — コアのチャットおよびツールエンジン
  • @tanstack/ai-react@latest — React バインディング(ヘッドレスで使用する場合は不要)
  • @tanstack/ai-client@latest — ヘッドレスチャットクライアントおよびアダプター
  • アダプター:@tanstack/ai-openai@latest | @tanstack/ai-anthropic@latest | @tanstack/ai-gemini@latest | @tanstack/ai-ollama@latest のいずれか
  • zod@latest — ツールのスキーマ検証

任意:

  • @tanstack/ai-solid@latest — Solid バインディング
  • @tanstack/react-query@latest — ツール内で取得したデータをキャッシュ
  • @tanstack/start@latest — AI ツールをサーバー関数と同じ場所に配置

公式ドキュメント


パッケージのバージョン(2025-12-09 に確認済み)

{
  "dependencies": {
    "@tanstack/ai": "latest",
    "@tanstack/ai-react": "latest",
    "@tanstack/ai-client": "latest",
    "@tanstack/ai-openai": "latest"
  },
  "devDependencies": {
    "zod": "latest"
  }
}

トラブルシューティング

問題:UI がツールの出力を受け取れない

解決策:ツールの実装がシリアライズ可能なオブジェクトを返すことを確認します。undefined は返さないでください。clientTools(...) を使ってクライアント実装を登録します。

問題:「Missing API key」レスポンスが返される

解決策:./scripts/check-ai-env.sh を実行し、該当するプロバイダーのキーを .env.local に設定します。chat() を呼び出す前に、ルートで処理を失敗させます。 citeturn0search1

問題:最初のチャンクの後にストリーミングが停止する

解決策:サーバーが toStreamResponse(stream)(または SSE ヘルパー)を返すことと、リバースプロキシがチャンク転送を許可していることを確認します。


セットアップの完全チェックリスト

このチェックリストを使って、セットアップを確認します。

  • コアとアダプターを1つ、および zod をインストールした
  • API ルートがツールの定義を含む toStreamResponse(stream) を返す
  • クライアントが fetchServerSentEvents(または対応するアダプター)を使用し、クライアントツールの実装を登録している
  • needsApproval のパスで承認/拒否 UI を表示する
  • エージェントループに上限を設定している(例:maxIterations)
  • check-ai-env.sh で環境キーを検証した
  • ビジョン/音声モデルを対象とする場合、マルチモーダル入力をテストした

質問や問題がありますか?

  1. 詳しい例については references/tanstack-ai-cheatsheet.md を読み込みます
  2. プロバイダーアダプターを1つだけ使って、クイックスタートの手順を再実行します
  3. API の更新については、上記の公式ドキュメントを確認します

コメント