The five signals Opzello looks for in a customer conversation
A shared WhatsApp number collects far more than it reports. Here are the five business signals our AI tags every conversation with, exactly how each one is detected, and the two places we refuse to guess.
A WhatsApp number that one person answers is a conversation. A WhatsApp number that fifteen people answer is a filing system nobody maintains. Every individual thread is complete and correct; the picture across threads exists nowhere. The person who handled Tuesday's angry customer is not the person who reads Friday's request for a quote, and neither of them can tell you whether the same complaint arrived eleven times this month.
Opzello's answer to that is not another dashboard. It is one AI pass over each conversation that tags it with a small, fixed set of business signals. This post is what those five signals are, how each one is actually detected, and the two places we deliberately refuse to guess.
One conversation, one call, strict JSON
When a conversation is analysed, its last forty messages are assembled into a transcript and sent to the model with a single instruction: return a JSON object containing a sentiment, one to five free-form intent tags, up to three signals, a one-sentence statement of what the customer needed, a satisfaction estimate from 0 to 100, and a two-to-three sentence summary.
Two of those fields do very different jobs. Intent tags are free-form — price_inquiry, shipping_question, refund_request — and they are useful for reading, not for counting, because next week the model will happily produce a synonym. Signals come from a fixed list of five, and anything outside that list is thrown away on our side before the result is stored. That is what makes them countable, filterable, and comparable from one month to the next.
The five
Complaint. The customer is unhappy about a product, a service, or an experience. Not "wrote a long message" — unhappy about something specific.
Buying signal. The customer shows clear interest in purchasing: asks the price, asks whether you have it, asks how to order.
Churn risk. The customer threatens to leave, mentions a competitor, or shows repeated frustration across the thread.
Question. The customer asked something that has not been answered anywhere in the transcript. This is not a category of message. It is a category of silence.
Missed follow-up. Your business promised something — a callback, a quote, a delivery update — that never appears in the transcript. Also silence, but yours.
Those last two are worth pausing on. Three of the five describe the customer's state, and a good agent reading the thread would notice them too. The other two describe your side of the conversation, and they are the two a human reviewer almost never catches, because catching them means re-reading a thread you already closed and noticing what is not in it.
What gets built on top
Because the five are fixed, the inbox can be filtered by them. Asking for every conversation carrying buying_signal returns a deterministic list, not a keyword search that depends on whether the customer wrote "price" or "cost".
Weekly, the three signals that mean something has gone wrong — complaint, churn risk, missed follow-up — are clustered into named business problems, each with the conversations it was drawn from and one concrete suggested action.
That clustering has a floor: fewer than three flagged conversations in the period and no report is produced at all. A pattern found in two threads is not a pattern, and publishing it would teach you to distrust the reports that are real.
Where we refuse to guess
If the model returns something unusable — the workspace has run out of AI tokens, an administrator has the AI switched off, the reply will not parse — the conversation is left unanalysed.
It is tempting to store the defaults instead: neutral sentiment, no signals, analysed just now, done. We don't, because that row is indistinguishable from a real verdict. It would drag down every average in your analytics, and the timestamp it writes would stop that conversation from ever being looked at again. A gap you can see is better than a verdict you cannot.
The second refusal: every signal is a link, not a number. A count of eleven churn risks you cannot click into and read for yourself is a number you have to take on faith, and nobody should take a machine's reading of their own customers on faith. The same applies to replies — the AI drafts them, a person sends them.
An honest caveat
Opzello has not launched. There are no customers to quote here, no before-and-after numbers, no case study. What there is: a taxonomy of five, a prompt that spells each one out, a rule that discards anything the model invents beyond the list, and a refusal to store a verdict we did not actually get.
If you run a WhatsApp number that more than one person answers, and you think a sixth signal is missing from that list, we would much rather hear it now than after we have built a year of reporting on top of five.