Suggestion

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.

How can I help you?

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 the label field 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 text
  • clearComposer={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 suggestions scope. Pass an array to Suggestions(...) in your runtime provider; render it with ThreadPrimitive.Suggestions. Best for welcome screen prompts.
  • Runtime / dynamic suggestions flow through thread.suggestions. Populate it via SuggestionAdapter (local runtime) or the suggestions field on useExternalStoreRuntime; render it with the shadcn ThreadFollowupSuggestions component or your own component reading useAuiState((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 suggestions scope: use ThreadPrimitive.Suggestions with the SuggestionPrimitive parts, which supply the title and description for you.
  • Rendering prompts from anywhere else: use ThreadPrimitive.Suggestion and 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: