I've spent the last few weeks going back and forth with two chatbots that never really talked to me. One kept pushing a delivery time further and further away every time I asked. The other one let my order get marked "delivered" when it wasn't, then handed me off between agents who couldn't see what the last agent had already promised — until Zomato's own email team told me the order was fine and I was wrong.

As a UX designer, I know the difference between a bug and a decision. What I ran into wasn't a bug.

What I Was Actually Talking To

Before I get into what happened, it's worth being clear about what's on the other end of that chat window, because it isn't a simple FAQ bot anymore.

Swiggy and Zomato are not companies that lack the technology to solve my problem in real time. They've built a fairly sophisticated AI layer and pointed most of its intelligence at ordering and logistics — and pointed a much shallower, scripted layer at me, the person with a complaint.

And I'm not the only one who's noticed the gap. Independent reporting (Moneycontrol, via Storyboard18) documents the same complaint across both platforms: the chatbot handles standard, scripted situations fine, and stalls — often with no visible way to reach a human — the moment the issue doesn't fit a preset category. That's not an isolated bad day. That's a boundary someone drew on purpose.

Case 1: Swiggy — The Delay That Never Actually Resolves

Swiggy support chat repeating the same delay reply as the user asks again
Ask again, get the same answer — the loop with no exit.

Here's what happened, in order:

The loop

1
My order is late, or the tracker shows the rider in the wrong place.
2
I open chat, ask what's going on.
3
The bot gives me a new ETA.
4
The ETA passes. I go back.
5
The bot apologizes, pushes the ETA out again, and says something close to what it said the first time.
6
I ask directly to speak to a human.
7
It says no — and loops back to step 5.

I know this pattern has a name, because I went looking. UX researchers now catalogue this as "defensive AI" support design, and the mechanisms match what I experienced almost exactly:

🔁
Endless Loops
My ETA kept moving instead of anyone offering an actual fix.
🚪
Hidden Human Access
I asked directly for an agent. Refused.
🎭
Strategic Deflection
Same message, rephrased, every time.
Response-Speed Manipulation
Every loop cost me time until I gave up.

Here's why, from a business-metrics standpoint, this is a completely rational thing for Swiggy to build, even though it's terrible for me: every conversation the bot contains — resolves or exhausts, doesn't matter which — is one conversation that never reaches a human agent's queue, never gets logged as a failure, and never costs a refund. Support teams call this containment rate, and it's a real KPI. An ETA-push loop that never escalates is a very efficient way to keep that number high.

As a designer, here's where it breaks, heuristic by heuristic:

Visibility of System Status
The ETA isn't a status. It's a placeholder. The system almost certainly knows the rider is idle or in the wrong geofence; it just doesn't tell me that.
User Control and Freedom
I asked to leave the automated flow. There was no exit.
Error Recovery
The bot has no memory that its last answer already failed me. Every turn resets like it's the first time I've asked.
Honesty
A "new ETA" implies a forecast based on real information. If it's actually just a stall tactic, that's a false affordance — the interface is pretending to have a capability it isn't using.

Case 2: Zomato — The Order That Was "Delivered" to No One

This one I lived through in more detail, so let me walk it the way it actually unfolded.

The delivery partner marks my order "Delivered." It was not delivered. I contact chat support. An agent calls the rider, who admits on that call that he marked it wrong, and promises delivery in 10 minutes.

Ten minutes pass. Nothing. I try calling the rider directly, but the number Zomato shows is a masked, centralized number, starting with the same prefix Zomato's own support agents call from, so I genuinely can't tell if I'm talking to the rider or someone else. When I do get through, he tells me he's now on a Rapido trip and will take longer.

I go back to Zomato chat. A different agent picks up the thread with zero visibility into what the first agent already confirmed — that the rider admitted the mistake. I'm re-explaining the entire thing from scratch. This agent makes the same 10-minute promise, as if it's the first time it's been made.

The order never comes. The chat times out from inactivity and closes on its own. When I try to reopen it, I don't get an agent — I get a system message along the lines of "query is still not resolved. Please describe your issue in detail," with a text CTA "Add comment," with absolutely no indication anyone is going to read that comment or follow up on it (I tried multiple times by adding comments in detail).

