"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
:
TamboThreadMessage
;
threadId
:
string
;
}
)
{
return
(
<
div
>
{
message
.
content
.
map
(
(
block
)
=>
{
switch
(
block
.
type
)
{
case
"text"
:
return
<
p
key
=
{
`
${
message
.
id
}
:text
`
}
>
{
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
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
Auto-registration
Component registers when mounted
Context sending
Current props automatically visible to AI
Tool registration
Update tools registered automatically
Bidirectional
User edits and AI updates both work
When to Use Each
Generative
Interactable
AI creates on-demand
You pre-place in UI
One-time render
Persistent across session
Props generated once
AI can update props
Chat responses, dashboards
Settings, forms, task boards