TanStack AI Tutorial: Build a Chat Agent With Tool Calling
A runnable TanStack AI 1.0 tutorial: install, stream a chat() server route, define a toolDefinition() that calls the live TrendsAGI trend API, and render it.

This TanStack AI tutorial builds a working chat agent on TanStack AI 1.0 that streams tokens to the browser and calls a real external API as a tool. We use the TrendsAGI trend intelligence API as the external tool so the agent answers with live trend signals instead of guesses, but the same wiring works for any HTTP API.
TanStack AI 1.0 shipped on October 23, 2026, moving its core chat(), tools, and provider APIs from RC to stable production status (tanstack.com). That release removed every API deprecated in 0.x and requires upgrading all stable @tanstack/ai* packages together, which is why so many 0.x and alpha users are searching for a current walkthrough right now. Below you get the install, the server route, the tool, the UI, the upgrade path, and an honest split between stable 1.0 APIs and the experimental agent harness.
What is TanStack AI, and what changed in 1.0
TanStack AI is a provider-agnostic toolkit for building AI chat and tool-calling features: a core chat() API, a tool definition layer, and provider adapters that let you point the same app at different model vendors. The 1.0 release covers 23 provider adapters, nine UI frameworks, 11 sandbox providers, MCP support in both directions, and an experimental agent harness with subagents (tanstack.com).
Three changes matter for anyone following a tutorial written before October 2026:
- Stable core, experimental harness. 1.0 ships stable core APIs, while the new agent harness APIs are marked experimental (tanstack.com).
- Version lockstep. A 1.0 client needs a 1.0 server, so all stable
@tanstack/ai*packages must move together, while harness packages stay on 0.x (tanstack.com). - A codemod-first upgrade. The upgrade path for most apps is a jscodeshift codemod plus a type check (tanstack.com).
What is not verified here: TanStack AI pricing, rate-limit numbers, or any usage quotas. No official pricing page appeared in the sources we reviewed, so treat cost planning as something to confirm with your provider.
Before you start: what you need
- Node and a package manager, plus a React app if you want the UI section to run unchanged. Other supported frameworks follow the same shape with their own hook package.
- A provider API key for whichever adapter you pick.
- A TrendsAGI API key, created in your account profile at trendsagi.com, exported as
TRENDSAGI_API_KEY.
TanStack's own Quick Start adds a server route, an API key, and a UI, producing a streaming chat in about five minutes (tanstack.com). This tutorial keeps that skeleton and replaces the toy tool with a live data call.
Step 1: Install TanStack AI 1.0 packages
A basic setup installs @tanstack/ai, a UI package such as @tanstack/ai-react, and a provider package such as @tanstack/ai-openai (github.com, @tanstack/ai API reference). Pin the stable packages to the same 1.0 line.
npm install @tanstack/ai @tanstack/ai-react @tanstack/ai-openai
npm install trendsagi
The trendsagi Python package is for a separate Python service or agent; skip it if your tool call goes straight to the REST API over HTTP. Nothing about the TanStack install changes because of it.
Step 2: Wire a server chat() route that streams
TanStack AI's chat() runs on the server and can be streamed with toServerSentEventsResponse, which sets Content-Type: text/event-stream (github.com). Give chat() an agentLoopStrategy such as maxIterations(20) so the agent can take several tool turns instead of stopping after one (github.com).
import { chat, toServerSentEventsResponse, maxIterations } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
import { trendsTool } from "./tools/trends";
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = chat({
adapter: openaiText("your-model-name"),
messages,
tools: [trendsTool],
agentLoopStrategy: maxIterations(20),
retry: { maxAttempts: 3 },
});
return toServerSentEventsResponse(stream);
}
Two notes. First, retry exists in the documented chat({ retry }) options for rate limits, but no concrete default limits are published, so your own backoff numbers are still your call. Second, the exact model identifier and option names are the part most likely to drift; check the adapter page in the @tanstack/ai API reference before you debug anything else.
Step 3: Define the external tool
TanStack AI 1.0 tools are defined with toolDefinition(); isomorphic tools can carry server-side and client-side execution. The shape described publicly is a schema plus handler, with the handler free to call any API. Treat the snippet below as the pattern, not a byte-exact copy — confirm parameter names against the current reference.
import { toolDefinition } from "@tanstack/ai";
import { z } from "zod";
export const trendsTool = toolDefinition({
name: "list_trends",
description:
"List live trending topics with measured velocity. Use when the user asks what is trending now.",
inputSchema: z.object({
category: z.string().optional(),
sort_by: z.enum(["velocity", "growth", "volume", "timestamp", "name"]).optional(),
limit: z.number().int().min(1).max(50).optional(),
}),
execute: async ({ category, sort_by, limit }) => {
const params = new URLSearchParams();
if (category) params.set("category", category);
if (sort_by) params.set("sort_by", sort_by);
params.set("limit", String(limit ?? 5));
const res = await fetch(
`https://api.trendsagi.com/api/trends?${params.toString()}`,
{ headers: { "X-API-Key": process.env.TRENDSAGI_API_KEY! } }
);
if (!res.ok) throw new Error(`TrendsAGI ${res.status}`);
return await res.json();
},
});
Why this tool is useful for a tutorial: TanStack AI defines the contract and routes the call, while TrendsAGI owns the data. The API returns topics with measured velocity — posts per hour computed from stored snapshots — not a forecast or a unique-user count. Keep that language in the tool description and the agent will avoid overclaiming.
Adding a second, richer tool
Once the list tool works, add a detail tool so the agent can go one level deeper before answering. The endpoint is GET /api/trends/{id}/ai-insights, and it returns an AI summary, key themes, sentiment, audience, and marketing angles.
const insights = await fetch(
`https://api.trendsagi.com/api/trends/${id}/ai-insights`,
{ headers: { "X-API-Key": process.env.TRENDSAGI_API_KEY! } }
).then((r) => r.json());
If the user asks how a topic moved rather than what it says, the analytics endpoint accepts period=24h|7d|30d. Two tools with clear descriptions beat one tool with a vague one, because the agent decides which to call from the descriptions alone.
Step 4: Render streamed tokens and tool results
TanStack AI ships UI framework hooks so the browser side is short. The docs list packages across React, Vue, Solid, Svelte, Preact, Angular and others, with hook names following the same convention in each (tanstack.com). In React, useChat consumes the event stream from your route.
import { useChat } from "@tanstack/ai-react";
export function Agent() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: "/api/chat",
});
return (
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button disabled={isLoading}>Send</button>
<ul>
{messages.map((m) => (
<li key={m.id}><strong>{m.role}</strong> {m.content}</li>
))}
</ul>
</form>
);
}
Tool calls appear as part of the message stream, so you can render a "calling list_trends" state while the request is in flight and swap in the result when it lands. The hook's exact return fields are the fastest thing to verify locally: log the message object once and map from what you actually receive.
Step 5: Choosing a provider adapter
1.0 offers 23 provider adapters plus openaiCompatible for any OpenAI-style API (tanstack.com). Three choices cover most tutorials:
| Adapter | Use it when | Trade-off |
|---|---|---|
openaiText | You already have an OpenAI key and want the shortest path | Ties the example to one vendor's model names |
openRouterText | You want to try several models without rewriting integration code | The OpenRouter adapter gives access to 400+ models through one API (openrouter.ai), so model choice becomes a config decision you must actually manage |
openaiCompatible | Your provider or self-hosted gateway speaks the OpenAI shape | Tool-calling fidelity varies by endpoint; test your tool before trusting it |
No source we reviewed publishes a comparison of tool-calling behavior across all 23 adapters, so we will not pretend to rank them. The honest advice: build the tutorial on one adapter, then re-run the same tool against a second adapter and diff the transcript.
Step 6: Upgrade a 0.x or alpha app to 1.0
The 1.0 announcement is the authority here, and its upgrade section is truncated mid-way, so treat this as a checklist rather than a complete migration script.
- Move every stable
@tanstack/ai*package to the same 1.0 version in one commit. A 1.0 client needs a 1.0 server (tanstack.com). - Leave harness packages on 0.x, since they are separate from the stable line.
- Run the jscodeshift codemod the release provides, then a full type check, which is described as the path for most apps (tanstack.com).
- Fix what the type check surfaces: 1.0 removed every API deprecated in 0.x, so leftovers fail loudly rather than silently.
- Re-test the stream response headers; if you replaced a hand-rolled handler, confirm
toServerSentEventsResponseis what your route returns.
Unconfirmed: whether harness packages can run alongside stable 1.0 packages without conflicts beyond the stated 0.x split. If you need both, isolate them and test early.
Stable chat() vs tools vs the experimental harness
| Need | Use | Status |
|---|---|---|
| Streaming chat with one or two tools | chat() plus toolDefinition() | Stable in 1.0 |
| Multi-step external API calls | agentLoopStrategy: maxIterations(n) | Stable in 1.0 |
| Delegation across specialised agents | Agent harness and subagents | Experimental (tanstack.com) |
| Consuming third-party tools | MCP server tools, managed MCP with chat(), or manual MCP | Documented in latest docs |
| Publishing your own tools | createMCPServer for Claude Desktop, Cursor and other hosts | 1.0 (tanstack.com) |
Most tutorials, including this one, only need the first two rows. Reach for the harness when a single agent loop becomes unmanageable, not on day one.
Calling TrendsAGI over MCP instead of REST
If you would rather expose trends as an MCP tool than hand-write a fetch, TrendsAGI hosts a Streamable HTTP MCP server at https://api.trendsagi.com/mcp using OAuth 2.1 sign-in or an API key as a Bearer token, with read-only tools. TanStack AI documents MCP server tools, managed MCP with chat(), and manual MCP (tanstack.com), so both sides speak the same protocol. Two ways to connect:
claude mcp add --transport http trendsagi https://api.trendsagi.com/mcp
Or locally, with the Python MCP server installed via pip install "trendsagi[mcp]" and TRENDSAGI_API_KEY set, run trendsagi mcp. Each tool call counts as one API request. If your agent runs in Python rather than inside TanStack, the SDK's TrendsAGITools wrapper returns OpenAI, Anthropic or LangChain tool schemas from the same client, which is handy for cross-checking that a TanStack tool definition and an MCP tool describe the same capability.
When wiring a webhook or MCP delivery, do not assume a payload shape: send a test delivery and map fields from what arrives.
Frequently asked questions
How do I install TanStack AI 1.0 packages and wire a server chat() route that streams to the browser?
Install @tanstack/ai, a UI package such as @tanstack/ai-react, and a provider package such as @tanstack/ai-openai at matching 1.0 versions (github.com). In a server route, call chat() with your adapter, messages and tools, then return toServerSentEventsResponse(stream), which sets the text/event-stream content type.
How do I define an isomorphic tool with toolDefinition() and call an external API from it?
Use toolDefinition() with a name, a description, an input schema, and an execute handler that performs the fetch. Keeping the handler side-effect free until execution means the same definition can describe a tool to the model while the server owns the real API call, as in the TrendsAGI example above. Confirm the exact parameter names in the current @tanstack/ai reference, since this is the area most affected by the 1.0 cleanup.
How do I render streamed tokens and tool results in a UI framework hook like useChat?
Import useChat from your framework package, point api at your server route, and render the messages array as it grows; the package exists for React, Vue, Solid, Svelte, Preact, Angular and others (tanstack.com). Tool calls arrive within that same stream, so render a pending state for the call and the result when it resolves.
What broke between 0.x and 1.0, and how do I run the codemod and upgrade all packages together?
1.0 removed every API deprecated in 0.x and requires all stable @tanstack/ai* packages to upgrade together, because a 1.0 client needs a 1.0 server (tanstack.com). The documented path for most apps is the jscodeshift codemod followed by a type check; the official announcement is truncated partway through that section, so verify the exact command flags in the current upgrade docs.
How do I choose a provider adapter (e.g. openaiText, openRouterText, openaiCompatible) and pass a model?
Pick openaiText if you already use OpenAI, openRouterText if you want 400+ models behind one API (openrouter.ai), and openaiCompatible for any OpenAI-style endpoint. You pass the model identifier to the adapter factory, as in openaiText("your-model-name"), and confirm the accepted string in your provider's docs.
When do I need the experimental agent harness, subagents, or MCP, versus plain chat()?
Plain chat() with an agentLoopStrategy covers a streaming assistant that calls a few tools, and that part is stable in 1.0. The agent harness with subagents is marked experimental (tanstack.com), so choose it only when delegation genuinely simplifies your design; choose MCP when you want to consume or publish tools across hosts rather than hard-code integrations.
Is there an official TanStack AI price list or rate limit I should budget for?
Not in the sources reviewed here. Model costs come from your chosen provider, and while chat({ retry }) exists for rate limits, no concrete limits are published in the pages we checked. Confirm both with your provider before committing to a plan.
How we researched this
Prepared by TrendsAGI Research. Facts checked on 5 November 2026 against the sources listed below.
We read the official TanStack AI documentation listed below. The TrendsAGI steps and code use its documented REST API and Python SDK; confirm the TanStack AI side against its current documentation, since third-party products change.
| Claim | Applies to | Source |
|---|---|---|
| TanStack AI 1.0 ships stable core APIs, with the new agent harness APIs marked experimental. | 1.0 | tanstack.com |
| 1.0 offers 23 provider adapters plus openaiCompatible for any OpenAI-style API. | 1.0 | tanstack.com |
| TanStack AI supports eight-to-nine UI frameworks across React, Vue, Solid, Svelte, Preact, Angular, Octane, Remix and vanilla JS. | 1.0 | tanstack.com |
| 1.0 requires upgrading all stable @tanstack/ai* packages together, since a 1.0 client needs a 1.0 server, while harness packages stay on 0.x. | 1.0 | tanstack.com |
| The upgrade path for most apps is a jscodeshift codemod plus a type check. | 0.x to 1.0 | tanstack.com |
| chat() server routes can be streamed with toServerSentEventsResponse, which sets Content-Type text/event-stream. | 1.0 | github.com |
| chat() accepts an agentLoopStrategy option such as maxIterations(20). | 1.0 | github.com |
| A basic setup installs @tanstack/ai, a UI package such as @tanstack/ai-react, and a provider package such as @tanstack/ai-openai. | All plans | github.com |
| The OpenRouter adapter (@tanstack/ai-openrouter) gives access to 400+ models through one API. | All plans | openrouter.ai |
| The Quick Start adds a server route, an API key, and a UI, producing a streaming chat in about five minutes. | latest docs | tanstack.com |
| TanStack AI has dedicated docs pages for MCP server tools, managed MCP with chat(), and manual MCP. | latest docs | tanstack.com |
| createMCPServer serves TanStack tools as an MCP server for Claude Desktop, Cursor and other MCP hosts. | 1.0 | tanstack.com |
Sources
- TanStack AI 1.0: Still Your AI, Still Your Way — tanstack.com
- @tanstack/ai API reference (GitHub (TanStack/ai)) — github.com
- TanStack AI Integration - OpenRouter SDK Support — openrouter.ai