More than 24 hours after I wrote in to their support email, I finally got a reply. It said Zomato found no discrepancy — the order was delivered — flatly contradicting what two live agents had already acknowledged to my face.

The Breakdown, Mapped to What's Actually Broken

Support chat closed for inactivity while the issue is still open
The conversation closes itself — the problem does not.
01
No Memory Across Contacts
Every new chat starts cold. The second agent had no access to the first agent's acknowledgment. This is a data problem wearing a UX costume — the support tooling isn't surfacing full order-history context to whoever picks up next, human or bot, so every contact resets instead of building on the last one. It violates recognition over recall: the system should carry the context forward, not make me re-litigate it and definitely not contradict its own earlier admission.
02
"Delivered" Is Treated as Unfalsifiable
Once a rider marks an order delivered, that status seems to become ground truth for everything downstream — refunds, escalation, the email team's review — even after a live agent already contradicted it. There's no visible way for me to attach evidence (a doorstep photo, a timestamp) before the case drops into a generic email queue that starts from zero trust. That's a failure of error prevention and match between system and real world — the product models "delivered" as fact when the entire complaint category exists because that fact is sometimes false.
03
"Add Comments" Is a Dead End
Asking me to act, with no stated consequence, no SLA, no confirmation anyone reads it — that's a textbook false affordance. It looks like an input mechanism. It functions as a way to make me feel like I did something while nothing happens on their side. In dark-pattern terms, that's Hiding Information and Bait and Switch applied to support instead of checkout. Same manipulative mechanism, different screen.
04
The Support Script Doesn't Account for How Riders Actually Work
Riders working Zomato, Swiggy, and Rapido at the same time isn't rare — it's normal, documented gig-economy behavior. Studies put multi-app riders at 40–50%+ of the workforce, and platforms are reported to tolerate it partly because it helps them argue riders aren't exclusively engaged by any one platform. What it exposes is that Zomato's support script assumes the rider is fully "on" my order. "Give him 10 more minutes" is offered as a real fix when the rider may already be mid-delivery for a completely different app. That's match between system and real world breaking down at the operational level, not just in the copy.
Order marked arrived early, then a prompt to rate the order that never came
Marked delivered, then rated — the record closes over the gap.

The Pattern Underneath Both Stories

Strip the surface differences away — a delay dispute versus a phantom delivery — and I was dealing with the same architecture both times:

The chat layer is built to end the conversation. Not to close the loop on what actually went wrong.

Swiggy ends the conversation by pushing time forward until I stop asking. Zomato ends it by resetting context (new agent, no memory) or letting it expire (auto-close, dead-end comment box) until I stop asking.

Both are containment-first, resolution-second systems. At the scale these platforms operate, that's a defensible cost strategy on paper. In practice, it costs three things UX is supposed to protect:

What gets lost

  • Trust — an interface that implies action without follow-through teaches me the interface lies to me.
  • Accountability — when an email team can flatly deny what a live chat agent already confirmed, I'm not dealing with one company. I'm dealing with several disconnected departments sharing a logo.
  • Escalation as a right, not a favor — refusing a direct, explicit request to speak to a human is the single most hostile move a conversational interface can make. Both platforms, independently, made it.

What I'd Fix

Support chat offering a clear choice between calling and chatting with an agent
What it could be: a real route to a person, offered up front.
1️⃣
Force-escalate on repeat contact
Bot detects repeat contact on the same order and force-escalates after 2 unresolved turns — escalation shouldn't depend on how long I'm willing to keep asking.
2️⃣
Human access as a hard rule
A direct request for a human should be a hard rule outside the model's discretion, not something the AI gets to decide against.
3️⃣
One shared ticket per order
Every contact on an order (chat, call, email) writes to one shared ticket, visible to whoever picks it up next.
4️⃣
A disputed-delivery state
A state between "Delivered" and "Refunded" that unlocks evidence upload and pauses auto-closure.
5️⃣
Every action needs a visible SLA
Any action I'm asked to take needs a visible SLA — "a specialist responds within X hours" — or it shouldn't be presented as an action at all.
6️⃣
Query live rider status
Support should query live rider status instead of promising a callback window it can't actually guarantee.