Get the FREE Ultimate OpenClaw Setup Guide →

components

npx machina-cli add skill andrmaz/spec-driven-architecture/components --openclaw
Files (1)
SKILL.md
3.9 KB

Tambo Components

Two component types: generative (AI creates on-demand) and interactable (pre-placed, AI updates).

Quick Start

// Generative: AI creates when needed
const components: TamboComponent[] = [
  {
    name: "WeatherCard",
    component: WeatherCard,
    description: "Shows weather. Use when user asks about weather.",
    propsSchema: z.object({ city: z.string(), temp: z.number() }),
  },
];

<TamboProvider components={components}>
  <App />
</TamboProvider>;

Generative Components

AI dynamically selects and renders these in response to user messages.

import { TamboProvider, TamboComponent } from "@tambo-ai/react";
import { z } from "zod";

const WeatherCardSchema = z.object({
  city: z.string().describe("City name"),
  temperature: z.number().describe("Temperature in Celsius"),
  condition: z.string().describe("Weather condition"),
});

const components: TamboComponent[] = [
  {
    name: "WeatherCard",
    component: WeatherCard,
    description:
      "Displays weather for a city. Use when user asks about weather.",
    propsSchema: WeatherCardSchema,
  },
];

<TamboProvider apiKey={apiKey} components={components}>
  <App />
</TamboProvider>;

Rendering Generative Components

Use ComponentRenderer to render AI-generated components in your message list:

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

function Message({
  message,
  threadId,
}: {
  message: TamboMessage;
  threadId: string;
}) {
  return (
    <div>
      {message.content.map((block) => {
        switch (block.type) {
          case "text":
            return <p key={block.type}>{block.text}</p>;
          case "component":
            return (
              <ComponentRenderer
                key={block.id}
                content={block}
                threadId={threadId}
                messageId={message.id}
              />
            );
          default:
            return null;
        }
      })}
    </div>
  );
}

Generative Key Points

  • propsSchema: Zod object with .describe() on each field
  • description: Tells AI when to use the component
  • Streaming: Props start undefined, make them optional or handle gracefully
  • Use z.infer<typeof Schema> for TypeScript props type

Interactable Components

Pre-place in your UI; AI can observe and update props via natural language.

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

const NoteSchema = z.object({
  title: z.string().describe("Note title"),
  content: z.string().describe("Note content"),
  color: z.enum(["white", "yellow", "blue"]).optional(),
});

function Note({ title, content, color = "white" }: Props) {
  return (
    <div style={{ backgroundColor: color }}>
      <h3>{title}</h3>
      <p>{content}</p>
    </div>
  );
}

export const InteractableNote = withTamboInteractable(Note, {
  componentName: "Note",
  description: "A note with editable title, content, and color",
  propsSchema: NoteSchema,
});

Interactable How It Works

  1. Auto-registration: Component registers when mounted
  2. Context sending: Current props automatically visible to AI
  3. Tool registration: Update tools registered automatically
  4. Bidirectional: User edits and AI updates both work

When to Use Each

GenerativeInteractable
AI creates on-demandYou pre-place in UI
One-time renderPersistent across session
Props generated onceAI can update props
Chat responses, dashboardsSettings, forms, task boards

Source

git clone https://github.com/andrmaz/spec-driven-architecture/blob/develop/.agents/skills/components/SKILL.mdView on GitHub

Overview

Tambo Components lets you define two component types: generative, AI creates on demand, and interactable, pre-placed components AI can update. Use it when defining components or wiring TamboComponent, withTamboInteractable, and propsSchema so AI can render or adjust components reliably.

How This Skill Works

Developers declare an array of TamboComponent items with a name, component, description, and a propsSchema. Wrap your app in a TamboProvider and use ComponentRenderer to render generative components inside messages; for interactable components, wrap with withTamboInteractable to enable auto-registration and AI updates. The schema and descriptions guide AI behavior and prop validation.

When to Use It

  • Generative: AI creates components on demand when responding to user messages.
  • Generative: Use for one-time renders like chat responses or dashboards.
  • Generative: Props are generated on the fly and may start undefined during streaming.
  • Interactable: Pre-place components in the UI so AI can observe and update their props.
  • Interactable: Maintain persistence across a session for settings or forms.

Quick Start

  1. Step 1: Define an array of TamboComponent with name, component, description and a propsSchema.
  2. Step 2: Wrap your app with <TamboProvider components={components}>.
  3. Step 3: Use ComponentRenderer to render generative components inside messages or rely on withTamboInteractable for updates.

Best Practices

  • Define a precise propsSchema with zod and describe on each field.
  • Provide a clear description to tell AI when to use the component.
  • Design streaming friendly props by allowing undefined values initially.
  • Use z.infer<typeof Schema> to derive TypeScript types for safety.
  • For interactables, rely on auto-registration and enable bidirectional updates.

Example Use Cases

  • WeatherCard generative example used to show weather on demand in chat.
  • Interactable Note pre-placed UI component with editable title, content, and color.
  • Weather dashboard that includes a generative component to answer weather questions.
  • Using ComponentRenderer to render AI-generated components inside a message list.
  • Auto-registered interactable notes with AI updating props via natural language.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers