Suggested prompts that users can click to quickly send or populate the composer.
The Suggestion primitive renders suggested prompts as clickable pills that send a message or populate the composer. Use it for welcome screen suggestions, follow-up prompts, or quick actions. You provide the layout and styling.
import {
ThreadPrimitive,
SuggestionPrimitive,
} from "@assistant-ui/react";
function SuggestionList() {
return (
<div className="grid grid-cols-2 gap-2">
<ThreadPrimitive.Suggestions>
{() => <SuggestionItem />}
</ThreadPrimitive.Suggestions>
</div>
);
}
function SuggestionItem() {
return (
<SuggestionPrimitive.Trigger
send
className="flex flex-col items-start gap-1 rounded-2xl border px-4 py-3 text-left text-sm hover:bg-muted"
>
<span className="font-medium">
<SuggestionPrimitive.Title />
</span>
<span className="text-muted-foreground">
<SuggestionPrimitive.Description />
</span>
</SuggestionPrimitive.Trigger>
);
}Quick Start
A suggestion list using the iterator pattern:
import { ThreadPrimitive, SuggestionPrimitive } from "@assistant-ui/react";
<ThreadPrimitive.Suggestions>
{() => <MySuggestionItem />}
</ThreadPrimitive.Suggestions>
function MySuggestionItem() {
return (
<SuggestionPrimitive.Trigger className="rounded-lg border px-3 py-2 hover:bg-muted">
<SuggestionPrimitive.Title />
</SuggestionPrimitive.Trigger>
);
}ThreadPrimitive.Suggestions iterates over available suggestions and renders your component for each one. Inside the component, SuggestionPrimitive parts read from the suggestion context automatically.
Info
Runtime setup: primitives require runtime context. Wrap your UI in AssistantRuntimeProvider with a runtime (for example useLocalRuntime(...)). See Pick a Runtime.
Core Concepts
Context-Based Rendering
SuggestionPrimitive parts read from a suggestion context. Use ThreadPrimitive.Suggestions to provide this context. It iterates over the thread's suggestions and renders your component for each one:
<ThreadPrimitive.Suggestions>
{() => <MySuggestion />}
</ThreadPrimitive.Suggestions>You can also use ThreadPrimitive.SuggestionByIndex to render a specific suggestion by index if you need more layout control.
Title and Description
Suggestions support two text parts for structured display:
Title: the primary text (e.g., "Write a blog post")Description: secondary text — renders thelabelfield from the suggestion config (e.g.,{ prompt: "...", label: "About React Server Components" })
Both render a <span> and accept children to override the value from state:
<SuggestionPrimitive.Title>Custom title</SuggestionPrimitive.Title>Send vs Populate
Trigger's send prop controls what happens on click:
send={true}: immediately sends the suggestion as a new message. While a run is in progress, the suggestion is queued on runtimes that support queueing (leaving the composer draft untouched); otherwise the trigger is disabled.send={false}(default): populates the composer text so the user can edit before sending
// Send immediately
<SuggestionPrimitive.Trigger send>
<SuggestionPrimitive.Title />
</SuggestionPrimitive.Trigger>
// Populate composer for editing
<SuggestionPrimitive.Trigger>
<SuggestionPrimitive.Title />
</SuggestionPrimitive.Trigger>clearComposer
When send={false}, the clearComposer prop controls whether the suggestion replaces or appends to existing composer text:
clearComposer={true}(default): replaces the current composer textclearComposer={false}: appends the suggestion to the existing text
Static configuration vs. runtime suggestions
There are two data flows for suggestions:
- Static configuration flows through the
suggestionsscope. Pass an array toSuggestions(...)in your runtime provider; render it withThreadPrimitive.Suggestions. Best for welcome screen prompts. - Runtime / dynamic suggestions flow through
thread.suggestions. Populate it viaSuggestionAdapter(local runtime) or thesuggestionsfield onuseExternalStoreRuntime; render it with the shadcnThreadFollowupSuggestionscomponent or your own component readinguseAuiState((s) => s.thread.suggestions). Best for follow up prompts after a turn.
When no static configuration is provided, the suggestions scope derives from thread.suggestions, so runtime suggestions also render through ThreadPrimitive.Suggestions. A static Suggestions(...) configuration takes precedence over the derived values.
See Suggested Prompts for end to end examples.
ThreadPrimitive.Suggestion
ThreadPrimitive.Suggestion is a self-contained button that takes its prompt as a prop instead of reading the suggestions scope. Both paths run the same trigger behavior, including the queueing and disabled handling described above, so the choice is about where the prompt comes from:
- Rendering the
suggestionsscope: useThreadPrimitive.Suggestionswith theSuggestionPrimitiveparts, which supply the title and description for you. - Rendering prompts from anywhere else: use
ThreadPrimitive.Suggestionand pass the prompt directly.
// Prompts from the suggestions scope
<ThreadPrimitive.Suggestions>
{() => <MySuggestionItem />}
</ThreadPrimitive.Suggestions>
// A prompt the caller already holds
<ThreadPrimitive.Suggestion prompt="Write a blog post" />The second case is not a fallback. A component that renders thread.suggestions cannot read them through the suggestions scope once the app also configures static suggestions, because that configuration takes precedence over the derived values. The shadcn ThreadFollowupSuggestions component reads thread.suggestions and renders each entry with ThreadPrimitive.Suggestion for that reason.
The autoSend and method props are deprecated; prefer send and clearComposer.
Parts
Title
Renders the suggestion title. Renders a <span> element unless asChild is set.
<SuggestionPrimitive.Title />Description
Renders the secondary suggestion description text. Renders a <span> element unless asChild is set.
<SuggestionPrimitive.Description />Trigger
Clickable button that sends or populates the suggestion. Renders a <button> element unless asChild is set.
<SuggestionPrimitive.Trigger send className="rounded-lg border px-3 py-2 hover:bg-muted">
<SuggestionPrimitive.Title />
</SuggestionPrimitive.Trigger>Prop
Type
Patterns
Welcome Screen Grid
function WelcomeSuggestions() {
return (
<AuiIf condition={(s) => s.thread.isEmpty}>
<div className="text-center">
<h2 className="text-lg font-semibold">How can I help you?</h2>
<div className="mt-4 grid grid-cols-2 gap-2">
<ThreadPrimitive.Suggestions>
{() => <SuggestionCard />}
</ThreadPrimitive.Suggestions>
</div>
</div>
</AuiIf>
);
}
function SuggestionCard() {
return (
<SuggestionPrimitive.Trigger
send
className="flex flex-col gap-1 rounded-2xl border px-4 py-3 text-left hover:bg-muted"
>
<span className="font-medium">
<SuggestionPrimitive.Title />
</span>
<span className="text-sm text-muted-foreground">
<SuggestionPrimitive.Description />
</span>
</SuggestionPrimitive.Trigger>
);
}Send-On-Click Suggestions
<SuggestionPrimitive.Trigger send className="rounded-full border px-4 py-2 hover:bg-muted">
<SuggestionPrimitive.Title />
</SuggestionPrimitive.Trigger>Populate-Only Suggestions
<SuggestionPrimitive.Trigger
send={false}
clearComposer={false}
className="rounded-lg border px-3 py-1.5 text-sm hover:bg-muted"
>
<SuggestionPrimitive.Title />
</SuggestionPrimitive.Trigger>Relationship to Components
The shadcn Thread component includes suggestions in its welcome screen using ThreadPrimitive.Suggestions with SuggestionPrimitive parts in a responsive grid. Start there for a prebuilt welcome experience.
API Reference
For full prop details on every part, see the SuggestionPrimitive API Reference.
Related: