Library / SDK
tambo-ai/tambo avatar
tambo-ai/tambo

Tambo: a React toolkit that turns Zod schemas into LLM tool definitions

Generative UI SDK for React

11,183 stars563 forksTypeScriptMIT

At a glance

What is it?
Tambo registers your React components with Zod prop schemas, converts them into LLM tool calls, and streams the resulting props back into the UI. It is a sensible fit for teams already committed to React and TypeScript; the hosted backend and the young API surface are the parts to scrutinise before adopting.
Who is it for?
Adopt Tambo if your app is already React plus TypeScript and you want the agent loop, streaming, and conversation state handled for you rather than assembled from parts. Skip it if you need server-rendered output with no client runtime, or if you cannot accept a backend that owns thread state.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Tambo solves is prop plumbing, not chat

Most React apps that add an assistant end up writing the same glue twice. First you wire a chat panel to a model. Then you discover that the model's answer is text, and your app needs a chart, a cart, or a task board. The usual fix is to parse structured output and hand-write a switch statement mapping intent strings to component renders, which grows a branch every time you add a feature.

Tambo takes a different position. You register the components you already have, describe their props with Zod, and the library turns those schemas into LLM tool definitions. The README states the agent "calls them like functions and Tambo renders the result." The model is not choosing between text and a component; the component is the tool call.

The audience is narrow and worth stating plainly. This is for React and TypeScript teams who already have a component library and want an agent to drive it. It is not a chat widget you drop into a marketing page, and it is not framework-agnostic. The README calls it "the open-source generative UI toolkit for React," and the package is published as @tambo-ai/react. If your frontend is Vue, Svelte, or server-rendered templates, the SDK's core abstraction does not apply to you.

Zod schemas become tool definitions, and props arrive as a stream

The mechanism has three parts. A component registry, a provider, and hooks.

The registry is an array of TamboComponent objects. Each entry carries a name, a description, the component itself, and a propsSchema built with Zod. In the README example, a Graph component declares data as an array of name and value pairs and type as an enum of line, bar, or pie. That schema is what the model sees. The description field is the only thing telling the model when to reach for Graph rather than something else, which makes it documentation the model reads at inference time.

A second registration path exists for components that should survive across turns. The withInteractable helper wraps a component with a componentName, description, and propsSchema. The README contrasts the two: generative components "render once in response to a message," while interactable components "persist and update as users refine requests." A chart is generative. A cart, spreadsheet, or task board is interactable. That split is the most useful design decision in the library, because it forces you to decide whether a piece of UI is an answer or a document.

The provider is TamboProvider, which wraps the app and takes an apiKey, a components array, and either userKey or userToken. The README is explicit that one of the two identity props is required, and that they serve different environments: userKey for "server-side or trusted environments," userToken (an OAuth access token) for "client-side apps where the token contains the user identity." That distinction matters more than it looks. Choosing userKey in a browser context means the client asserts who it is.

On top of the provider sit the hooks. useTambo() returns messages, streaming state, and thread management. useTamboThreadInput() returns value, setValue, submit, and isPending. The README's own snippet destructures isStreaming from the first and isPending from the second, which are separate states: one describes the model still producing props, the other describes a submission in flight. Treating them as one boolean will produce UI that flickers between turns.

Scaffolding, provider config, and the self-hosted Docker path

The quickstart is three commands. npm create tambo-app my-tambo-app, which the README notes "auto-initializes git + tambo setup," then cd my-tambo-app, then npm run dev. That is the whole getting-started section, so the interesting configuration lives in the provider rather than in a config file.

The provider takes apiKey, userKey or userToken, and components. In the README example the key comes from process.env.NEXT_PUBLIC_TAMBO_API_KEY, which is a Next.js convention and a hint about the intended host framework. Note the NEXT_PUBLIC_ prefix: that value is shipped to the browser. If you use the hosted backend, the key is client-visible by design, and the security boundary is the userToken rather than the API key.

The backend is the part with a real decision in it. The README describes two modes. Tambo Cloud is "a hosted backend that manages conversation state and agent orchestration," free to start with credits. Self-hosted "runs the same backend on your infrastructure via Docker." Two claims are worth testing before you commit: whether "the same backend" means feature parity, and how conversation data is stored in each mode. The README does not say.

