---
title: "How to handle STOP and HELP when an AI agent sends texts"
description: "Keep STOP and HELP away from the model: handle keywords first, send one confirmation, honor plain-language opt-outs, log consent, check before every send."
url: https://www.unitpost.com/blog/agents/ai-agent-sms-stop-help
section: Blog
updated: 2026-11-02
---
# How to handle STOP and HELP when an AI agent sends texts

Handle opt-out keywords before the model ever sees a reply: record STOP, send one confirmation and nothing after it, and drop the message from the agent's queue. Answer HELP with who you are, how to reach a person and how to opt out. Send plain-language requests to stop to a person or a fixed rule, log every consent change, treat START as a return to service texts only, and check opt-out status on every send.

## How to handle STOP and HELP when an AI agent sends texts

> Keep STOP and HELP away from the model: handle keywords first, send one confirmation, honor plain-language opt-outs, log consent, check before every send.

An agent that reads replies will eventually read "STOP". The worst thing it can do is answer: an apology, a retention offer, a question about why. Each of those is a message sent after an opt-out.

Opt-out handling has to sit in front of the model, in code that matches words exactly and doesn't negotiate.

### Why must STOP be handled before the model sees it?

The CTIA Messaging Principles (https://api.ctia.org/wp-content/uploads/2023/05/230523-CTIA-Messaging-Principles-and-Best-Practices-FINAL.pdf) (section 5.1.3) ask senders to acknowledge an opt-out with one final confirmation and send nothing after it. A model asked to reply helpfully doesn't know that the right reply to STOP is no reply. A prompt makes a behavior likely. An opt-out needs it to be certain.

On Unitpost numbers, keyword handling happens before your webhook fires. An incoming text is matched, as the whole message, against the opt-out keywords: STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, QUIT, REVOKE, OPT OUT, OPTOUT, OPT-OUT, REMOVE, TD and ARRET. Case, accents and punctuation around the word don't matter, so "Stop." and "(STOP)" both count. Unitpost records the opt-out and sends one confirmation from your registered STOP text. On a US toll-free number the carrier also catches STOP and sends its own confirmation, so for that word Unitpost records the opt-out and sends none.

Your `sms.received` webhook still gets the text, with `keyword: "OPT_OUT"` and `auto_replied: true`. That is the signal to drop it before it reaches the agent. This is the handler from Unitpost's SMS docs:

```bash
import { Unitpost, verifyWebhook } from "unitpost";

const unitpost = new Unitpost(process.env.UNITPOST_API_KEY);

// Your webhook endpoint, subscribed to sms.received. Pass the RAW body.
export async function onWebhook(rawBody: string, headers: Record<string, string>) {
  const event = verifyWebhook<{ type: string; data: SmsReceived }>({
    payload: rawBody,
    secret: process.env.UNITPOST_WEBHOOK_SECRET!, // whsec_…
    headers,
  });
  if (event.type !== "sms.received") return;
  const reply = event.data;
  if (reply.keyword === "OPT_OUT" || reply.auto_replied) return; // STOP, or already answered
  if (reply.looks_like_opt_out) return flagForReview(reply); // "please stop texting me": a person decides

  const { data: history } = await unitpost.sms.list({ participant: reply.from, limit: 20 });
  const answer = await yourAgent(history?.data ?? [], reply.body);

  // No `from`: the answer goes out from the number they texted.
  await unitpost.sms.send({ to: reply.from, body: answer });
}

type SmsReceived = {
  sms_id: string;
  from: string;
  to: string;
  body: string | null;
  keyword: "OPT_OUT" | "OPT_IN" | "HELP" | null;
  auto_replied: boolean;
  looks_like_opt_out: boolean;
  in_reply_to: string | null;
  received_at: string | null;
};
```

The early returns are the point. An opt-out, and a text that already got its compliance answer, never becomes a prompt.

### What should the opt-out confirmation say?

One message that confirms and ends. Unitpost's registration recipes write it as "Acme: You are unsubscribed and will receive no further messages." No offer, no survey, no "before you go".

The wording is the `stop_message` of the messaging program your registration was filed from, which is also where carriers read it. Because Unitpost sends it, the agent never writes it and can't be tempted to improve it.

### What does HELP return?

HELP (or INFO) gets your registered help text: who you are, how to reach a person, and how to stop. The recipe version reads:

```bash
Acme: For help, email support@acme.com. Message and data rates may apply. Reply STOP to opt out.
```

Unitpost sends it automatically, and the webhook arrives with `keyword: "HELP"` and `auto_replied: true`, so the agent shouldn't answer a second time. HELP isn't an opt-out: the person stays subscribed. A question in their own words, such as "who is this?", is an ordinary message. The agent can answer it, starting with your business name.

### What about "please stop texting me"?

Only an exact keyword records an opt-out on Unitpost. "Please stop texting me", "unsubscribe me" or "take me off this list" arrive with `keyword: null` and `looks_like_opt_out: true`. Unitpost doesn't guess, because a loose match would opt people out of texts they asked for.

That flag is yours to act on, and you should act on it. CTIA asks senders to read and act on opt-out requests made in normal language, not only the standard keyword. Unitpost's SMS Messaging Policy requires you to honor an opt-out however it reaches you (a reply in plain words, an email, a call, a support ticket) and to record it in Unitpost promptly, within ten days at most.

US federal rules point the same way. The FCC's revocation rule, 47 CFR 64.1200(a)(10) (https://www.ecfr.gov/current/title-47/chapter-I/subchapter-B/part-64/subpart-L/section-64.1200), names stop, quit, end, revoke, opt out, cancel and unsubscribe as replies that revoke consent and gives senders ten business days to honor a revocation. An FCC order published on October 26, 2026 (https://www.consumerfinancialserviceslawmonitor.com/2026/10/fcc-publishes-revised-tcpa-revocation-rules/) amends these rules from November 25, 2026: a sender may designate clearly disclosed opt-out methods, and a texting sender must still honor all seven words (https://www.insideglobaltech.com/2026/10/02/update-fcc-adopts-final-order-and-further-notice-on-tcpa-consent-revocation/). The practice doesn't change. Treat a clear request in plain words as an opt-out.

Don't give that call to the agent. When `looks_like_opt_out` is true the agent stays silent, and a person, or a narrow rule you have written and tested, decides. If it is an opt-out, record it with `POST /contacts/{id}/sms-consent` and `action: "opt_out"`. From then on the number is refused like any STOP.

### How do you keep a consent event log?

When a carrier or regulator asks whether someone agreed, "the agent remembered" isn't an answer. CTIA lists what to keep (section 5.1.2): when consent was given, the medium, what the person saw, the campaign, the IP address, the number, and who consented.

Unitpost keeps that as an append-only history per number. Each `POST /contacts/{id}/sms-consent` takes:

- `action`: `opt_in` or `opt_out`
- `source`: `web_form`, `hosted_form`, `keyword`, `qr`, `verbal`, `paper`, `api_import` or `api`
- `purpose`: `marketing` or `transactional`
- `occurred_at`, backdated to when it really happened (a future time is refused)
- `evidence_url` and `disclosure_version`

STOP and START replies land in the same history on their own. `GET /contacts/{id}/sms-consent` returns the current state, `marketing_eligible`, and the history, newest first. Let the agent read it. Keep consent writes in your own code, where a person or a tested rule decides.

### How does someone opt back in?

They text START or UNSTOP to your number. Unitpost records it, and the number can receive service texts again: reminders, receipts, codes.

START does not create marketing consent. Someone who texted START to get their appointment reminders back hasn't asked for promotions, so marketing needs a new express written consent with its own record. An agent should never read a friendly reply ("sure, keep me posted") as a re-opt-in. Only START, or a new opt-in recorded with its source, changes the state.

### Why check opt-out status on every send?

Lists go stale between the moment they are built and the moment they are used. An agent that pulled this morning's patients and texts them this afternoon is working from a list some of them may have left at lunch. Agents also carry state through a conversation: "this person is fine to text" was true an hour ago.

Unitpost checks the suppression list and the number's opt-out state on every send, transactional included. A STOP has no transactional bypass. A refused send comes back `403` with `message_suppressed` or `recipient_not_opted_in`, and `error.details[0].code` is `opted_out`. Nothing is sent and nothing is billed. A text scheduled earlier is checked again when it is due, ends `suppressed`, and fires `sms.suppressed`.

Teach the agent what that refusal means: stop, tell the user why, don't retry, and don't look for another route to the person, such as another sender or another workspace. Working around an opt-out breaks Unitpost's Acceptable Use Policy. An SMS opt-out leaves the person's email subscription as it was, and it isn't a reason to deliver the same message by email instead.

> **Not legal advice:** This describes industry guidance and how Unitpost behaves. Consent and revocation rules are changing; confirm the ones that apply to you with counsel.

## FAQ

### Which words count as an SMS opt-out?

On Unitpost numbers: STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, QUIT, REVOKE, OPT OUT, OPTOUT, OPT-OUT, REMOVE, TD and ARRET, matched as the whole message whatever the case, accents or surrounding punctuation. A sentence that asks to stop is flagged with looks_like_opt_out for you to decide, not recorded automatically.

### Does STOP to one of my numbers opt the person out of all my texts?

Yes. On Unitpost, STOP opts the number out of your workspace's whole SMS channel, service messages included, whichever of your numbers it was sent to. It doesn't change the person's email subscription.

### Can my agent send anything after someone texts STOP?

Only the one confirmation, and the agent doesn't write it: Unitpost sends your registered STOP text, or the carrier sends its own on a US toll-free number. After that, every send to the number is refused with opted_out until the person opts back in, for example by texting START.

## Related

- [How to let an AI agent answer text messages](https://www.unitpost.com/blog/agents/ai-agent-two-way-sms): Let an AI agent reply to texts safely: the sms.received webhook, messages it must not answer, opt-out words it shouldn't guess at, and when to hand off.
- [Does AI-written marketing email still need consent?](https://www.unitpost.com/blog/agents/ai-marketing-email-consent): AI-written marketing email still needs consent. The rules in the US, EU, UK and Canada, Gmail and Yahoo bulk sender rules, and where AI agents go wrong.
- [Which API key permissions does an AI agent need?](https://www.unitpost.com/blog/agents/api-key-permissions-for-ai-agents): The smallest API key for each AI agent job, from sending receipts to running campaigns, what no key can ever do, and the 403 a missing permission returns.
