TCPA Compliance for AI SMS Bots: A Builder's Consent Guide
How I build AI texting bots that cannot message anyone without consent, covering opt-in records, opt-out handling, quiet hours, and A2P registration.
Updated 2026-08-18

I am not a lawyer and this is not legal advice. I build and operate SMS bots for small businesses, and what follows is how I engineer them so that the compliance question mostly answers itself. Run your actual policy past a lawyer who does telecom work. What I can tell you is where the software goes wrong, because I have had to build the guardrails.
The single most useful thing I ever did on a texting project was for a sports-facility company. Their CRM had thousands of contacts, and they wanted an AI assistant that could text leads and customers. I built the assistant with a hard consent gate: the send function physically refuses to deliver a message to any number that does not have a stored opt-in record. Not a warning. Not a flag on a dashboard. A refusal, at the lowest layer, with no override path in the UI and no override path in the prompt. Staff could not bypass it, the model could not talk its way around it, and a bug in a higher layer could not leak a message through.
That design decision has saved that project more than once. It is also the thing I would tell anyone building an AI texting feature to do first, before the personality, before the knowledge base, before anything.
What the TCPA actually cares about, in builder terms
The Telephone Consumer Protection Act is the US federal law behind most SMS marketing rules. Layered on top are FCC rules, carrier requirements enforced through A2P 10DLC registration, and the CTIA messaging principles. As a builder you rarely interact with the statute directly. You interact with three practical requirements that fall out of it.
Consent before you send. You need the recipient's prior express consent to send informational or transactional texts, and prior express written consent for marketing texts. Written here means a recorded affirmative action, like a checked box or a submitted form, not a verbal "sure" on a phone call. Consent must be specific about who is texting and roughly what for.
Honor opt-outs immediately. STOP, UNSUBSCRIBE, CANCEL, END, QUIT and similar keywords must stop messages, and the stop must be honored quickly and permanently until the person opts back in.
Identify yourself and stay in the lane. The business name should appear, at minimum in the first message of a conversation. Consent gathered for appointment reminders does not automatically cover promotional blasts.
An AI layer does not change any of this. It raises the stakes, because a language model will happily generate a message to any number you hand it. The model has no idea whether that number consented. Consent is not a prompt problem. It is a plumbing problem.
The hard consent gate, concretely
Here is the shape I use. It is not complicated, and that is the point.
The bot's outbound send is a single function. Every path that wants to text a human, whether it is the AI, a workflow, a staff member clicking a button, or a scheduled job, goes through that one function. Inside it, before any provider API call:
- Normalize the destination number to E.164.
- Look up a consent record for that number.
- Check the record's status is
opted_in, notpending, notrevoked, notunknown. - Check the message category is covered by the scope on that record.
- Check the recipient's local time against quiet hours.
- Only then hand off to the carrier API, and write a log row with the consent record ID that authorized this specific send.
If any check fails, the function throws. It does not return a soft failure that a caller might ignore. And critically, there is no force: true parameter. I have watched well-meaning override flags get used routinely within a month of being added, and once staff are used to overriding, the gate is decorative.
The consent record itself is boring and that is good. Phone number, timestamp, source (web form, in-person kiosk, checkout, reply to a keyword), the exact wording of the disclosure that was shown, scope, IP address or staff user who captured it, and current status with a revocation timestamp if applicable. Store the disclosure wording as a snapshot, not a foreign key to a page that gets edited later. When someone complains eighteen months from now, you want to show what they actually saw, not what your form says today.
Where AI specifically makes things riskier
The model will invent an opt-out confirmation. If a user texts "stop texting me" in plain language rather than the keyword STOP, a naive setup lets the model reply "no problem, I've removed you" while the underlying suppression list is untouched. That is worse than doing nothing, because now the person believes they opted out. Handle opt-out intent in code, not in the prompt. Match the standard keywords deterministically, and additionally run a narrow classifier or intent check for natural-language opt-outs that writes to the same suppression list before the model composes anything.
This is the same failure mode as a receptionist agent I once fixed that told callers it had blocked their number. It had no such ability. It sounded completely confident. The fix there was an explicit "abilities you do NOT have" list in the system prompt, which is worth doing here too, but a prompt is a mitigation, not a control. See stopping chatbot hallucinations for more on that distinction.
Consent scope drifts as the bot gets better. You launch with appointment confirmations. Six weeks later someone asks the bot to mention a promotion when it confirms. That message is now marketing, sent under transactional consent. Encode the category on the send call and validate it against the record scope, so the change fails loudly instead of quietly.
Test messages go to real people. Seed data with plausible phone numbers is a genuine hazard. I use my own cell for every test, always, and I gate any non-production environment to an allowlist of numbers. Testing your own phone before rollout is a rule I apply to every voice and SMS project anyway, and it is covered more broadly in testing voice agents.
Rate and burst behavior. An agentic loop that retries can double-send. Idempotency keys on outbound sends are cheap insurance, and they also stop the classic "the customer got the same reminder four times" support ticket.
A2P 10DLC and the carrier layer
Separate from the law, US carriers require application-to-person traffic on standard 10-digit numbers to be registered. You register a brand (the business, with its EIN) and a campaign (the use case, with sample messages and a description of how consent is collected). Carriers throttle or block unregistered traffic, and unregistered sending is a slow, confusing failure where messages appear to send and never arrive.
A few practical notes from doing this repeatedly on Twilio and Telnyx numbers. The sample messages you submit should match what the bot actually sends, including the opt-out language. The consent description should point at a real, reachable page describing your messaging program. Toll-free numbers have their own verification path that is often faster for a single-location business. Throughput is tied to your trust score, so a brand-new registration will not blast thousands of messages on day one, which matters if you are planning a campaign. And if you are running several small clients through one messaging account, keep the campaigns separate per client, because one client's sloppiness should not be able to poison another's deliverability.
Missed-call text-back is not an exemption
The flow I sell most often to contractors is missed-call text-back: a customer calls, nobody picks up, they get an instant text. People assume this is automatically fine because the customer initiated contact. The common reading is that an inbound call is a reasonable basis for a responsive informational text, and that first reply should identify the business and include opt-out instructions. Whether it covers the follow-up you send two days later is a different question, and that is exactly where I would want a lawyer's read for your business.
My engineering answer is to treat the inbound call as the consent event, record it as such with the call timestamp, scope it narrowly to conversational replies about that inquiry, and require a separate opt-in before anything that looks like marketing. The record then tells the story on its own.
Quiet hours, frequency, and the boring stuff
Federal quiet hours are commonly implemented as 8am to 9pm in the recipient's local time, and some states are stricter. Derive local time from the number's area code as a fallback but prefer a stored timezone if you have one, because area codes lie constantly now that people keep numbers when they move. Queue anything that would land outside the window rather than dropping it.
Frequency caps belong in the same layer as the consent gate. A cap of one automated outbound per contact per day, with a manual staff message exempt but still logged, has been enough on every project I have run. If a bot needs to exceed that, something upstream is broken.
Also: keep the logs. Every send, every consent capture, every revocation, with timestamps you can defend. The cost of storage is nothing. The cost of not being able to prove consent is the entire point of this page.
FAQ
Does the customer texting me first count as consent?
An inbound message from a person is generally treated as consent for a conversational reply, and it is the cleanest basis you can have for a two-way bot. It does not extend to marketing, and it should still be recorded as a consent event with its own timestamp. Ask your lawyer where the boundary sits for your specific messages.
Can I let the AI decide when a contact has opted out?
No. Keyword and intent detection should feed a deterministic suppression list that the send function checks, with the model never having authority to grant or revoke anything. Use the model to detect natural-language opt-out intent, then write that result to the list in code. The model composing a reply is fine; the model deciding whether a send is allowed is not.
Do I need A2P registration for a bot that only replies?
Yes, in the US on a standard 10-digit long code, replies are still application-to-person traffic and need a registered brand and campaign. Toll-free verification is an alternative path that some businesses find quicker. Without registration, expect silent filtering rather than clean errors.
What is the fastest way to sanity-check an existing SMS bot?
Try to send a message to a number with no consent record and see what happens. If it goes out, or if there is a button or a flag anywhere that lets it go out, you do not have a consent gate, you have a suggestion. Then text the bot "please stop messaging me" in plain English and verify the suppression list actually changed.
Is a chat widget simpler than SMS for compliance?
Considerably, since a website chat session does not carry the same messaging-law obligations as texting someone's phone. That tradeoff is worth thinking through before you commit, and I compare the two in SMS bot vs chat widget. Many businesses end up running both, with the widget capturing the opt-in that later authorizes texts.