Guided Flow

A short multi-step flow inside the chat, like booking a table or returning an item.

Pattern

≈ 1,689 tokens per use (tool 1,125 · guidance 258 · typical payload 306)How token costs are estimated

Example: Guided Flow

Book us a table at Marlow & Pine on Friday evening.

Book a table at Marlow & Pine

Step 1 of 4: Party size

When to use

  • The user wants to complete a short task that needs a few ordered inputs: booking, returning, scheduling, signing up.
  • Later steps depend on earlier ones, or the inputs mix choices, times and contact details.

When not to use

  • You only need one or two answers. Ask in text, or use a Question Stepper.
  • You're collecting a single record with many fields and no order. Use a form.
  • The task needs more than 5 steps. Split it, or do part of it yourself.

How the agent should use it

  • Keep it to 2–5 steps, each with a short title, in the order a person would decide.
  • Options and slots are data-bound when they refer to real items, payment methods or availability. Read them from a tool, never invent them.
  • Mark only the fields you truly need as required. Required fields are marked with an asterisk; the rest are optional.
  • End with a review step before anything binding, such as a booking, payment or return.
  • Don't act until you receive submit, and use only the returned values.

Step types

TypeShowsValue in the result
choiceOption cards, one pick or several with multipleThe option value, or an array of values
slotsA grid of times. Unavailable slots are shown struck through and can't be pickedThe slot id
fieldsLabelled inputs: text, email, tel, number, textarea, date{ [fieldId]: string }, empty optional fields left out
reviewEvery earlier answer, each with an Edit buttonNone

Interaction

InputAction
NextDisabled until the step is valid. On the last step it becomes the submitLabel button
EnterIn a single-line input, continues to the next step. If the step isn't valid yet, it shows every error on the step
BackPrevious step. Answers are kept
Edit (review)Jumps to that step; its button then reads Back to review
×Cancels the flow. The agent should ask in text what the user wants instead
  • Validation is inline. Required fields, email addresses, phone numbers, numbers and dates are checked when the user leaves a field, with the error linked to the input through aria-describedby.
  • Focus follows the step. After moving, focus lands on the step title, which screen readers announce as "Step 2 of 4: Details". On screen, progress is a segmented bar.
  • Streaming. Steps arrive one by one and the user can start on step 1 straight away. The announced count reads "of 2…" until the payload is complete, and submitting waits for it.

Installation

npx shadcn@latest add https://your-site.com/r/guided-flow.json

Usage

app/api/chat/route.ts
import { tool } from "ai"
import { guidedFlowTool } from "@/components/genui/guided-flow.schema"

const tools = {
  // No execute(): the call is completed by the user's answers in the UI.
  [guidedFlowTool.name]: tool({
    description: guidedFlowTool.description,
    inputSchema: guidedFlowTool.inputSchema,
  }),
}
components/message.tsx
import { GuidedFlow } from "@/components/genui/guided-flow"

function ToolPart({ part, addToolResult }) {
  if (part.type !== "tool-start_flow") return null

  return (
    <GuidedFlow
      {...part.input}
      status={part.state === "input-streaming" ? "streaming" : undefined}
      result={part.state === "output-available" ? part.output : undefined}
      onResult={(result) =>
        addToolResult({
          tool: "start_flow",
          toolCallId: part.toolCallId,
          output: result,
        })
      }
    />
  )
}

The agent receives one of:

{
  action: "submit",
  values: {
    party: "3-4",
    time: "1930",
    contact: { name: "Dana Levi", phone: "+1 555 0142" },
  },
}
{ action: "cancel" }

With LangGraph

Push it from a graph node with ui.push({ name: "start_flow", props: { toolCallId, ...args } }, { message }), and render the thread's UI messages with the Renderer.

Restoring from history

When a conversation is reloaded, pass the stored result back as result. The component renders a compact, read-only summary of the answers (or "Cancelled") and never calls onResult again, so the flow can't be submitted twice. With the AI SDK, that's the tool call's output:

<GuidedFlow
  {...part.input}
  result={part.state === "output-available" ? part.output : undefined}
/>

Schema

PropTypeNotes
titlestringWhat the flow does. Names the card for screen readers and heads the finished summary
stepsStep[]2–5 steps
submitLabelstring?Final button, e.g. "Book table". Default "Submit"

Step (every type has id, title and an optional description, one short line such as a date or a constraint)

TypeFieldsNotes
choiceoptions: { value, label, description? }[], multiple?2–8 options. Data-bound when they refer to real entities
fieldsfields: { id, label, type?, required?, placeholder? }[]1–6 fields. type defaults to text
slotsslots: { id, label, available? }[]Up to 24. Data-bound
reviewLists the earlier answers with Edit buttons

Host props: status (streaming, ready, submitted, cancelled), onResult, result and className.

Source

On this page