Skip to main content

Overview

Component registration tells Tambo which React components the AI can render and how to use them. By providing a Zod schema for props, the AI understands what data each component needs and can stream props in real-time.

Component Types

Tambo supports two types of components:
  • Generative Components - Render once in response to a message (charts, summaries, visualizations)
  • Interactable Components - Persist and update as users refine requests (task boards, shopping carts, forms)
1
Install Zod
2
First, install Zod if you haven’t already:
3
npm install zod
4
Tambo supports both Zod v3 and v4. You can also use other Standard Schema-compliant validators like Valibot or ArkType.
5
Define Your Component
6
Create a React component that will be rendered by the AI:
7
import React from 'react';

interface WeatherCardProps {
  location: string;
  temperature: number;
  condition: string;
  humidity?: number;
}

export const WeatherCard: React.FC<WeatherCardProps> = ({
  location,
  temperature,
  condition,
  humidity,
}) => (
  <div className="weather-card">
    <h2>{location}</h2>
    <div className="temp">{temperature}°F</div>
    <div className="condition">{condition}</div>
    {humidity && <div className="humidity">Humidity: {humidity}%</div>}
  </div>
);
8
Create the Component Schema
9
Define a Zod schema that matches your component’s props:
10
import { z } from 'zod';

export const weatherCardSchema = z.object({
  location: z.string().describe('The city and state/country'),
  temperature: z.number().describe('Temperature in Fahrenheit'),
  condition: z.string().describe('Weather condition (sunny, cloudy, rainy, etc.)'),
  humidity: z.number().optional().describe('Humidity percentage (0-100)'),
});
11
Use .describe() to add descriptions that help the AI understand each field’s purpose.
12
Register the Component
13
Create a TamboComponent registration object:
14
import { TamboComponent } from '@tambo-ai/react';
import { WeatherCard, weatherCardSchema } from '@/components/weather-card';

export const components: TamboComponent[] = [
  {
    name: 'WeatherCard',
    description: 'Displays current weather information for a location. Use this when the user asks about weather conditions.',
    component: WeatherCard,
    propsSchema: weatherCardSchema,
  },
];
15
Write clear, detailed descriptions. The AI uses these to decide which component to render.
16
Add to TamboProvider
17
Pass your components array to TamboProvider:
18
import { TamboProvider } from '@tambo-ai/react';
import { components } from '@/lib/tambo-components';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <TamboProvider
          apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}
          userKey="user-123"
          components={components}
        >
          {children}
        </TamboProvider>
      </body>
    </html>
  );
}

Multiple Components

Register multiple components by adding them to the array:
lib/tambo-components.ts
import { TamboComponent } from '@tambo-ai/react';
import { WeatherCard, weatherCardSchema } from '@/components/weather-card';
import { StockChart, stockChartSchema } from '@/components/stock-chart';
import { TaskList, taskListSchema } from '@/components/task-list';

export const components: TamboComponent[] = [
  {
    name: 'WeatherCard',
    description: 'Displays current weather information',
    component: WeatherCard,
    propsSchema: weatherCardSchema,
  },
  {
    name: 'StockChart',
    description: 'Renders a stock price chart with historical data',
    component: StockChart,
    propsSchema: stockChartSchema,
  },
  {
    name: 'TaskList',
    description: 'Displays a list of tasks with checkboxes',
    component: TaskList,
    propsSchema: taskListSchema,
  },
];

Loading States

Provide a loading component to show while props are streaming:
import { Skeleton } from '@/components/ui/skeleton';

const WeatherCardSkeleton = () => (
  <div className="weather-card">
    <Skeleton className="h-8 w-32 mb-2" />
    <Skeleton className="h-12 w-20 mb-2" />
    <Skeleton className="h-6 w-24" />
  </div>
);

export const components: TamboComponent[] = [
  {
    name: 'WeatherCard',
    description: 'Displays current weather information',
    component: WeatherCard,
    loadingComponent: WeatherCardSkeleton,
    propsSchema: weatherCardSchema,
  },
];

Best Practices

Choose names that clearly indicate what the component does. WeatherCard is better than Card1.
Include when to use the component and what scenarios it’s appropriate for. The AI uses this to make decisions.
Use .describe() on each schema field to help the AI understand what data to provide.
Your Zod schema should match your TypeScript prop types. Use z.infer<typeof schema> to derive types:
const weatherCardSchema = z.object({
  location: z.string(),
  temperature: z.number(),
});

type WeatherCardProps = z.infer<typeof weatherCardSchema>;

export const WeatherCard: React.FC<WeatherCardProps> = (props) => {
  // ...
};
When a prop has specific valid values, use z.enum():
const chartSchema = z.object({
  type: z.enum(['line', 'bar', 'pie']),
  data: z.array(z.object({ name: z.string(), value: z.number() })),
});

Troubleshooting

  • Verify the component is in the components array passed to TamboProvider
  • Check that the name field matches what you expect
  • Ensure the AI’s response includes your component (check the message content)
  • Confirm your schema matches the expected prop types
  • Check for TypeScript errors in the component
  • Verify the schema validates the incoming data
  • Make descriptions more specific and detailed
  • Add examples of when to use each component
  • Ensure component names are distinct and clear

Next Steps

Interactable Components

Create components that persist and update

Register Tools

Add functions the AI can call

Component State

Manage state inside AI-rendered components

Streaming Status

Monitor prop streaming progress

Build docs developers (and LLMs) love