Playbooks · 5 min read

Sentiment Analysis Is Not Here. Route the Angry Ones Anyway

The PostEngage teamEngineering and support ·

The request arrives in almost the same sentence every time: can it tell when someone is upset, and handle that one differently?

No. There is no sentiment analysis in this product. No mood score on a thread, no positive-negative label on a lead, no emotion column anywhere in the export. Nothing reads a message and decides how the person feels.

What is worth the rest of this page is why that absence has cost almost nobody anything, because the decision you actually need to make is not the decision a score is shaped for.

The decision is binary. A score is not

Sit with what you want to happen when an angry message lands. You want the automation to stay out of it, and you want to reply yourself.

That is one bit of information. Reply, or do not reply.

A sentiment score is a continuous number, so the moment you have one you also have a threshold to pick, and the threshold is where the whole idea falls apart. Is a message at 0.4 angry enough to hold? At 0.35? You will never have a principled answer, and every time the automation gets one wrong you will move the number a little and hope. That is not tuning. That is superstition with a slider attached.

Every score you cannot explain is a threshold you will end up guessing, forever.

What does the job instead

Negative keywords. A list of words that mean do not reply, sitting in the builder next to the words that mean do reply.

The list writes itself if you read a month of your own inbox rather than imagining what an unhappy customer sounds like. In an Indian inbox it usually ends up looking like refund, cancel, worst, fraud, scam, not interested, paisa wapas, bekar, complaint, late, still not received.

Matching folds case and punctuation, so WORST!!! and worst are already the same string and you do not need three spellings for shouting. It folds Latin accents too.

The automation builder with an any-of keyword list above and the negative keywords field below it.
Two lists, both written by you. The second one is the one that decides which conversations a machine never touches.

Why a list you wrote beats a number you did not

Three reasons, and none of them is about accuracy.

  1. You can read the reason. When a reply does not go out, Activity records which check stopped it. A row that says a negative keyword matched is a row you can act on in ten seconds. A row that says the sentiment score was below threshold tells you nothing you can change.
  2. You can change it in one place. A customer starts using a word you never listed. You add the word. Done, deterministic, effective on the next message. There is no equivalent move for a model that decided your customer sounded fine.
  3. It behaves the same tomorrow. The same message gets the same outcome every time, which means the test you ran last week is still true this week.

That is the same design instinct as the gate itself. Ten checks run before any reply is sent, in a fixed order — kill_switch, connection, takeover, window, dedupe, cooldown, quiet_hours, rate_budget, credits, content_safety — and each one has a name. Nothing in that list is a confidence value. Every refusal is a sentence you can read.

The ten checks listed in the fixed order they run in, from kill switch through to content safety.
Ten named reasons, in one order, every time. A refusal you can name is a refusal you can argue with.

The one place a model does look at tone

content_safety is the last check in that order, and it can stop a generated reply from going out. Replies the system is not confident about go to a review queue rather than to the customer.

Be precise about what that is, though. It judges the reply we are about to send, not the person who wrote to you. It is a brake on our output. It is not a classifier pointed at your customer, and it will never hand you a mood label for a thread.

The other half is takeover

Not replying is only half of routing an angry message. The other half is you replying.

Takeover handles the seam: automation stands down the moment a human answers by hand in that thread. So the working pattern is unglamorous and it holds up. The negative keyword stops the machine. The message sits unanswered in your inbox. You see it, you open it, you write something a person would write, and from that moment the automation is out of that conversation for good.

There is no handoff to build and no escalation rule to configure. The absence of a reply is the escalation.

What you actually give up

Two things, and they are worth naming rather than glossing.

You give up the chart. There is no dashboard here that will tell you your inbox got happier this quarter, and if that number is something you report upward, this product will not produce it. The only three data stores we keep are Activity, Leads and the credit ledger, and none of them holds a mood.

You also give up catching the polite ones. Somebody writes "no worries, I understand, thanks anyway" and means something quite different. No keyword list catches that. A sentiment model would claim to and would be wrong often enough that you would stop trusting it, which is the worst of both worlds — a signal you check and then override.

What catches those is a person reading their own inbox for ten minutes a day. That has always been the answer and no amount of scoring replaces it.

For the full list of what can stop a send and why each check exists, the safety post covers it properly. For what a generated reply is allowed to draw on in the first place, grounding is the thing to read next.

One email when we publish.

No drip sequence, no “quick question” follow-up. Unsubscribe is one click and we honour it immediately.

Try it on your own posts

Free forever. Three minutes to set up.

Start free