0.30.0 • Published 29 days ago

@tambo-ai/react v0.30.0

Weekly downloads
-
License
-
Repository
github
Last release
29 days ago

Tambo React SDK

Tambo allows AI models to dynamically render React components in response to user messages, enabling AI assistants to display interactive widgets, charts, forms, and other UI elements instead of just text. Tambo is a great way to add generative UI to your AI assistant, copilot, or agent.

This package provides react hooks to talk to the Tambo API and render custom components inline, but does not provide any UI components on its own. For pre-built UI components that use this package, see tambo-ui.

Build with MCP and Generative UI

Watch the video

Source code

Creating a new project

You can create a new project using our MCP template:

npx tambo create-app -t mcp tambo-mcp-app

This will create a new nextjs project with Tambo pre-configured, and then step you through the process of setting up a Tambo project, including signing up for an API key, and adding it to .env.local.

Adding components to an existing project

If you have an existing project, you can add components to it. First, initialize your project:

npx tambo init

This will step you through the process of setting up a Tambo project, including signing up for an API key, and adding it to .env.local.

Then add components from our library to your project in the components/ui directory:

npx tambo add message-thread-full

See the complete component library at ui.tambo.co.

Manual installation

You can also install Tambo manually:

npm install @tambo-ai/react
# or
yarn add @tambo-ai/react

How does Tambo work?

Tambo uses a client-side registry of React components that can be used by an LLM.

1. Register your components

import { type TamboComponent } from "@tambo-ai/react";
import { Graph, graphSchema } from "@/components/ui/graph";

const components: TamboComponent[] = [
  {
    name: "Graph",
    description:
      "A component that renders various types of charts (bar, line, pie) using Recharts. Supports customizable data visualization with labels, datasets, and styling options.",
    component: Graph,
    propsSchema: graphSchema, // zod schema
  },
  // Add more components
];

2. Wrap your app in a TamboProvider

If you are using one of Tambo's pre-built components, you can wrap your app in a TamboProvider.

import { TamboProvider } from "@tambo-ai/react";
import { MessageThreadFull } from "@/components/ui/message-thread-full";

// In your chat page
<TamboProvider
  apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}
  components={components}
>
  <MessageThreadFull />
</TamboProvider>;

You can also use your own components with the TamboProvider:

import { TamboProvider } from "@tambo-ai/react";

<TamboProvider
  apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}
  components={components}
>
  <YourChatComponents />
</TamboProvider>;

3. Render AI-generated components

This is also handled automatically for you if you are using the MessageThreadFull component.

For custom components, you can use the useMessageContext hook to get the current message.

import {
  useTambo,
  useMessageContext,
  type TamboThreadMessage,
} from "@tambo-ai/react";

function ChatHistory() {
  const { thread } = useTambo();
  return (
    <div>
      {thread.messages.map((message) => (
        <CustomMessage key={message.id} message={message} />
      ))}
    </div>
  );
}

function CustomMessage({ message }: { message: TamboThreadMessage }) {
  // Render the component
  return (
    <div>
      {/* Render the message content */}
      <div>Role: {message.role}</div>
      <div>
        {message.content.map((part) =>
          part.type === "text" ? (
            <div key={part.id}>{part.text}</div>
          ) : (
            <div key={part.id}>Non-text content: {part.type}</div>
          ),
        )}
      </div>
      {/* Render the component, if any */}
      <div>{message.renderedComponent}</div>
    </div>
  );
}

4. Submit user messages

If you are using the MessageThreadFull component, you can skip this step, it is handled automatically.

If you are using a custom component, you can use the useTamboThreadInput hook to submit user messages.

import { useTamboThreadInput } from "@tambo-ai/react";

function ChatInput() {
  const { submit, value, setValue } = useTamboThreadInput();

  return (
    <div>
      <input
        type="text"
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
      <button onClick={() => submit()}>Send</button>
    </div>
  );
}

5. Put it all together

function ChatInterface() {
  return (
    <div>
      <ChatHistory />
      <ChatInput />
    </div>
  );
}

Getting Started

Templates

AppDescription
MCP (new!)Get started with MCP + Generative UX
Regular ToolsGet started with Generative UX
Conversational FormCollect information with generative UX

Check out our UI library tambo-ui for components that leverage tambo.

In depth examples

1. Displaying a message thread:

import { useTambo, useTamboThreadInput } from "@tambo-ai/react";

