Every two-way SMS program eventually hits the same wall: replies start coming in faster than a person can read them. Some of those replies are legal obligations you have to honor in seconds. Some are real customers trying to buy. Some are confused people who need a human. If you treat all three the same — drop them in one inbox and let a teammate triage when they get a chance — you'll miss conversions and, worse, accidentally text someone who already said STOP.
Full disclosure: I work for ReadySMS, so I think about inbound routing more than a normal person should. But the logic here is platform-agnostic. The goal of this post is a routing tree you can draw on a napkin: every inbound message lands in exactly one bucket, the compliance-critical ones get handled by machine the instant they arrive, and the ones that genuinely need a human get escalated cleanly.
The three classes of inbound message
Before you build anything, sort inbound replies into three buckets. They behave completely differently and they have completely different urgency.
- Compliance keywords —
STOP,STOPALL,UNSUBSCRIBE,CANCEL,END,QUIT,START,HELP. These are not optional. STOP and HELP are carrier-mandated behaviors on registered 10DLC routes. Latency matters: an opt-out has to suppress the contact before your next blast goes out. - Support / intent-unclear — "is this still available?", "what's your address?", "I think I was charged twice." These need a human eventually, or an AI that knows when to hand off.
- Conversion replies —
YES,Y,CONFIRM,BOOK, a number from a menu, a coupon claim. These are the replies that make you money, and they're the ones most likely to rot in a queue.
A routing tree evaluates an inbound message in this order. Compliance first, always. You never want a clever "YES" matcher firing on a message that also happened to contain "STOP."
Layer 1: Compliance keywords, handled before anything else
This layer should never touch a human and never depend on your CRM workflows being awake.
On ReadySMS, STOP/UNSUBSCRIBE is honored automatically and the opt-out propagates across campaigns — so the contact can't be messaged again from a different list or a different workflow you forgot about. That cross-campaign propagation is the part most home-rolled setups get wrong. People build a STOP handler on their promo campaign, then their abandoned-cart automation, sitting in a separate flow, texts the same person two hours later. That's exactly the kind of double-text problem covered in the four GHL workflow mistakes that double-text your contacts — and it's also a TCPA exposure, because continued texting after an opt-out is a textbook violation.
Your Layer 1 rules, in evaluation order:
- Match opt-out keywords first (
STOP,STOPALL,UNSUBSCRIBE,CANCEL,END,QUIT). Suppress the contact globally, send the carrier-required confirmation, stop processing. Do not fall through to any other rule. - Match HELP next. Reply with your business name, support contact, and "Reply STOP to opt out." This is a static auto-reply — no human, no AI.
- Match START / UNSTOP to re-subscribe a contact who opted back in.
Practical detail: match these as whole-word, case-insensitive, trimmed. "Stop" "STOP " and "stop please" should all trigger. But don't fire opt-out on "non-stop" or "stop by anytime" — anchor to the message being primarily that keyword. Most platforms, ReadySMS included, handle the canonical keywords for you; the trap is when you add custom variants and write a sloppy contains() check that swallows legitimate replies.
Layer 2: Conversion keywords, matched tightly
Once a message survives Layer 1 (it wasn't a compliance keyword), check it against your conversion set. This is where the routing tree earns its keep, because conversion replies are time-sensitive and high-value.
Keep this set small and exact. The more keywords you match loosely, the more support questions you'll misroute as conversions. A tight set:
| Inbound | Action | Human needed? |
|---|---|---|
YES / Y / CONFIRM | Confirm appointment / claim offer, advance flow | No |
BOOK | Send booking link, tag as hot lead | No |
A digit (1, 2, 3) | Menu selection, route to matching branch | No |
Coupon keyword (SAVE20) | Apply / send code, tag | No |
| Anything else | Falls through to Layer 3 | Yes (or AI) |
The discipline here is the fall-through. If a reply doesn't exactly match a conversion keyword, it does not get an automated conversion response. "Yes I have a question about my order" should not trigger your "Great! You're confirmed!" auto-reply. Match YES as a near-standalone token, not a substring. When in doubt, fall through to a human — a misfired confirmation is worse than a slightly slower human reply.
If you're building these keyword funnels from scratch, the mechanics of capturing and matching keywords at scale are covered in SMS keyword campaigns: building an opt-in funnel that scales.
Layer 3: Everything else routes to a human (or a careful AI)
What's left after Layers 1 and 2 is the genuinely ambiguous stuff. This is where two-way messaging matters: the reply lands in a conversations inbox (and in GoHighLevel for connected accounts, mapped to the right sub-account so an agency's clients stay isolated). A person reads it and answers.
ReadySMS has an optional AI-assisted reply layer with three modes — off, suggest, and auto. For Layer 3, I'd start in suggest mode: the AI drafts a reply, a human approves it. That gives you speed without letting a model improvise on a billing dispute or a medical question. Move to auto only for the boring, well-bounded queries ("what are your hours?") once you've watched it behave for a few weeks. I'm not going to oversell this — it's a newer capability and you should treat it like a junior teammate, not an oracle.
The one rule that survives every layer: AI never overrides a STOP. Opt-out handling sits below the AI in the tree and fires first, deterministically. You do not want a model deciding whether someone really meant it.
Worked example: a clinic recall reminder thread
Say a clinic sends a recall reminder: "Hi Dana, you're due for a cleaning. Reply YES to book, HELP for support, STOP to opt out." Here's how three different replies route:
- "STOP" → Layer 1 fires. Contact suppressed across all campaigns, confirmation sent, thread closed. No staff time. Critically, the marketing list and the recall list both honor it — and if you're running recall and promo as separate consent types (you should be), see why a recall text and a promo text need different consent.
- "YES" → Layer 2 fires. Booking link sent, contact tagged as ready-to-schedule. No staff time.
- "Do you take my insurance?" → Falls through to Layer 3. Lands in the inbox, AI suggests a draft, front-desk staff confirms and sends.
One outbound message, three correct outcomes, and a human only touched the one that actually needed judgment.
Don't forget quiet hours and the consent audit trail
Routing isn't only about what you reply — it's about whether you should send at all and when. Two adjacent guardrails make the tree safer:
- Quiet-hours enforcement holds outbound sends outside permitted local hours based on the recipient's area. This applies to automated conversion replies too — if someone texts
YESat 11:40pm, you may want the confirmation to send but the follow-up nurture to wait. More on the legal-vs-smart distinction in SMS quiet hours rules. - Consent / attestation capture records opt-in for bulk and API sends, so when someone texts
STARTto re-subscribe, you've got the audit trail showing they did. Your routing tree is also your consent ledger.
And before you ever send the campaign that generates these replies, scrub the list. Honoring STOP at the inbound layer is reactive; litigator and DNC scrubbing at $0.005 per contact is proactive — it keeps the worst numbers off the send entirely.
Putting it together
The whole tree is three layers, evaluated in strict order:
- Compliance keywords → automatic, deterministic, propagates globally, no human.
- Conversion keywords → tight exact-match, automatic, tagged for follow-up.
- Everything else → human inbox, optionally AI-drafted, never overrides Layer 1.
Build it once and your inbound volume stops being a staffing problem. The replies that are legal obligations get handled in milliseconds, the replies that make money get advanced instantly, and your team only sees the conversations where a human actually adds value.
If you want to see how the automatic STOP handling and two-way inbox map into your existing stack, the integrations page walks through the GHL OAuth sync, and you can model your inbound-plus-outbound costs on the calculator before you commit a dollar. Start with Layer 1 — get opt-out right — and add the other two once the compliance floor is solid.