Model access is bring-your-own-key. The README lists OpenAI, Anthropic, Gemini, Mistral, "or any OpenAI-compatible provider." It also says Tambo works with agent frameworks like LangChain and Mastra but that they are "not required." That phrasing suggests Tambo sits below those frameworks rather than competing with them: it owns the render loop, they own the reasoning loop, and you can use both or neither.

Two failure modes worth designing around

The first is schema drift. The model only knows what the propsSchema and description tell it. If a component's props change and the schema is not updated in the same commit, the agent will keep emitting props that no longer match, and the failure appears at render time rather than at build time. Nothing in the README describes a build step that validates registered schemas against the components they wrap. In a codebase where components are edited by people who are not thinking about the agent registry, this will happen.

The second is the interactable component lifecycle. Interactable components "persist and update as users refine requests." Persistence implies state that outlives a single message, and the README does not describe how that state is keyed, merged, or discarded. The provider example passes an explicit id to the interactable (id="note-1"), which suggests identity is your responsibility rather than the library's. If two users, or two threads, generate a note with the same id, the behaviour is not documented in the material available.

There is also a boundary case the README implies but does not address. Because props stream as the model generates them, a component must tolerate partial props. A chart that assumes data is a complete array will throw on the first chunk. The README lists "cancellation, error recovery, and reconnection" as handled, but handling transport errors is not the same as handling a component that renders before its props are valid.

How this differs from Vercel AI SDK's tool-calling approach

The closest comparison in the React ecosystem is the Vercel AI SDK, which also supports tool calls and streaming into React. The difference is where the schema lives.

With the AI SDK, you define tools as objects with a description, a parameters schema, and an execute function. The execute function returns data, and your component decides what to do with it. The tool boundary is between the model and your data layer. Rendering is a separate concern you handle yourself.

Tambo moves the boundary. The tool is the component. There is no execute function returning data for you to render, because the props are the render. This is why the README can say "Show me sales by region" renders your Chart: the model is not asking for sales data, it is calling a component with the data as arguments.

That is a genuine architectural difference with consequences in both directions. You get less code, because there is no mapping layer between model output and UI. You also get less control, because the model is now choosing your component tree. If you need to inspect or transform what the model produced before it reaches the screen, Tambo's model gives you fewer places to stand. Teams that want an audit step between the model and the DOM should look at the tool-returns-data pattern instead.

Licence, release cadence, and what maintenance actually costs

Tambo is MIT licensed, which permits commercial use, modification, and redistribution with the licence and copyright notice retained. That is the permissive end of the spectrum and imposes no copyleft obligation on your application code. This is not legal advice; check the LICENSE file and your own counsel for anything that matters.

The repository is a monorepo. The release names in the material are prefixed by workspace (web-v0.135.1, tambo-v0.56.2, showcase-v0.38.0), all published on the same day in June 2026. The tambo package at v0.56.x is pre-1.0, which is the number that should drive your upgrade planning. Pre-1.0 packages reserve the right to break APIs between minor versions, and a React SDK's surface is the provider props and the hooks, which is exactly the code you write by hand.

The README opens with "Tambo 1.0 is here!" while the published tambo package is at v0.56.2. Those are not necessarily contradictory, since the announcement may refer to a product milestone rather than a semver tag, but the material does not reconcile them. Verify which version the announcement refers to before you treat the API as stable.

Ongoing cost is mostly the backend. If you self-host, you own a Docker deployment plus whatever conversation storage it needs, and you own upgrades to it. If you use Tambo Cloud, you trade that operational work for a dependency on a hosted service and its pricing. The README does not state what happens to conversation state if you move between the two, which is the question to ask before you accumulate threads you care about.

Editorial conclusion

Adopt Tambo if your app is already React plus TypeScript and you want the agent loop, streaming, and conversation state handled for you rather than assembled from parts. Skip it if you need server-rendered output with no client runtime, or if you cannot accept a backend that owns thread state. Before committing, verify three things: whether self-hosted Docker exposes the same feature set as Tambo Cloud, how userToken validation behaves in your OAuth setup, and whether the propsSchema of your largest component stays inside practical token limits.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. tambo-ai/tambo on GitHub
Community notes

Community notes