# An SMS STOP, end to end

The opt-out word is recognised at ingest, before any reasoning. A suppression is written against the person, a memory row tagged `block:sms` records the directive durably, and the audit trail records the refusal as a decision. Everything after that is skipped on purpose: no draft, no approval queue, no sales judgement about whether the customer really meant it.

- **Status:** Foundation
- **Audience:** both
- **Channels:** sms
- **In the app:** #/inbox, #/relationships, #/autonomy-audit
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/workflows/sms-stop/

## The chain

1. Trigger — a person decides they no longer want messages from the business.
2. External event — they reply to the business number with an opt-out word, and the provider posts it like any other inbound message.
3. Authentication and workspace resolution — the post is verified and the receiving number resolves to one workspace; a directive can only ever be written inside the workspace that received it.
4. Ingest — the payload is normalised, and the body is scanned for an opt-out word before anything treats it as correspondence.
5. Canonical record — the message is stored on the conversation. The customer's own words are the evidence for everything that follows, so they are kept rather than consumed.
6. Classification — the message is classified as a directive, not as a question. This is where the flow branches away from the ordinary inbound path.
7. Knowledge, memory and rules — a memory row against the contact, tagged `block:sms` in the tag list. `directives()` reads only tags, which is what makes the block hold on every future decision instead of being advice buried in a body.
8. Autonomy and approval — none is sought. An opt-out is not a proposal a person approves; it is a refusal that takes effect immediately, and no autonomy mode can override it.
9. Action — a suppression entry against the person, enforced at the send boundary every other outbound message passes through.
10. Result — outbound contact for that person is refused from this moment. Anything already handed to a provider is already gone and cannot be recalled.
11. Relationship, timeline and memory — the directive is visible on the contact with its origin, so the next person to open that record sees why nothing is going out.
12. Audit, usage and Needs You — the refusal and its rule are recorded, because a refusal is a decision. Nothing is queued for approval; there is nothing to decide.
13. Next — a confirmation is the conventional courtesy where a provider can carry one. On the live carrier no SMS can be sent, so the acknowledgement a customer would normally receive by text does not go out.

## What is deliberately skipped

| Skipped stage | Why | What would go wrong otherwise |
|---|---|---|
| Drafting a reply | There is nothing to answer | A generated reply to a stop request is the worst message this product could send |
| Approval in Needs You | Nobody approves an opt-out | A queue would delay a refusal that must be immediate |
| Sentiment judgement | Matching is literal | A model deciding whether somebody meant it makes an unauditable rule out of a legal one |
| Sales classification | A directive is not an objection | Treating withdrawal of consent as a stage in a pipeline is exactly the failure this path prevents |
| Retry | The write either happened or the request failed loudly | A silently retried block could produce duplicate entries with different origins |

> **Note** The short path is the safe path. Each stage removed here is a stage that could delay or dilute the refusal, and none of them adds anything the customer asked for.

## What a person sees afterwards

1. Open the contact.
   - Result: The suppression is shown with its origin — an inbound opt-out, rather than something somebody added by hand.
2. Open the conversation.
   - Result: The message that caused it is there in the customer's own words, which is what makes the entry reviewable months later.
3. Open the Decision Log.
   - Result: The refusal appears as a decision with its rule. Later attempts to contact that person appear as refusals too, so a stalled sequence explains itself.

If the block should be wider than one channel — and a person who texts **STOP** often means every channel — widen it on the contact rather than adding a second entry per channel. [A do-not-contact reaching every channel](/docs/workflows/dnc-across-channels/) is that flow, and it is one memory row rather than five.

## Questions

### Does an autonomous workspace behave differently here?

No. Autonomy governs what Connect may do without asking; it has no mode that permits contacting a suppressed person. The most autonomous configuration and the most cautious one honour a stop request identically.

### What if the opt-out arrives while a campaign is running?

Anything not yet handed to a provider is refused at the send boundary when it is attempted, including steps scheduled earlier. Anything already handed over will be delivered — no messaging network offers a recall.

### Can the customer undo their own stop request by texting again?

Writing again does not clear the entry by itself. Clearing one is a decision a person with permission takes and the audit trail records, precisely so that a block is not lifted by an ambiguous message.

## Related

- [STOP and opt-out](https://connectbyjbrh.com/docs/sms/stop/)
- [SMS suppression](https://connectbyjbrh.com/docs/sms/sms-suppression/)
- [An inbound SMS, end to end](https://connectbyjbrh.com/docs/workflows/sms-inbound/)
- [A do-not-contact reaching every channel](https://connectbyjbrh.com/docs/workflows/dnc-across-channels/)
- [A WhatsApp opt-out, end to end](https://connectbyjbrh.com/docs/workflows/whatsapp-optout/)
- [What Connect may do](https://connectbyjbrh.com/docs/autonomy/)

## What this page is based on

- `docs-source/sources/CHANNELS.md` §3 — STOP and suppression
- `docs-source/sources/GENERAL.md` §5 and §6 — autonomy, audit, tagged directives
- Connect capability registry (docs-source/facts.py) — `sms_stop`, `block_directive`
