Tambo Lockup

Response Component Streaming

Stream response components from Tambo as they are being generated with real-time prop updates.

When you message.renderedComponent is called, it will return a component and it will update the props as the values stream in.

How Does It Work?

Inside the provider the thread.messages array is updated with the renderedComponent property.

basic-streaming.tsx
import { useTambo } from "@tambo-ai/react";

function ChatInterface() {
  const { thread } = useTambo();

  return (
    <div>
      {thread.messages.map((message, index) => (
        <div key={index}>
          {/* Updates in real-time as props stream in */}
          <div>{message.renderedComponent}</div>
        </div>
      ))}
    </div>
  );
}

Why Use Response Component Streaming?

  • Real-time feedback - Content appears as it's generated
  • Better perceived performance - Immediate visual feedback reduces wait times
  • Progressive disclosure - Content appears in logical order
  • Enhanced engagement - Dynamic updates keep users focused

Prop Streaming Order

Critical: Props stream in the order you define them in your Zod schema. Define the most important props first:

schema-order-example.tsx
import { z } from "zod";

// ✅ Good: Title streams first, then content
const ArticleSchema = z.object({
  title: z.string(), // First in schema = streams first
  content: z.string(), // Second in schema = streams second
  author: z.string(), // Third in schema = streams third
});

// ❌ Bad: Content streams before title
const ArticleSchema = z.object({
  content: z.string(), // First in schema = streams first
  title: z.string(), // Second in schema = streams second
});

Handling Streaming Props

Since Tambo renders components before all props are complete, your components must handle undefined values gracefully. Here are three approaches in order of complexity:

1. Default Values (Simplest)

default-values.tsx
const ArticleCard = ({
  title = "Loading title...",
  content = "Loading content...",
  author = "Loading author...",
}: {
  title?: string;
  content?: string;
  author?: string;
}) => {
  return (
    <div className="article-card">
      <h2>{title}</h2>
      <p>{content}</p>
      <span>By {author}</span>
    </div>
  );
};

2. Optional Props with Conditional Rendering

optional-props.tsx
const WeatherWidget = ({
  temperature,
  condition,
  humidity,
}: {
  temperature?: number;
  condition?: string;
  humidity?: number;
}) => {
  return (
    <div className="weather-widget">
      <div className="temperature">
        {temperature !== undefined ? `${temperature}°C` : "Loading..."}
      </div>
      <div className="condition">{condition || "Loading condition..."}</div>
      <div className="humidity">
        {humidity !== undefined ? `${humidity}%` : "Loading humidity..."}
      </div>
    </div>
  );
};

Objects with State

Important: If your component uses objects with internal state (like form controls, charts, or complex UI components), use useEffect or the Stream Status Provider to properly handle state updates as props stream in.