From 9d198069930f052ca3840b29fc70a03c159887d9 Mon Sep 17 00:00:00 2001 From: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com> Date: Mon, 26 Oct 2026 17:27:39 +1100 Subject: [PATCH 1/3] docs(comparison): add TanStack AI vs pi, focused on where the agent runs --- docs/comparison/pi.md | 103 ++++++++++++++++++++++++++++++++++++++++++ docs/config.json | 5 ++ 2 files changed, 108 insertions(+) create mode 100644 docs/comparison/pi.md diff --git a/docs/comparison/pi.md b/docs/comparison/pi.md new file mode 100644 index 0000000000..a24c20f2fd --- /dev/null +++ b/docs/comparison/pi.md @@ -0,0 +1,103 @@ +--- +title: TanStack AI vs pi +id: pi +order: 2 +description: "Pick between TanStack AI and pi: where the agent runs, when each one fits, how the core APIs map, and a feature table." +keywords: + - tanstack ai + - pi + - pi-ai + - pi-agent-core + - pi-coding-agent + - comparison + - alternatives + - ag-ui + - agent loop + - coding agent +--- + +Pick TanStack AI for an app where a browser talks to an agent on your server. Pick pi for an agent that runs in one process: a terminal coding agent, a bot, or a script. + +Both are open-source TypeScript toolkits under the MIT license. Both stream model output, call tools, run an agent loop, and talk to many providers. The difference is where the agent runs and who reads its events. + +## Where the agent runs + +| | pi | TanStack AI | +| --- | --- | --- | +| The agent loop runs | In your process, next to the code that reads its events | On your server | +| Its events go to | Callbacks in the same process (`agent.subscribe`) | A client over HTTP, as [AG-UI](https://docs.ag-ui.com/) events | +| The UI is | A terminal (`pi-tui`), or your own code in the same process | `useChat` in the browser, for React, Solid, Vue, Svelte, Preact, Angular and more | +| In a browser app | The loop and the tools run in the browser. `streamProxy` sends only the model call through your server, to keep the API key there | The loop and the server tools run on the server. The browser renders the run and runs only client tools | + +So the two toolkits solve different problems: + +- **pi** gives you an agent to embed. You own the process, and the events never leave it. +- **TanStack AI** gives you a client and a server that talk to each other. The protocol, the approvals, the reconnects and the saved history are part of the toolkit. + +## Pick TanStack AI when + +- **You build a web app.** `useChat` renders the run on the client, and the run survives a slow network or a reload. See [UI](../ui/react) and [Resumable Streams](../resumable-streams/overview). +- **Your tools must run on the server.** Database calls, secrets and paid APIs stay on the server. The browser never sees them. +- **You want to define a tool once.** One schema gives the input and output types on the server and on the client. Add `.server()` or `.client()` to run it on either side. See [Tools](../tools/tools). +- **You want people to approve tool calls.** `needsApproval` pauses the run on the server, and the user answers in the browser. See [Tool approval](../tools/tool-approval). +- **You want to own your data.** Persistence writes to your database, in your schema. See [Persistence](../persistence/overview). + +TanStack AI also has these, each in its own package: + +- **Coding-agent harnesses.** Run Claude Code, Codex, OpenCode, Grok Build, or any ACP agent as a chat backend, in a local process or a sandbox. See [Harness](../harness/overview). +- **Subagents.** A tool can run a child agent, and the client shows its run as a card. See [Subagents](../chat/subagents). +- **Media beyond chat.** Images, video, speech, transcription, music and realtime voice use the same adapters and persistence as chat. See [Generations](../media/generations). + +## Pick pi when + +- **Your product is a terminal coding agent.** `pi-coding-agent` is a CLI with read, bash, edit and write tools, sessions, extensions and skills. +- **Your agent has no browser client.** A bot, a CLI or a job reads the agent events in the same Node process. +- **The agent must run on the user's machine.** In a browser app, `streamProxy` keeps the loop and the tools in the browser. +- **You sign in with a model subscription.** pi has OAuth logins for Claude Pro and Max, ChatGPT, GitHub Copilot and OpenRouter. + +## How the core APIs map + +| pi | TanStack AI | +| --------------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| `@earendil-works/pi-ai` | `@tanstack/ai` and one adapter package per provider | +| `createModels()`, `setProvider(anthropicProvider())`, `getModel('anthropic', id)` | `anthropicText(id)` from `@tanstack/ai-anthropic` | +| `models.streamSimple(model, context)` | `chat({ adapter, messages })` | +| `models.completeSimple(model, context)` | `chat({ adapter, messages, stream: false })` | +| The leading `system` message | `systemPrompts: ['...']` | +| `AgentTool` with TypeBox `parameters` and `execute` | `toolDefinition({ inputSchema }).server(fn)` | +| `agentLoop()` or the `Agent` class | `chat({ tools })`, which runs the loop | +| `beforeToolCall` / `afterToolCall` | `middleware: [...]` with tool call hooks | +| `agent.followUp(message)` | The [message queue](../chat/queueing) of `useChat` | +| `agent.subscribe()` and `AgentEvent` | The AG-UI events of `chat()`, read by `useChat` on the client | +| `streamProxy()` in the browser | `toServerSentEventsResponse` on the server, `useChat` on the client | +| `@earendil-works/pi-mcp` | `@tanstack/ai-mcp`. See [MCP](../tools/mcp). | +| `@earendil-works/pi-codemode` | `@tanstack/ai-code-mode`. See [Code Mode](../code-mode/code-mode). | + +## Feature comparison + +Versions: pi `1.4` and TanStack AI 1.0. + +| Feature | pi | TanStack AI | +| ---------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| License | MIT | MIT | +| Main use | An agent in one process: coding agent CLI, and the libraries under it | Full-stack AI apps: server, client and UI hooks | +| Wire protocol | In-process `AgentEvent` objects. Remote sessions over CBOR (`pi-protocol`) | Native AG-UI, in both directions | +| Providers | About 35 in `pi-ai`, plus any OpenAI-compatible API | OpenAI, Anthropic, Gemini, Vertex, Bedrock, Grok, Groq, Mistral, OpenRouter, and more. Any OpenAI-compatible endpoint | +| Subscription logins | OAuth for Claude Pro and Max, ChatGPT, GitHub Copilot, OpenRouter (Node only) | API keys | +| UI | `pi-tui` for the terminal, `pi-web-ui` components | React, Solid, Vue, Svelte, Preact, Angular, Octane, Remix, React Native | +| Tools | `AgentTool` with a TypeBox schema, run in the agent | One `toolDefinition()`, with `.server()` and `.client()` | +| Tool approval | `beforeToolCall` can block a call | Per-tool `needsApproval`, with batched approvals and interrupts | +| Steering and follow-up | Built-in queues on the `Agent` | A message queue in `useChat` | +| Subagents | Not built in | Built in, with a card per child run | +| Structured output | Constrained sampling for tool arguments | Typed message part, streamed with tools and kept in the history | +| Token usage | Usage and cost on each assistant message | Usage on each model call | +| Persistence | SQLite session backends. `pi-durable` is experimental | `withPersistence` middleware, server or browser stores | +| Resumable streams | `pi-durable` resumes a turn after a crash (experimental) | Built in. `useChat` reconnects by itself | +| MCP client | `pi-mcp`: stdio and Streamable HTTP | `@tanstack/ai-mcp`: multi-server pools, generated types, lazy tools, managed lifecycle | +| Code Mode | `pi-codemode`: QuickJS on Node, Bun and Cloudflare | 6 isolate drivers: Node, QuickJS WASM, QuickJS Bun, Cloudflare, Daytona, E2B | +| Coding agents | `pi-coding-agent`, a CLI with extensions, skills and themes | Claude Code, Codex, OpenCode, Grok Build, and any ACP agent, on a local process or a sandbox | +| Image | Image generation through OpenRouter | Stable, typed per model | +| Video, speech, music | Not built in | Stable | +| Realtime voice | Not built in | Stable: OpenAI, Grok, ElevenLabs | + +To try TanStack AI, start with the [Quick Start](../getting-started/quick-start). diff --git a/docs/config.json b/docs/config.json index 2577af99fb..2aee94c62b 100644 --- a/docs/config.json +++ b/docs/config.json @@ -166,6 +166,11 @@ "to": "comparison/vercel-ai-sdk", "addedAt": "2026-04-15", "updatedAt": "2026-10-22" + }, + { + "label": "TanStack AI vs pi", + "to": "comparison/pi", + "addedAt": "2026-10-26" } ], "tab": "get-started" From d408a2c9b0ad0def3414c5482b8dfe50fcdc0748 Mon Sep 17 00:00:00 2001 From: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com> Date: Mon, 26 Oct 2026 18:01:29 +1100 Subject: [PATCH 2/3] docs(comparison): correct pi and TanStack AI claims - Say pi events stay in-process by default; pi-protocol and RPC mode can send them out - Link coding-agent harnesses to harness/coding-agents and mark the harness experimental - Note harness steering in the steering row - Fix pi subagents, persistence, getModel and systemPrompt cells; drop pi-web-ui - Reword the pi-coding-agent bullet in our own words - Add Gemini to realtime voice and cost to token usage (Vercel page too) --- docs/comparison/pi.md | 22 +++++++++++----------- docs/comparison/vercel-ai-sdk.md | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/comparison/pi.md b/docs/comparison/pi.md index a24c20f2fd..d973867c59 100644 --- a/docs/comparison/pi.md +++ b/docs/comparison/pi.md @@ -31,7 +31,7 @@ Both are open-source TypeScript toolkits under the MIT license. Both stream mode So the two toolkits solve different problems: -- **pi** gives you an agent to embed. You own the process, and the events never leave it. +- **pi** gives you an agent to embed. You own the process, and by default the events stay in it. `pi-protocol` and RPC mode can send them to another process. - **TanStack AI** gives you a client and a server that talk to each other. The protocol, the approvals, the reconnects and the saved history are part of the toolkit. ## Pick TanStack AI when @@ -44,13 +44,13 @@ So the two toolkits solve different problems: TanStack AI also has these, each in its own package: -- **Coding-agent harnesses.** Run Claude Code, Codex, OpenCode, Grok Build, or any ACP agent as a chat backend, in a local process or a sandbox. See [Harness](../harness/overview). +- **Coding-agent harnesses.** Run Claude Code, Codex, OpenCode, Grok Build, or any ACP agent as a chat backend, in a local process or a sandbox. The harness is experimental. See [Coding agents](../harness/coding-agents). - **Subagents.** A tool can run a child agent, and the client shows its run as a card. See [Subagents](../chat/subagents). - **Media beyond chat.** Images, video, speech, transcription, music and realtime voice use the same adapters and persistence as chat. See [Generations](../media/generations). ## Pick pi when -- **Your product is a terminal coding agent.** `pi-coding-agent` is a CLI with read, bash, edit and write tools, sessions, extensions and skills. +- **Your product is a terminal coding agent.** `pi-coding-agent` is a terminal agent that reads, edits and runs code in your repo. It saves sessions and loads extensions and skills. - **Your agent has no browser client.** A bot, a CLI or a job reads the agent events in the same Node process. - **The agent must run on the user's machine.** In a browser app, `streamProxy` keeps the loop and the tools in the browser. - **You sign in with a model subscription.** pi has OAuth logins for Claude Pro and Max, ChatGPT, GitHub Copilot and OpenRouter. @@ -60,10 +60,10 @@ TanStack AI also has these, each in its own package: | pi | TanStack AI | | --------------------------------------------------------------------------------- | ------------------------------------------------------------------ | | `@earendil-works/pi-ai` | `@tanstack/ai` and one adapter package per provider | -| `createModels()`, `setProvider(anthropicProvider())`, `getModel('anthropic', id)` | `anthropicText(id)` from `@tanstack/ai-anthropic` | +| `createModels()`, `setProvider(anthropicProvider())`, `models.getModel('anthropic', id)` | `anthropicText(id)` from `@tanstack/ai-anthropic` | | `models.streamSimple(model, context)` | `chat({ adapter, messages })` | | `models.completeSimple(model, context)` | `chat({ adapter, messages, stream: false })` | -| The leading `system` message | `systemPrompts: ['...']` | +| `systemPrompt` in the context | `systemPrompts: ['...']` | | `AgentTool` with TypeBox `parameters` and `execute` | `toolDefinition({ inputSchema }).server(fn)` | | `agentLoop()` or the `Agent` class | `chat({ tools })`, which runs the loop | | `beforeToolCall` / `afterToolCall` | `middleware: [...]` with tool call hooks | @@ -84,20 +84,20 @@ Versions: pi `1.4` and TanStack AI 1.0. | Wire protocol | In-process `AgentEvent` objects. Remote sessions over CBOR (`pi-protocol`) | Native AG-UI, in both directions | | Providers | About 35 in `pi-ai`, plus any OpenAI-compatible API | OpenAI, Anthropic, Gemini, Vertex, Bedrock, Grok, Groq, Mistral, OpenRouter, and more. Any OpenAI-compatible endpoint | | Subscription logins | OAuth for Claude Pro and Max, ChatGPT, GitHub Copilot, OpenRouter (Node only) | API keys | -| UI | `pi-tui` for the terminal, `pi-web-ui` components | React, Solid, Vue, Svelte, Preact, Angular, Octane, Remix, React Native | +| UI | `pi-tui` for the terminal | React, Solid, Vue, Svelte, Preact, Angular, Octane, Remix, React Native | | Tools | `AgentTool` with a TypeBox schema, run in the agent | One `toolDefinition()`, with `.server()` and `.client()` | | Tool approval | `beforeToolCall` can block a call | Per-tool `needsApproval`, with batched approvals and interrupts | -| Steering and follow-up | Built-in queues on the `Agent` | A message queue in `useChat` | -| Subagents | Not built in | Built in, with a card per child run | +| Steering and follow-up | Built-in queues on the `Agent` | A message queue in `useChat`. The harness also steers a running turn (experimental) | +| Subagents | Task-owned child conversations in `pi-durable` (experimental) | Built in, with a card per child run | | Structured output | Constrained sampling for tool arguments | Typed message part, streamed with tools and kept in the history | -| Token usage | Usage and cost on each assistant message | Usage on each model call | -| Persistence | SQLite session backends. `pi-durable` is experimental | `withPersistence` middleware, server or browser stores | +| Token usage | Usage and cost on each assistant message | Usage on each model call, and cost when the provider reports it | +| Persistence | JSONL session files with branching. `pi-durable` is experimental | `withPersistence` middleware, server or browser stores | | Resumable streams | `pi-durable` resumes a turn after a crash (experimental) | Built in. `useChat` reconnects by itself | | MCP client | `pi-mcp`: stdio and Streamable HTTP | `@tanstack/ai-mcp`: multi-server pools, generated types, lazy tools, managed lifecycle | | Code Mode | `pi-codemode`: QuickJS on Node, Bun and Cloudflare | 6 isolate drivers: Node, QuickJS WASM, QuickJS Bun, Cloudflare, Daytona, E2B | | Coding agents | `pi-coding-agent`, a CLI with extensions, skills and themes | Claude Code, Codex, OpenCode, Grok Build, and any ACP agent, on a local process or a sandbox | | Image | Image generation through OpenRouter | Stable, typed per model | | Video, speech, music | Not built in | Stable | -| Realtime voice | Not built in | Stable: OpenAI, Grok, ElevenLabs | +| Realtime voice | Not built in | Stable: OpenAI, Gemini, Grok, ElevenLabs | To try TanStack AI, start with the [Quick Start](../getting-started/quick-start). diff --git a/docs/comparison/vercel-ai-sdk.md b/docs/comparison/vercel-ai-sdk.md index 2f02f850c9..93e2058496 100644 --- a/docs/comparison/vercel-ai-sdk.md +++ b/docs/comparison/vercel-ai-sdk.md @@ -190,7 +190,7 @@ Versions: Vercel AI SDK `ai@7.x` and TanStack AI 1.0. | Speech and transcription | Marked experimental | Stable. Word timestamps and diarization | | Music and sound effects | - | `generateAudio()` | | Live worlds and live video | - | Reactor and World Labs adapters | -| Realtime voice | Experimental `experimental_useRealtime` | Stable: OpenAI, Grok, ElevenLabs | +| Realtime voice | Experimental `experimental_useRealtime` | Stable: OpenAI, Gemini, Grok, ElevenLabs | | Devtools | `devToolsMiddleware` and a local inspector (server, dev only) | In-app panel for the server and the client | To move an app, start with [Migration from Vercel AI SDK](../migration/migration-from-vercel-ai). From b99b039c6cb3a1342e0ca0c2dab70015ca86d47a Mon Sep 17 00:00:00 2001 From: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com> Date: Tue, 27 Oct 2026 20:53:29 +1100 Subject: [PATCH 3/3] docs(comparison): pi is single-process, TanStack AI does that plus client/server --- docs/comparison/pi.md | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/docs/comparison/pi.md b/docs/comparison/pi.md index d973867c59..d8e9dd0a71 100644 --- a/docs/comparison/pi.md +++ b/docs/comparison/pi.md @@ -2,7 +2,7 @@ title: TanStack AI vs pi id: pi order: 2 -description: "Pick between TanStack AI and pi: where the agent runs, when each one fits, how the core APIs map, and a feature table." +description: "Pick between TanStack AI and pi: where the agent can run, when each one fits, how the core APIs map, and a feature table." keywords: - tanstack ai - pi @@ -16,44 +16,41 @@ keywords: - coding agent --- -Pick TanStack AI for an app where a browser talks to an agent on your server. Pick pi for an agent that runs in one process: a terminal coding agent, a bot, or a script. +pi is built for an agent that runs in one process: a terminal coding agent, a bot, or a script. TanStack AI does that too, and it also lets you split the agent across a client and a server. Pick pi if you want pi's coding agent CLI or its subscription logins. Pick TanStack AI for everything else, and for any app with a browser in it. -Both are open-source TypeScript toolkits under the MIT license. Both stream model output, call tools, run an agent loop, and talk to many providers. The difference is where the agent runs and who reads its events. +Both are open-source TypeScript toolkits under the MIT license. Both stream model output, call tools, run an agent loop, and talk to many providers. The difference is where the agent can run. ## Where the agent runs | | pi | TanStack AI | | --- | --- | --- | -| The agent loop runs | In your process, next to the code that reads its events | On your server | -| Its events go to | Callbacks in the same process (`agent.subscribe`) | A client over HTTP, as [AG-UI](https://docs.ag-ui.com/) events | -| The UI is | A terminal (`pi-tui`), or your own code in the same process | `useChat` in the browser, for React, Solid, Vue, Svelte, Preact, Angular and more | -| In a browser app | The loop and the tools run in the browser. `streamProxy` sends only the model call through your server, to keep the API key there | The loop and the server tools run on the server. The browser renders the run and runs only client tools | +| In one process | Yes. `agentLoop()` runs next to the code that reads its events (`agent.subscribe`) | Yes. `chat()` returns an async stream you read in the same process. A harness keeps a session open across turns | +| In a terminal | `pi-tui`, or `pi-coding-agent` | `runCli` from `@tanstack/ai-harness-cli`: line mode, print mode for scripts and CI, NDJSON, and ACP for editors | +| Split across client and server | Not built in. `pi-protocol` and RPC mode can send events to another process. `streamProxy` keeps the loop in the browser and sends only the model call through your server | Built in. The loop and the server tools run on the server. The browser gets [AG-UI](https://docs.ag-ui.com/) events over HTTP and renders them with `useChat` | +| With a browser UI | Your own code | `useChat` for React, Solid, Vue, Svelte, Preact, Angular and more, with approvals, reconnects and saved history | -So the two toolkits solve different problems: - -- **pi** gives you an agent to embed. You own the process, and by default the events stay in it. `pi-protocol` and RPC mode can send them to another process. -- **TanStack AI** gives you a client and a server that talk to each other. The protocol, the approvals, the reconnects and the saved history are part of the toolkit. +So pi gives you an agent to embed in one process. TanStack AI gives you the same agent, plus a client and a server that talk to each other when you need them. ## Pick TanStack AI when +- **You build a terminal agent, a bot, or a script.** `chat()` runs the loop in your process. A [harness](../harness/overview) keeps the conversation open, queues and steers messages, and runs typed agents from code. See [Run a harness in the terminal](../harness/cli). - **You build a web app.** `useChat` renders the run on the client, and the run survives a slow network or a reload. See [UI](../ui/react) and [Resumable Streams](../resumable-streams/overview). - **Your tools must run on the server.** Database calls, secrets and paid APIs stay on the server. The browser never sees them. - **You want to define a tool once.** One schema gives the input and output types on the server and on the client. Add `.server()` or `.client()` to run it on either side. See [Tools](../tools/tools). -- **You want people to approve tool calls.** `needsApproval` pauses the run on the server, and the user answers in the browser. See [Tool approval](../tools/tool-approval). -- **You want to own your data.** Persistence writes to your database, in your schema. See [Persistence](../persistence/overview). +- **You want people to approve tool calls.** `needsApproval` pauses the run, and the user answers in the terminal or in the browser. See [Tool approval](../tools/tool-approval). TanStack AI also has these, each in its own package: - **Coding-agent harnesses.** Run Claude Code, Codex, OpenCode, Grok Build, or any ACP agent as a chat backend, in a local process or a sandbox. The harness is experimental. See [Coding agents](../harness/coding-agents). - **Subagents.** A tool can run a child agent, and the client shows its run as a card. See [Subagents](../chat/subagents). +- **Persistence.** Writes to your database, in your schema. See [Persistence](../persistence/overview). - **Media beyond chat.** Images, video, speech, transcription, music and realtime voice use the same adapters and persistence as chat. See [Generations](../media/generations). ## Pick pi when -- **Your product is a terminal coding agent.** `pi-coding-agent` is a terminal agent that reads, edits and runs code in your repo. It saves sessions and loads extensions and skills. -- **Your agent has no browser client.** A bot, a CLI or a job reads the agent events in the same Node process. -- **The agent must run on the user's machine.** In a browser app, `streamProxy` keeps the loop and the tools in the browser. +- **You want pi's coding agent as the product.** `pi-coding-agent` is a finished terminal agent that reads, edits and runs code in your repo. It saves sessions and loads extensions and skills. - **You sign in with a model subscription.** pi has OAuth logins for Claude Pro and Max, ChatGPT, GitHub Copilot and OpenRouter. +- **The loop must stay in the browser.** `streamProxy` keeps the loop and the tools on the user's machine and sends only the model call through your server. ## How the core APIs map @@ -80,11 +77,11 @@ Versions: pi `1.4` and TanStack AI 1.0. | Feature | pi | TanStack AI | | ---------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | License | MIT | MIT | -| Main use | An agent in one process: coding agent CLI, and the libraries under it | Full-stack AI apps: server, client and UI hooks | +| Main use | An agent in one process: coding agent CLI, and the libraries under it | Agents in one process, in a terminal, or split across client and server | | Wire protocol | In-process `AgentEvent` objects. Remote sessions over CBOR (`pi-protocol`) | Native AG-UI, in both directions | | Providers | About 35 in `pi-ai`, plus any OpenAI-compatible API | OpenAI, Anthropic, Gemini, Vertex, Bedrock, Grok, Groq, Mistral, OpenRouter, and more. Any OpenAI-compatible endpoint | | Subscription logins | OAuth for Claude Pro and Max, ChatGPT, GitHub Copilot, OpenRouter (Node only) | API keys | -| UI | `pi-tui` for the terminal | React, Solid, Vue, Svelte, Preact, Angular, Octane, Remix, React Native | +| UI | `pi-tui` for the terminal | Terminal (`runCli`), plus React, Solid, Vue, Svelte, Preact, Angular, Octane, Remix, React Native | | Tools | `AgentTool` with a TypeBox schema, run in the agent | One `toolDefinition()`, with `.server()` and `.client()` | | Tool approval | `beforeToolCall` can block a call | Per-tool `needsApproval`, with batched approvals and interrupts | | Steering and follow-up | Built-in queues on the `Agent` | A message queue in `useChat`. The harness also steers a running turn (experimental) |