Skip to content
Nasir Nasir-Ameen
Notes

Gazelle's Kitchen

Saying "I want to order" should not get you through to the owner

The design behind a WhatsApp assistant for a food business whose real problem was harassment disguised as orders, and why the language model is not the part that decides anything.
7 min read

The obvious reading of a WhatsApp assistant for a small food business is that it exists to reply faster, so fewer orders are lost.

For Gazelle's Kitchen that was not the problem. The owner was being contacted by people who opened with something that looked like an order and then turned the conversation personal or abusive. "I want to order" had become a way to get her attention.

That changes what the system is for. A faster chatbot would have made things worse.

Why an ordinary AI assistant is the wrong tool

A language model is built to keep a conversation going. It is polite, it responds to whatever it is given, and it will happily engage with someone who has no intention of buying anything.

For this business, every one of those qualities is a liability. A person who is there to harass gets a patient conversation partner, and if the assistant escalates anything it does not understand, they get the owner as well. The assistant becomes the route in.

So the first decision was about what the model is not allowed to decide. It does not decide who reaches the owner. It does not decide whether an order is complete. It does not decide whether a reply should be sent at all.

Access is earned by a complete order

The rule that replaced "they said they want to order" is simple to state: a conversation reaches the owner when it contains a complete, valid order, or when there is a genuine reason a person is needed.

Complete and valid are checked by fixed rules, not by the model. The item has to be on the menu the owner has published. The order has to fall inside the ordering window she has set for that meal. The quantity and the customer's name have to be present. The total is worked out from her published prices.

Until those are satisfied, the assistant keeps working with the customer and the owner sees nothing. Someone who never gets past "I want to order" never becomes her problem.

Rules decide, the model words it

The model still has a job. It helps read what a customer wrote and it phrases the reply so it sounds like a person and not a form.

What it cannot do is change an outcome. If the rules say an order for Saturday's meal cannot be placed on a Thursday, the customer gets that answer however they phrase the request, and however the model might have been persuaded. I think of it as two layers: the lower one owns every decision and the upper one owns only the wording.

This is also what makes the system testable. A decision made by rules gives the same answer every time, so I can write a test for it. A decision made by a model can only be sampled.

Silence is a response

The part I thought hardest about was what to do with a message that is personal or abusive.

The obvious design is a firm, polite refusal. I decided against it. A refusal is still a reply, and a reply is what the sender came for. It gives them something to argue with.

So for those messages the assistant sends nothing. No reply, no draft waiting for approval, no task for the owner. By default the message is not passed to a model at all. From the sender's side, nobody is there.

The exception is a credible safety concern, which is raised to the owner privately. That is the one case where interrupting her is the right outcome.

The owner sees only what needs a person

Her console is deliberately short. It holds qualified orders, real support exceptions, cases the rules could not settle, and safety concerns. She can take over any conversation herself.

The measure of success is not how many conversations the assistant handles. It is how few of the wrong ones reach her.

How I tested behaviour, not sentences

Testing an assistant by reading its replies does not scale and does not prove much. A reply can sound right and leave the system in the wrong state.

So the tests assert on what the system did. Given this conversation, was a reply sent? Was an order created? Did anything reach the owner? I ran that across 700 simulated conversations, including ones written to push at the rules and ones generated at random.

One set matters more to me than the rest: a collection of purely personal messages, where the only acceptable result is that nothing happens. No reply, no draft, no owner task. If that set ever produces an output, the test fails.

Where it stands

This is a pilot. The core is built and has been exercised in production mode, and the remaining acceptance checks against the real WhatsApp number are still a gate before I would call it fully live. Thresholds, the wording of the rules and the owner's operating details are not published, because they are hers.

The idea I would carry to any similar system is the first one: before deciding what the model should do, decide what it must never be the one to decide.