tambo-ai

Registering Components

Learn how to register components with Tambo.

One of the core features of Tambo is its ability to intelligently respond to user messages with UI components filled with relevant data instead of just text. With this ability, Tambo allows your users to conversationally control your app with AI assistance rather than simply have questions answered.

Tambo does not, however, generate components from scratch on-the-fly. Instead, you "tell" Tambo which components are available and what props they expect using a registerComponent call.

The @tambo-ai/react package provides hooks to help with this.

Core Concepts

Component Registration

There are two main approaches to registering components with Tambo:

1. Using the TamboProvider

You can pass a list of components directly to the TamboProvider component. All components will be visible to Tambo hooks and components rendered inside the provider.

layout.tsx
import { TamboProvider } from "@tambo-ai/react";
import { z } from "zod";
 
// Define a Zod schema for the weather data
export const WeatherDisplayProps = z.object({
  data: z.object({
    date: z.string(),
    day: z.object({
      maxtemp_c: z.number(),
      mintemp_c: z.number(),
      avgtemp_c: z.number(),
      maxwind_kph: z.number(),
      totalprecip_mm: z.number(),
      avghumidity: z.number(),
      condition: z.object({
        text: z.string(),
        icon: z.string(),
      }),
    }),
  }),
});
 
const components = [
  {
    name: "WeatherDisplay",
    description: "A display of the weather in a city",
    component: WeatherDisplay,
    propsSchema: WeatherDisplayProps, // Using Zod schema
    associatedTools: [tools.forecast, tools.history], // Any context tools that Tambo should focus on when getting extra information to fill in the props of this component
  },
];
 
<TamboProvider components={components}>
  <App />
</TamboProvider>;

When creating the list of components, you may not yet have access to the tools callbacks that you need, because they may need additional context or authentication.

You can still register the component without the tools using this approach, and then register the tools later with addToolAssociation. See the Tools documentation for more information.

2. Dynamic Registration

For runtime registration, use the registerComponent function from the useTamboRegistry() hook:

page.tsx
import { useEffect } from "react";
import { useTamboRegistry } from "@tambo-ai/react";
import { z } from "zod";
import { WeatherDisplay } from "@/components/WeatherDisplay";
 
// Define a Zod schema for the weather data
export const WeatherDisplayProps = z.object({
  data: z.object({
    date: z.string(),
    day: z.object({
      maxtemp_c: z.number(),
      mintemp_c: z.number(),
      avgtemp_c: z.number(),
      maxwind_kph: z.number(),
      totalprecip_mm: z.number(),
      avghumidity: z.number(),
      condition: z.object({
        text: z.string(),
        icon: z.string(),
      }),
    }),
  }),
});
 
export default function Page() {
  const { registerComponent } = useTamboRegistry();
 
  useEffect(() => {
    registerComponent({
      name: "WeatherDisplay",
      description: "A display of the weather in a city",
      component: WeatherDisplay,
      propsSchema: WeatherDisplayProps, // Using Zod schema
      associatedTools: [tools.forecast, tools.history],
    });
  }, [registerComponent]);
 
  return (
    // Your page content
  );
}

Note that dynamic registration makes tools available to all components within the <TamboProvider> component.

Props Definition Options

You have two options for defining the props your components expect:

import { z } from "zod";
import { DataChart } from "@/components/DataChart";
import { registerComponent } from "@tambo-ai/react";
 
// Define the schema with Zod
export const DataChartProps = z.object({
  data: z.object({
    labels: z.array(z.string()),
    values: z.array(z.number()),
  }),
  type: z.enum(["bar", "line", "pie"]),
});
 
// Register with the Zod schema
registerComponent({
  component: DataChart,
  name: "DataChart",
  description: "Displays data as a chart",
  propsSchema: DataChartProps,
});

You can also use z.describe() to provide extra guidance to the AI:

import { z } from "zod";
import { DataChart } from "@/components/DataChart";
import { registerComponent } from "@tambo-ai/react";
 
// Define schema with descriptions for AI
export const DataChartProps = z
  .object({
    data: z
      .object({
        labels: z
          .array(z.string())
          .describe("Use single words or short phrases."),
        values: z.array(z.number()).describe("Use whole numbers."),
      })
      .describe("A component for displaying data in various chart formats"),
    type: z
      .enum(["bar", "line", "pie"])
      .describe(
        "Use a chart type that is appropriate for the data. Only use pie charts when less than 5 values.",
      ),
  })
  .describe("A component for displaying data in various chart formats");
 
// Register with the enhanced Zod schema
registerComponent({
  component: DataChart,
  name: "DataChart",
  description: "Displays data as a chart",
  propsSchema: DataChartProps,
});

Using a JSON-like Object (Alternative)

import { DataChart } from "@/components/DataChart";
import { registerComponent } from "@tambo-ai/react";
 
// Using JSONSchema format
registerComponent({
  component: DataChart,
  name: "DataChart",
  description: "Displays data as a chart",
  propsSchema: {
    type: "object",
    properties: {
      data: {
        type: "object",
        properties: {
          labels: {
            type: "array",
            items: { type: "string" },
            description: "Use single words or short phrases.",
          },
          values: {
            type: "array",
            items: { type: "number" },
            description: "Use whole numbers.",
          },
        },
        required: ["labels", "values"],
      },
      type: {
        type: "string",
        enum: ["bar", "line", "pie"],
        description:
          "Use a chart type that is appropriate for the data. Only use pie charts when less than 5 values.",
      },
    },
    required: ["data", "type"],
    description: "A component for displaying data in various chart formats",
  },
});

Now when a user sends a message asking about something related to your components, Tambo can respond with the appropriate component filled with relevant data!

On this page