The sentiment_router skill
What the skill does
Most customer-support escalations come too late. By the time the customer types "I want to speak to a manager", they've already had a bad experience. sentiment_router gets ahead of this.
The skill scores every customer message for sentiment on a 5-level scale: very positive, positive, neutral, frustrated, angry. When sentiment crosses a configurable threshold (default: frustrated for 2 consecutive turns, or angry for 1 turn), the skill triggers a downstream action:
- Route to a human via the escalate_to_human skill.
- Switch the bot's tone to de-escalation mode (more apologetic, more conciliatory, less product-focused).
- Tag the conversation as
at_riskfor prioritization in your Live Chat inbox. - Fire a webhook so your customer-success team gets a Slack alert.
The skill is on Starter and above. Starter+
Signals the skill watches
The skill considers four input types per message:
- Keyword patterns. Direct anger markers ("this is ridiculous", "I'm furious", "absolutely useless"). Configurable phrase list.
- Punctuation and capitalization. ALL CAPS, multiple exclamation points, sequential question marks.
- Negation and intensifiers. "still doesn't work", "third time I've asked", "completely broken".
- LLM-side sentiment classification. Each message runs through a sentiment classifier that returns the 5-level score.
The four signals combine into a single per-message sentiment score. Consecutive low scores trigger the configured action.
Setup
The skill is on by default once you enable it. Configure under AI Agents > Skills > sentiment_router:
- Trigger threshold. Default: frustrated for 2 consecutive turns, or angry for 1 turn. Tighten if you want earlier intervention; loosen if false-positives are an issue.
- Action on trigger. Pick one or more: escalate to human, switch to de-escalation mode, tag conversation, fire webhook.
- De-escalation system prompt. The system prompt swap when de-escalation mode fires. Default emphasizes apology and acknowledgment.
- Webhook URL. Where to POST when sentiment crosses the threshold.
Per-channel overrides let you have different triggers for different channels. For example, WhatsApp customers tend to be more direct in language, so you might tighten the threshold there.
Per-channel behavior
| Channel | Default action | Latency |
|---|---|---|
| Web widget | Escalate to live chat | Under 500 ms |
| Tag conversation + Slack alert | Under 1 second | |
| Switch to de-escalation drafting | Per email-poll cycle (60s) | |
| Slack | Ping designated user | Under 500 ms |
The de-escalation mode
When de-escalation triggers (and you've configured it instead of immediate escalation), the bot's system prompt swaps to a softer version. Effects:
- Bot opens with acknowledgment. "I'm sorry you're dealing with this; let me see what I can do."
- Bot avoids "no" or "I can't" phrasings. Even when the answer is no, the phrasing softens.
- Bot offers escalation proactively. "Would you like me to connect you with a human?" appears in every reply.
- Bot avoids product-pitch tone. Marketing-style language gets stripped.
De-escalation is a temporary state, lasting for the duration of the conversation. New conversations start fresh in normal mode.
False positives
Sentiment classifiers aren't perfect. Two common false-positive sources:
- Sarcastic positive. "Oh great, ANOTHER broken page" reads as positive on keyword detection but is clearly angry. The LLM classifier usually catches this; the keyword path may not.
- Cultural variance. Direct phrasing in some cultures reads as angry to a US-trained classifier. Indian English and German English are common false-positive triggers.
Tune the threshold tighter for your specific user base. Test with sample conversations under Skills > sentiment_router > Test Mode.
False negatives
The other failure mode: customer is angry but the classifier missed it. Usually because the customer is staying polite. Watch the Live Chat > Tagged "at_risk" view for cases your classifier might have missed; manually retraining the keyword list closes the gap.
Webhook payload
When the skill fires, the webhook POST includes:
{ "event": "sentiment.threshold_crossed", "conversation_id": "conv_xxx", "workspace_id": "wt_xxx", "channel": "widget", "current_sentiment": "angry", "consecutive_negative_turns": 2, "customer_email": "verified@example.com", "recent_messages": [...], "request_id": "req_xxx"}Subscribe to it under Dashboard > Webhooks > Add Endpoint with the sentiment.threshold_crossed event.
Limits
- Plan availability. Starter and above.
- Per-message latency. Under 200 ms added to bot response time.
- Multi-language support. English, Spanish, Portuguese, German, French, Hindi, Mandarin. Other languages fall back to keyword-only detection.
Common pitfalls
Skill triggers on every conversation. Threshold is too tight, or your knowledge base is making the bot unhelpful so customers complain about the bot. Investigate the bot's answer quality first; sentiment_router is a symptom, not a cause.
Customer says "I want a human" but no escalation. That's not sentiment, that's explicit escalation. The escalate_to_human skill handles this separately.
De-escalation mode persists into next conversation. It shouldn't; state is per-conversation. If you see persistence, check Settings > Conversation State > Reset Policy.
False positives on slang. Add the slang phrases to Skills > sentiment_router > Allowlist to prevent matching.
FAQ
Does the customer know the bot detected anger?
No. The skill operates silently. The customer just sees the bot's response (in de-escalation mode) or gets transferred to a human (escalation mode). No "I detected that you're frustrated" disclosure.
Can I use this for prioritization without auto-escalation?
Yes. Set the action to tag-only. The conversation gets tagged at_risk in your Live Chat inbox; your team picks it up at their pace.
Does the skill consume an extra query per message?
Yes. Each per-turn sentiment classification counts toward your query quota. For high-volume workspaces, the cost adds up; budget accordingly.
Can I disable sentiment_router per visitor?
Not directly. The skill runs workspace-wide. If you want it off for VIP customers, you can use audience-tagged routing to skip the skill when a specific audience matches.
How is this different from escalate_to_human?
escalate_to_human fires when the customer explicitly asks or when low-confidence answers chain. sentiment_router fires when the customer is frustrated but hasn't explicitly asked yet. Both work together: sentiment_router catches anger earlier.