关于 tanstack-ai
tanstack-ai 是用于构建跨 LLM 提供方 TypeScript 聊天应用的 SDK 技能,涵盖流式响应、类型化工具、提供方适配器及 React 或 Solid 客户端模式。
主要功能
- 01选择提供方适配器
- 02流式聊天响应
- 03类型化工具定义与验证
- 04客户端和服务器工具模式
- 05限制 Agent 循环并设置审批
适用场景
- 01构建流式聊天界面
- 02结合服务器数据工具与 UI 操作
- 03为敏感工具调用添加审批步骤
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill tanstack-ai安装后在 Claude Code 中输入/tanstack-ai确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/api-chat-route.tstool-definitions.tsreferences/adapter-matrix.mdreact-integration.mdstart-vs-next-routing.mdstreaming-troubleshooting.mdtanstack-ai-cheatsheet.mdtool-patterns.mdtype-safety.mdscripts/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 绑定只是对无头客户端的封装。 citeturn1search3
- 适配器会屏蔽提供商的差异,因此你无需重写代码就能更换模型。 citeturn1search3
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 请求调用这些工具;具体实现则放在相应的运行时中。 citeturn0search7
- 始终使用流式传输;分块响应能让 UI 保持响应灵敏,并减少 token 浪费。 citeturn0search1
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(或对应的适配器)来接收流式响应。 citeturn0search0 - 客户端工具名称必须与定义完全一致,以避免出现“找不到工具”的错误。 citeturn0search7
4 步设置流程
第 1 步:安全地选择提供商和模型
- 添加正确的适配器,并设置对应的 API 密钥(
OPENAI_API_KEY、ANTHROPIC_API_KEY、GEMINI_API_KEY,或 Ollama 主机)。 - 优先使用适配器提供的按模型选项类型,避免使用无效选项(例如,仅用于视觉的字段)。 citeturn1search3
第 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会要求用户明确批准敏感操作。 citeturn0search1- 工具应职责单一且具备幂等性;返回结构化对象,而不要抛出错误。 citeturn0search1
第 3 步:创建连接适配器和聊天选项
- 服务端:使用
toStreamResponse(stream)进行 HTTP 流式传输;使用toServerSentEventsStream辅助函数处理 Server-Sent Events。 citeturn0search3turn0search4 - 客户端:使用
fetchServerSentEvents('/api/chat');如有需要,可使用适用于 websockets 的自定义适配器。 citeturn0search0 - 配置
agentLoopStrategy(例如maxIterations(8))以限制工具递归调用。 citeturn1search4
第 4 步:添加可观测性和防护措施
- 记录工具执行情况和流分块以便调试;alpha 版已提供钩子,开发者工具仍在开发中。 citeturn0search1
- 使用 Zod 验证输入;尽早失败并返回类型化的错误对象。
- 在工具中的外部 API 调用上强制设置超时,以防 Agent 循环卡住。
关键规则
务必做到
✅ 使用流式响应;避免等待完整响应。 citeturn0search1
✅ 将定义传给服务端,将实现传给正确的运行时。 citeturn0search7
✅ 使用 Zod 模式定义工具的输入和输出,以确保不同提供商之间的类型安全。 citeturn0search1
✅ 使用 maxIterations 限制 Agent 循环,防止工具调用失控。 citeturn1search4
✅ 对具有破坏性或涉及计费的工具启用 needsApproval。 citeturn0search1
切勿这样做
❌ 在单个请求中混用提供商适配器——每次调用只实例化一个适配器。
❌ 从工具中抛出原始错误;应返回结构化错误负载。
❌ 将客户端工具的实现发送到服务端(只发送定义)。
❌ 将模型能力硬编码;应依靠适配器类型定义来处理按模型设置的选项。 citeturn0search1
❌ 跳过 API 密钥检查;应在服务端尽早失败并提供有用的错误消息。 citeturn0search1
预防已知问题
此技能可预防已记录的 3 个问题:
问题 #1:“未找到工具”/工具静默失败
原因:定义未传递给 chat();本地只有实现。
预防措施:单独导出定义,并将其包含在服务端 tools 数组中;保持名称稳定。 citeturn0search7
问题 #2:界面中的流式传输停滞
原因:服务端响应类型与客户端适配器不匹配(HTTP 分块传输与 SSE 不匹配)。
预防措施:在服务端使用 toStreamResponse,并在客户端使用 fetchServerSentEvents(或匹配的适配器)。 citeturn0search1turn0search0
问题 #3:模型选项验证错误
原因:将特定提供商的选项(例如视觉参数)发送给不支持这些选项的模型。
预防措施:使用适配器提供的类型;依靠针对各模型的选项类型,在编译时发现无效字段。 citeturn1search3
配置文件参考
.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:使用有界工具的 Agent 循环
import { chat, maxIterations } from '@tanstack/ai'
import { openai } from '@tanstack/ai-openai'
const stream = chat({
adapter: openai(),
messages,
tools,
agentLoopStrategy: maxIterations(8), // hard cap
})
适用场景:任何大模型可能通过工具递归调用的流程(搜索 → 总结 → 获取详情)。 citeturn1search4
模式 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] })
适用场景:模型必须在一个循环中同时获取数据并更改界面状态。 citeturn0search1
使用打包的资源
脚本(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— 可直接使用的 toolDefinition 示例,包含审批和 zod 架构。
何时加载参考资料
针对特定实现情境加载参考文件:
-
适配器对比:在 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选项。 citeturn1search3 - 对于多模态模型,发送 MIME 类型正确的
parts;不支持的模态会在编译时被发现。 citeturn1search3
工具审批体验
- 通过
useChat中的approval对象呈现;渲染批准/拒绝界面,并为每次工具调用保存决定。 citeturn0search1 - 对于可审计的操作,应将审批决定与工具输入一并记录。
连接适配器
- 如需最简配置,默认使用
fetchServerSentEvents(SSE);如需支持 WebSocket 或 HTTP 分块传输,则切换到自定义适配器。 citeturn0search0 - 在客户端中使用
ImmediateStrategy,以便每个数据块到达时立即发出,适用于显示输入指示器的 UI。 citeturn0search0
依赖项
必需:
- @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 工具与服务端函数放在一起
官方文档
- TanStack AI 概览:https://tanstack.com/ai/latest/docs/getting-started/overview
- 快速入门:https://tanstack.com/ai/latest/docs/getting-started/quick-start
- 工具架构与审批:https://tanstack.com/ai/latest/docs/guides/tool-architecture
- 客户端工具:https://tanstack.com/ai/latest/docs/guides/client-tools
- API 参考:https://tanstack.com/ai/latest/docs/api/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() 前,于路由中快速失败。 citeturn0search1
问题:流式传输在第一个数据块后停止
解决方案:确认服务端返回 toStreamResponse(stream)(或 SSE 助手),并确保任何反向代理都允许分块传输。
完整配置检查清单
使用此清单验证配置:
- 已安装核心软件包、一个适配器和 zod
- API 路由返回包含工具定义的
toStreamResponse(stream) - 客户端使用
fetchServerSentEvents(或匹配的适配器),并注册客户端工具实现 -
needsApproval路径会显示批准/拒绝 UI - Agent 循环已设上限(例如
maxIterations) - 已使用
check-ai-env.sh验证环境密钥 - 如果目标模型支持视觉/音频,已测试多模态输入
有疑问?遇到问题?
- 加载
references/tanstack-ai-cheatsheet.md,查看更多示例 - 使用单个提供方适配器重新执行快速入门步骤
- 查阅上述官方文档,了解 API 接口更新