Writing

Designing for AI That Calls the Real World

At Aurora, the model doesn't scrape a database. It phones a dozen businesses at once and verifies what they say. Designing an interface for that kind of uncertainty broke most of my instincts about loading states.

AI ProductJul 12, 20268 min read

Most AI products retrieve. You ask, the model reaches into an index or a vector store, and text comes back. The uncertainty is hidden — the answer either exists or the model politely invents one, and either way it arrives in under two seconds looking equally confident.

Aurora is different. When you ask for the cheapest in-stock part, a same-day appointment, or whether a shop actually has the thing on the shelf, the system calls the businesses. In parallel. On the phone. In real time. Then it cross-checks what they said before it shows you anything. Which means the interface has to represent a world that is genuinely, honestly unresolved for ten, twenty, sometimes forty seconds at a stretch.

I've spent the last year designing that gap. Almost everything I believed about loading states, progress and confidence turned out to be a habit borrowed from products where waiting was an accident rather than the actual work.

Retrieval is cheap. Acting is expensive.

The distinction that reorganised my thinking: a retrieval product's worst failure is a wrong sentence. An acting product's worst failure is a wrong phone call — to a real business, occupying a real person, on behalf of a user who didn't quite ask for it. The cost of being wrong stops being embarrassment and starts being someone's Tuesday afternoon.

That changes the design brief in three concrete ways. Actions need consent before they happen, not an undo afterwards. Progress has to be legible while it's still running, because you can't roll a phone call back. And the system has to be willing to come back with less than you asked for, on time, rather than everything you asked for, eventually.

In a retrieval product, latency is a tax. In an acting product, latency is the product doing its job in public.

The loading spinner is a lie

A spinner says wait, something is happening. It says nothing about what is happening, or whether it's going well. For a two-second fetch that's fine — the spinner is a placeholder for an absence nobody has time to notice. For a thirty-second fan-out of live phone calls, a spinner is an act of cruelty. Users assume it's broken. Then they leave, and the calls keep happening on their behalf, which is the worst possible outcome for everyone including the businesses we just dialled.

So we killed the spinner and replaced it with presence. You watch the work happen: eleven businesses dialled, four picked up, two put us on hold, one quoted a price we're now cross-checking against the others. Rows arrive as they resolve. Nothing is faked, nothing is smoothed — if a call is sitting in a hold queue, the row says so, and the little timer keeps counting because that is the truth.

The wait did not get shorter. It got legible. And legible waiting feels roughly three times faster than opaque waiting, which is a claim I didn't believe until I watched the session recordings. People don't abandon slow interfaces. They abandon interfaces that stop telling them things.

  • Show the unit of work, not the aggregate. Eleven rows moving independently beats one bar creeping to 40%.
  • Never invent progress. A fake bar that hits 90% and stalls is worse than no bar; it converts patience into betrayal.
  • Let the first result land early. One verified quote at eight seconds buys you thirty more seconds of attention.
  • Keep the timer honest. If a call has been on hold for ninety seconds, say ninety seconds.

Showing confidence without showing off

A verified quote and an unverified one cannot look the same. But putting a percentage next to every price turns the screen into a spreadsheet and quietly tells the user we're not sure about any of this. Confidence scores are real, and they are the most seductive garbage a team can ship: they feel rigorous, they're trivial to render, and they push the entire interpretive burden onto the person least equipped to carry it.

We ended up with three states, not a hundred:

  • Verified — two or more independent sources agree, or the business confirmed it on the call. Shown plainly, with no adornment at all. Trust is the absence of hedging.
  • Reported — a single source said it. Marked with a quiet label, not an alarm. The user can tap through to hear the clip.
  • Stale — true an hour ago, unconfirmed now. Greyed, with a one-tap re-check that costs the user nothing but a few seconds.

Three states are a design decision disguised as a data model. Internally the model still produces a continuous score; the interface makes the call about where the thresholds sit and takes responsibility for it. Ninety-seven shades of confidence is honesty that helps no one — it's a way of pre-blaming the user for whatever happens next.

The one place we do expose the raw evidence is the receipt: every quote can be opened to reveal who said it, at what time, and a transcript of the moment they said it. Aggregate confidence is noise. A specific quote from a specific call at 2:14pm is proof, and proof is what people actually want when the stakes are real.

Keep a hand on the wheel

Autonomy demos beautifully and lives badly. The first version of the flow was gloriously hands-off: ask, wait, receive. It tested well for about four minutes, right up until someone wanted to change the question halfway through and discovered there was no way in.

Every long-running action now has three affordances that are always available, never buried in a menu, and never disabled while work is in flight:

  1. Stop. One tap kills the whole fan-out. It is the largest destructive control in the product and it never asks are you sure — a user who wants to stop phoning strangers should not have to negotiate.
  2. Narrow. Drop the six businesses that clearly aren't it, and the remaining calls re-prioritise. Steering mid-flight is worth more than perfect initial input.
  3. Take over. The number, the name and the context are one tap away, because sometimes the fastest path is a human making the call themselves. Handing the user the phone is a feature, not an admission of defeat.
Autonomy is a spectrum, and the useful part of it is the middle. Design the dial, not the switch.

Design the sad path first

Roughly half of Aurora's calls end in a way the happy path never anticipated. Voicemail. A disconnected number. An IVR tree with no human at the bottom of it. A person who says call back Monday. A shop that closed permanently but is still listed as open everywhere on the internet.

If you design the beautiful result screen first and bolt error handling on afterwards, the product feels like it's lying the moment reality intrudes — because it is. The polished screen was drawn for a world where everyone picks up.

So now I sketch the failure states before the success state. What does the screen say when six of ten businesses never picked up? The answer cannot be an empty page with a shrug. It has to be four real quotes, plus an honest, specific note about the six that went nowhere, plus one obvious next move. Partial truth delivered with composure beats a perfect answer that never arrives.

Two rules came out of that, and they've survived every redesign since. First: a screen is not finished until its empty, partial and broken versions are drawn. Second: every dead end owes the user an exit — re-run, widen the radius, try tomorrow morning, or hand it over. A dead end with no door is where trust goes to die.

An AI product is only as trustworthy as its worst-looking screen.

What we measured instead of latency

We stopped optimising time-to-answer as the headline metric, because it turns out nobody experiences it. What people experience is the shape of the wait. Three numbers replaced it, and all three moved in ways that raw latency never explained:

  • Time to first signal — how long until anything true appears on screen. Under four seconds and abandonment collapses, almost regardless of total duration.
  • Abandonment during work — the share of people who leave mid-run. This is the real read on whether your progress design is honest or decorative.
  • Post-answer verification — how often someone opens the receipt to check a quote. Counter-intuitively, we want this non-zero: it means the evidence is discoverable, and the people who check it convert far better than the people who don't.

Total run time barely moved across two quarters. Completion went up by a third. The system didn't get faster; it got easier to believe.

What carried over

The lessons generalise past phone calls. Any AI acting in the real world — booking, buying, negotiating, filing — will be slow, partial and occasionally wrong. The design job is not to paper over that. It's to make uncertainty read as competence: we are working on it, here is exactly where we are, here is what we already know for sure, and we will tell you the truth the moment we know more.

Every product I've built since starts from the same three questions. What does this look like while it's still happening? What does it look like when it half-works? And what can the user do, right now, without waiting for us? Answer those and the happy path mostly draws itself.