Guides

Letting users reorder by voice in three tool calls

Repeat purchase is the cheapest first agent feature to ship. Three tools carry it, only one of them writes, and a confirm card sits between the second and the third.

VVoqal · Engineering6 min readPart of Agent basics
A flow from the phrase reorder my usual through find_last_order and check_availability to a highlighted confirm card, then place_order, then an order card drawn in the app.

About this article

Why repeat purchase first#

A user who says “reorder my usual” has already made every decision the product normally asks them to make. They chose the items on a previous visit, they chose the quantities, and they are telling you the answer rather than asking a question. The agent’s job shrinks to fetching something that exists and asking one question before it writes.

That is what makes it a good first feature. The tool list is short enough to reason about, the failure modes are visible, and you find out within a week whether the plumbing in your app works, without betting a quarter on a feature where the model has to be creative. The general case, and why a finished task beats a good answer, is the argument this sits underneath.

Two reads, one confirm, one write. The write is the only call that can change anything, and it is the only one behind the gate.

The three tools#

find_last_order takes the signed-in user and returns their most recent completed order with its line items. It reads. If the user has never ordered, it returns an empty result, and the agent has to say so rather than invent a basket. Make that case explicit in the tool description, because a model given an empty list and no instruction will sometimes fill it.

check_availability takes those line items and returns, for each one, whether it is in stock and at what price today. Prices move and products get delisted, so the basket the user is about to approve is rarely the basket they bought last time. This is the call teams skip in the first version and add after the first support ticket.

place_order takes the approved line items and writes. It is the only call in the flow that changes anything, and it runs after the confirm, never before.

Three tools, and the middle one decides whether users trust the feature. This walkthrough assumes you have already decided what an in-app agent is and what you would let it touch. How those three reach your backend at all is the tool seam, which is a longer story than this one.

Where the confirm sits#

Dismissing the card is a complete, valid ending. Nothing was written on the way to it.

An action tool does not execute when the model selects it. It resolves to a confirm widget carrying what the model intends to do: the items, the count, the total, the address. The user reads it and taps, or dismisses it and nothing at all has happened.

This is worth being precise about, because it is the property that makes the whole pattern shippable. The model is not trusted with the write. It is trusted with a proposal, which a person then approves in an interface your team designed. If the model misreads “my usual” and proposes last month’s party order instead of last week’s groceries, the cost is that the user reads six items, says no, and rephrases. Nothing to reverse, nothing to refund, no support ticket.

The card itself should show the numbers a person would check before paying: item count, total, and anything that changed since last time. A confirm card that says “Place your usual order?” with a single button is a dialogue box wearing a nicer font.

Substitutions, which is the actual hard part#

Two of the six items are out of stock. Now what?

The tempting answer is to have the agent pick replacements and mention them in the spoken sentence. It reads well in a demo and it is the wrong call. Users do not audit a sentence the way they audit a list, and a substitution the user did not notice becomes a complaint about the wrong product arriving, which is more expensive than the abandoned basket you were trying to save.

Show it instead. The confirm card carries the four items that are available, the two that are not, and any suggested replacement as an unchecked option the user has to actively accept. The spoken answer says that two things are unavailable and stops there, because speech is a bad medium for a list the user has to inspect.

The Voqal assistant sheet inside a grocery app, showing a list of milk products with sizes, prices in Egyptian pounds and an add button on each row.
A products widget in the Rabbit demo app, drawn from a render spec. The card, the type and the add button are Rabbit's own components, so the widget inherits the app's brand rather than sitting inside a themed chat frame.

The same principle covers a price change. If the total moved more than a little since the last order, the card says so above the button rather than below it.

What the app has to provide#

Very little, which is the point. The app opens the assistant, hands over the user’s existing token on each request, and renders the widget types it has registered. The reorder flow needs three of them: a products list, a confirm card, and an order card for the result. Each one’s payload is in the widget catalogue.

None of those are chat components. They are your components, registered against a widget type, so the list of milk in the screenshot above uses the grocery app’s own card, type scale and add button. A user who taps “add” on a row in that list is in the same interaction they would be in anywhere else in the product.

What to measure#

Instrument three things before you ship it, because each one tells you about a different failure.

Confirm-card dismissal rate tells you whether the model is proposing the right basket. A high rate means “my usual” is resolving to the wrong order, and the fix is in the tool rather than the prompt. Time from first word to confirm card tells you whether the two reads are fast enough to keep in the same turn, or whether the availability check belongs behind a loading state. Completion rate after tap tells you whether the write path is solid under the conditions real phones are in.

None of those need a model to interpret. They are ordinary product metrics, which is a good sign that the feature has stopped being an experiment.

Filed underAgentsTool designCommerceConfirmation

Next

The confirm, products and order widgets this flow returns, with the payload each one expects.

See the widget catalogue

The rest of Agent basics

Open the cluster

The structural difference between something that answers and something that finishes the task, and how to tell which one a vendor is selling you.

Elsewhere on the map