Guided Flow
A short multi-step flow inside the chat, like booking a table or returning an item.
≈ 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
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
reviewstep 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
| Type | Shows | Value in the result |
|---|---|---|
choice | Option cards, one pick or several with multiple | The option value, or an array of values |
slots | A grid of times. Unavailable slots are shown struck through and can't be picked | The slot id |
fields | Labelled inputs: text, email, tel, number, textarea, date | { [fieldId]: string }, empty optional fields left out |
review | Every earlier answer, each with an Edit button | None |
Interaction
| Input | Action |
|---|---|
| Next | Disabled until the step is valid. On the last step it becomes the submitLabel button |
| Enter | In a single-line input, continues to the next step. If the step isn't valid yet, it shows every error on the step |
| Back | Previous 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
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,
}),
}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
| Prop | Type | Notes |
|---|---|---|
title | string | What the flow does. Names the card for screen readers and heads the finished summary |
steps | Step[] | 2–5 steps |
submitLabel | string? | 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)
| Type | Fields | Notes |
|---|---|---|
choice | options: { value, label, description? }[], multiple? | 2–8 options. Data-bound when they refer to real entities |
fields | fields: { id, label, type?, required?, placeholder? }[] | 1–6 fields. type defaults to text |
slots | slots: { id, label, available? }[] | Up to 24. Data-bound |
review | Lists the earlier answers with Edit buttons |
Host props: status (streaming, ready, submitted, cancelled), onResult, result and className.