A conversation, end to end
One conversation traced through a flow agent — from a tap in your app, or a phone call, through the welcome message, the first step, variables, a tool, a component on screen and the paths taken, to the goodbye and the record it leaves.
The other flow pages describe each part on its own. This one follows one conversation through a small flow, turn by turn, so you can see the parts work together: where the data comes from, which step runs when, what the customer hears, sees and taps, and what is left behind afterwards. Each stage links to the page that covers it in full.
The conversation starts in your app, from the assistant bar. The same flow also answers phone calls, and every stage says what differs on one.
The flow
An appointment helper: it checks the customer has a booking to move, lets them pick a new time, books it in your own system, and says goodbye.
Three things outside the flow take part:
| What it is | Where it is set up | |
|---|---|---|
offer_appointment_times | A component — calendar slots drawn on the customer's screen. Its When they tap is Open a screen with the path appointments?time={id} | Web components, switched on for this agent under Embed & Widgets → On screen — Components |
move_appointment | One of the agent's tools: a request to your own server with appointment_id and new_time | The builder's Tools area — Tools, transfers and knowledge |
open_screen | An in-app action your app answers by navigating | Declared under Embed & Widgets, handled in your app — Actions |
The flow's defaults give business_name the value Acme; every other
variable comes from the conversation itself
(The Variables panel).
How it works
The path this conversation takes. Dashed boxes say nothing to the customer: the branch decides within a turn, and no_booking is the path not taken.
The trace
Before anyone speaks: the data
The customer, Rohan, is on your app's appointments screen. Your app has already told the agent who he is, what he has booked and where he is:
The Android, iOS and Flutter SDKs take the same values through identify,
setVariables and setScreen. When the conversation connects, these become the
conversation's data: the flow fills {customer_name} from it, and rules read the
same values as recipient_data.customer_name and recipient_data.open_bookings.
Values travel as text, so 1 arrives as "1"; a rule still compares it
as a number. The flow's own defaults fill only what is still missing — here,
business_name.
On a phone call the same data comes from a campaign's columns or the
variables of POST /v2/calls, and there is no screen.
Variables in text
The conversation connects: the welcome message
Rohan taps the bar. The conversation opens, following the same flow as the agent's phone calls, and the welcome message plays at once: "Hi Rohan, this is Asha from Acme." It is not a step, and nothing in the flow has run yet. In a chat it arrives as text.
On a phone call it plays when the call connects. Give every variable in the welcome message a default: on a phone call it is prepared before the call connects. When the call connects
Turn 1: three steps in one turn
Rohan: "Hi — I can't make it on the 15th. Can we move my appointment?"
- The first step runs now, on his first words.
confirmhas two AI-decided paths, so the decision model reads their conditions and the conversation, and picks "The customer wants to move their appointment". - The branch decides in the same turn.
has_bookingsays nothing: its rule holds ("1"is above0), so the call moves on topick_time. With no booking, the Always path would have taken it to the fixed lineno_bookinginstead. - The step the call is now on replies. Rohan hears
pick_time;confirmnever speaks, because his first words already answered it.
Still turn 1: a component on screen
pick_time's instructions tell the AI to show the open times. The component is a
tool the AI calls by its name, offer_appointment_times: it says one is coming, the SDK
draws your loader, and the calendar slots appear on Rohan's screen in your
brand's design — fetched from your API at that moment if the component has an
endpoint. The AI says: "I've put the next three dates on your screen — which
suits you?"
The AI reply step also knows which screen Rohan is on and which component is open, and could call your in-app actions. Which tools it calls on a step it decides itself; only Uses a tool forces one.
On a phone call there is no screen and no component: write the step's instructions so they also work by voice ("…or read out two dates if they cannot see a screen"), or give each surface its own agent. On your website and in your app
Turn 2: the tap is a turn
Rohan taps Fri 17 Oct, 10:00. Three things happen:
- The choice reaches the agent as Rohan's next turn — "Friday 17 October at 10:00 works" — and the structured answer goes to your webhook.
- The component's When they tap → Open a screen runs your
open_screenhandler withappointments?time=…, and your app reports the screen it lands on. pick_time's paths are checked: the decision model takes "The customer has chosen a time" and collectsnew_timefrom the conversation. From now on, text can say{new_time}and rules can testnew_time.
The call moves to book, which uses a tool: on arriving it must call
move_appointment, so your server receives the booking and the new time, and
the AI speaks from what your server answered: "Done — you're booked for Friday
17 October at 10:00. It's on your appointments screen." Had new_time been
missing, the step would have replied without calling the tool: its instructions
use {new_time}, and the tool requires it.
Collecting values on the way · Make a step use a tool · When they tap
Turn 3: the goodbye ends it
Rohan: "Great, thanks." book has one path, Always, so the call moves to
goodbye, which uses End the call: the AI says goodbye and the conversation
hangs up once the goodbye has played. In your app the SDK reports the end of
the conversation, as it does for any ending.
A step with no paths would not have ended anything: the call stays on it until the agent's call settings, in Settings › On the call, end it. How a call ends
Afterwards: what it leaves
| Where | What you find |
|---|---|
| Call History | The conversation under Rohan's name, its transcript — the welcome message, his tap as his own turn, every reply — and, for an in-app conversation, the screens he moved through and the actions the agent took with your app's answers — What lands in Call History |
| Execution Logs | Every turn's timing, and the connection's own rows for an in-app conversation — Execution Logs |
| Your server | The move_appointment request, and the component's structured answer at your webhook |
| Your webhook | The call's event, as for any call — Webhooks |
In your app and on a phone call
| Stage | In your app | On a phone call |
|---|---|---|
| Where the data comes from | identify and setVariables in your app | A campaign's columns, or variables on POST /v2/calls |
| The welcome message | Plays when the conversation connects; text in a chat | Prepared before the call connects |
| Components | Drawn on screen; a tap is a turn | None — the step must work by voice |
| In-app actions | Offered on every AI reply step | None |
| Your system moving the call | — | Events, with the call's execution_id |
| What the agent follows | The same flow, kept in step with every save | The flow as saved |
When the trace goes differently
| What you see | Why |
|---|---|
| The first step speaks even though the customer's first words answered it | The decision model did not match their words to a condition. Write the condition the way customers talk, and test by chat in the builder |
| The branch always takes Always | The rule's field is missing or not a number. A rule on a field the conversation does not have never holds — check the variable's name, and that its value reads as a number |
A {name} is silent in a reply | The variable has no value and no default, so it is left out. Set a default under Variables in the flow builder |
| A value your app set never arrives | A conversation carries up to 12 variables, about 1 KB in all — keep the ones the flow needs short and few |
| The component never appears | It is not switched on for this agent, the step's instructions do not ask for it, or the conversation is a phone call — Is it actually on the agent? |
| The tap opened nothing | Your app has no open_screen handler, or the action is not declared — Actions |
The tool was not called on book | A variable the tool requires had no value, so the step replied without it |
| The call never ends | No step uses End the call (or a fixed line set to hang up still has paths out), and the agent's settings in Settings › On the call let it run on |
Where next
How a call moves through a flow
Every rule behind the trace: turns, paths, branches, silence, interruptions and variables.
Build your first flow
Create a flow agent and find your way around the flow builder.
Components
Designing what the agent draws, and live content from your API.
Events
Move a live phone call from your own systems.