function ChatInterface() {
  const { thread } = useTambo();
  const { value, setValue, submit } = useTamboThreadInput();

  return (
    <div>
      {/* Display messages */}
      <div>
        {thread.messages.map((message, index) => (
          <div key={index} className={`message ${message.role}`}>
            <div>{message.content}</div>
            {message.renderedComponent}
          </div>
        ))}
      </div>

      {/* Input form */}
      <form
        onSubmit={(e) => {
          e.preventDefault();
          submit();
        }}
        className="input-form"
      >
        <input
          type="text"
          value={value}
          onChange={(e) => setValue(e.target.value)}
          placeholder="Type your message..."
        />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}

2. Adding AI-Generated Components:

Create components that can be dynamically generated by the AI:

// components/WeatherCard.jsx
import { useTamboComponentState } from "@tambo-ai/react";

export function WeatherCard({
  location,
  temperature,
  condition,
}: {
  location: string;
  temperature: number;
  condition: string;
}) {
  // useTamboComponentState manages state that persists even if
  // the component is unmounted
  const [isMetric, setIsMetric] = useTamboComponentState(
    "isMetric", // unique identifier for this component's state
    false, // default value
  );

  return (
    <div>
      <h3>{location}</h3>
      <div>
        {isMetric ? temperature : (temperature * 1.8 + 32).toFixed(1)}°
        {isMetric ? "C" : "F"}
      </div>
      <div>{condition}</div>
      <input
        type="checkbox"
        checked={isMetric}
        onChange={(e) => setIsMetric(e.target.checked)}
      />
    </div>
  );
}

3. Register your components:

// App.jsx
import { TamboProvider } from "@tambo-ai/react";
import { WeatherCard } from "./components/WeatherCard";
import { z } from "zod";

// Define your components
const components = [
  {
    name: "WeatherCard",
    description: "A component that displays weather information",
    component: WeatherCard,
    propsSchema: z.object({
      temperature: z.number(),
      condition: z.string(),
      location: z.string(),
    }),
  },
];

// Pass them to the provider
function App() {
  return (
    <TamboProvider apiKey="your-api-key" components={components}>
      <YourApp />
    </TamboProvider>
  );
}

Adding Tools for the AI

Register tools to make them available to the AI:

import { TamboTool } from "@tambo-ai/react";
import { z } from "zod";

// Define your tools
const tools: TamboTool[] = [
  {
    name: "getWeather",
    description: "Fetches current weather data for a given location",
    tool: async (location: string, units: string = "celsius") => {
      // Example implementation
      const weather = await fetchWeatherData(location);
      return {
        temperature: weather.temp,
        condition: weather.condition,
        location: weather.city,
      };
    },
    toolSchema: z
      .function()
      .args(
        z.string().describe("Location name (city)"),
        z
          .string()
          .optional()
          .describe("Temperature units (celsius/fahrenheit)"),
      )
      .returns(
        z.object({
          temperature: z.number(),
          condition: z.string(),
          location: z.string(),
        }),
      ),
  },
];

// Pass tools to the provider
<TamboProvider apiKey="your-api-key" tools={tools}>
  <YourApp />
</TamboProvider>;

Using MCP Servers

import { TamboProvider } from "@tambo-ai/react";
import { TamboMcpProvider } from "@tambo-ai/react/mcp";

const mcpServers = [
  {
    url: "https://mcp-server-1.com",
    transport: "http",
    name: "mcp-server-1",
  },
];

// Pass MCP servers to the provider
<TamboProvider
  apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}
  components={components}
>
  <TamboMcpProvider mcpServers={mcpServers}>{children}</TamboMcpProvider>
</TamboProvider>;

Read our full documentation

Join the Community

We're building tools for the future of user interfaces. Your contributions matter.

Star this repo to support our work.

Join our Discord to connect with other developers.

0.20.1

3 months ago

0.19.8

3 months ago

0.20.0

3 months ago

0.19.0

4 months ago

0.19.1

4 months ago

0.19.2

4 months ago

0.19.3

3 months ago

0.19.4

3 months ago

0.19.5

3 months ago

0.19.6

3 months ago

0.19.7

3 months ago

0.15.0

4 months ago

0.15.1

4 months ago

0.17.0

4 months ago

0.13.4

4 months ago

0.30.0

29 days ago

0.29.0

1 month ago

0.27.0

1 month ago

0.25.1

2 months ago

0.25.0

2 months ago

0.23.2

2 months ago

0.21.4

2 months ago

0.23.1

2 months ago

0.21.3

2 months ago

0.23.0

2 months ago

0.21.2

2 months ago

0.21.1

2 months ago

0.29.1

29 days ago

0.21.0

3 months ago

0.18.1

4 months ago

0.18.2

4 months ago

0.14.0

4 months ago

0.14.1

4 months ago

0.16.0

4 months ago

0.16.1

4 months ago

0.18.0

4 months ago

0.16.2

4 months ago

0.26.3

1 month ago

0.28.0

1 month ago

0.26.2

1 month ago

0.26.1

1 month ago

0.26.0

2 months ago

0.24.0

2 months ago

0.20.4

3 months ago

0.20.3

3 months ago

0.22.0

2 months ago

0.20.2

3 months ago

0.26.4

1 month ago

0.13.1

4 months ago

0.13.0

4 months ago

0.12.1

4 months ago

0.12.0

4 months ago