> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hitheo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Follow-Ups

> How Theo generates suggested next prompts and how to render them in a chat UI.

Every Theo completion returns a `follow_ups: Array<{ label, prompt }>` field. These are AI-generated, mode-aware suggestions for the next turn — ready to drop into a chat UI as suggestion chips.

## When follow-ups are generated

* On **every text-mode completion** (`auto`, `fast`, `think`, `code`, `research`, `roast`, `genui`, `vision`, stealth text variants).
* On **image / video / document** turns — follow-ups tend to be edit/variation prompts ("Try a wider aspect ratio", "Make the background lighter").
* **Not** on `stt` (speech-to-text) or `tts` (text-to-speech) responses — there's no natural next turn.
  The server returns between 0 and 3 follow-ups per response. Empty arrays are possible for terse answers, errors, or when Theo has nothing useful to suggest.

## Shape

```typescript theme={null}
interface FollowUp {
  /** Short label suitable for a UI chip (max ~60 chars). */
  label: string;
  /** Full prompt to send on click — safe to use as-is in the next request. */
  prompt: string;
}
```

`label` is the user-visible text on the chip. `prompt` is what you submit as the next `prompt` field when the user clicks it. The two are usually different — `label` is a short imperative, `prompt` is a fully-formed instruction that picks up where the last turn left off.

## How they're generated

Theo passes the turn's content, tools used, and any artifacts into a lightweight follow-up generator that runs after the main completion. The suggestions are AI-generated, not rules-based, so quality varies with the model tier — `think` mode produces better follow-ups than `fast`. There is no "follow-up cost" line item; the generator piggybacks on the same LLM call.

## Rendering in a chat UI

A minimal React pattern: chip row rendered below the last assistant bubble.

```tsx theme={null}
{assistantMessage.follow_ups?.length ? (
  <div className="flex flex-wrap gap-2 mt-3">
    {assistantMessage.follow_ups.map((f) => (
      <button
        key={f.label}
        onClick={() => sendPrompt(f.prompt)}
        className="px-3 py-1 rounded-full border text-sm hover:bg-zinc-100"
      >
        {f.label}
      </button>
    ))}
  </div>
) : null}
```

* Render the chips **after** the full message is displayed. For streaming responses, `follow_ups` only appears on the `done` event, so wait for it before rendering.
* When the user clicks a chip, send `prompt` verbatim as the next `prompt`. Do NOT concatenate it with the user's own input — the prompts are self-contained.
* Hide the chip row once the user starts typing a new message, then re-show the next turn's chips on completion. This matches the pattern most production chat UIs use.

## Streaming

For streaming completions, follow-ups appear on the `done` event:

```typescript theme={null}
for await (const event of stream) {
  if (event.type === "done") {
    setFollowUps(event.data.follow_ups);
  }
}
```

See [Streaming Completions](/api-reference/completions/streaming) for the full event schema.

## Opting out

If follow-ups clutter your UI, simply ignore the field. There is no per-request toggle \u2014 it is cheap enough to always generate, and some callers (voice, analytics) read it even when it isn't rendered.
