All posts
Consent as Code: Opt-Outs an Agent Can't Forget
ComplianceBy Dial Engineering·6 min read·September 30, 2026·0

Consent as Code: Opt-Outs an Agent Can't Forget

A customer replies STOP to a text. Three days later, the same company's email agent writes to them again. Treating consent as a protocol primitive, checked at dispatch and shared across channels, closes the gap. A builder's view, not legal advice.


Imagine a customer named Theo. He gets a promotional text from a retailer, decides he has had enough, and replies STOP. The system answers, "You have been unsubscribed." Theo puts down his phone, satisfied.

Three days later, an email arrives. Then a WhatsApp message. Then a call from an automated voice, inviting him to a sale.

Each of these was sent by a different agent, running on a different system, none of which had heard that Theo said STOP.

This is hypothetical, but the pattern is one of the most natural failures in multi-channel agent systems. The opt-out worked perfectly. It just worked in one room of a house with five rooms.

A quick note before we go on: this is an engineering perspective, not legal advice. Consent rules differ by country, channel, and type of message, and they change. Ask a qualified lawyer what applies to you.


Why opt-outs get forgotten

Humans remember. A shop assistant who is told "please stop calling me" does not need a database to recall it. Software needs somewhere to write it down, and that somewhere has to be readable by every part of the system that might contact Theo.

Agents make the problem worse in three ways.

They multiply. A company may run many agents: sales, support, reminders, re-engagement. Each one is a place a stale list can hide.

They are fast. A human who forgets an opt-out sends one wrong message. An agent that forgets sends a few hundred in the time it takes to notice.

They span channels. STOP arrives by text. The unsubscribe link lives in email. A WhatsApp user might just block the number. Each channel has its own opt-out mechanism, and none of them was designed to tell the others.

The result is the five-rooms problem. One room has the note. The other four have no idea.


The core idea in the ACES whitepaper is that consent should be a protocol primitive: a first-class piece of data that travels with every message and is checked by infrastructure, not remembered by whichever agent happens to be sending.

Two sentences from the paper capture it:

  • The consent field on every message is not a self-reported claim. It is resolved against the operator's registered consent store at dispatch time.
  • If consent cannot be verified, the message is blocked before it reaches the carrier.
  • Read that twice. The agent does not get to decide. The agent could be confused, poorly prompted, or manipulated by a hostile text (see our post on prompt injection), and it still cannot send to someone who has opted out, because the check does not live inside the agent.


    A useful consent record is more than a yes or no. Think of it as a small, auditable history per contact:

    // illustrative pseudocode
    consent_record:
      contact:     "+1415..."
      events: [
        { type: "granted", channel: "web_form", at: "2026-03-02T10:14Z",
          scope: "appointment reminders", evidence: "form submission id" },
        { type: "revoked", channel: "sms_stop", at: "2026-09-12T08:31Z",
          scope: "all" }
      ]
      current_status: "revoked"

    A few properties matter:

  • Scope. Consent to appointment reminders is not consent to marketing. Record what was agreed to.
  • Source and time. When and how it was given, so you can answer "how do you know?"
  • Evidence. A pointer to the form, call recording, or message that established it.
  • History, not overwrite. Keep the revocation as an event instead of deleting the grant. The trail is the point.
  • Current status. Derived from the history, and what the dispatch check reads.
  • The whitepaper's message format includes policy fields such as a consent verified flag and a consent timestamp, so that every message carries a record of its own permission.


    STOP handling across channels

    Each channel has its own way of saying no, and a good system understands them all:

    ChannelHow people opt outWhat the system must do
    SMSReplying STOP or similar keywordsIntercept the keyword, confirm once, record the revocation
    EmailUnsubscribe link or replyHonor promptly, record, suppress
    WhatsAppBlocking the number, or a message asking to stopTreat as a revocation signal
    VoiceSaying "take me off your list"Detect intent, record it, end politely

    The detail that is easy to miss is the voice row. Opt-outs spoken to an agent are still opt-outs. Your agent has to recognize "please don't call me again" as a revocation and not as small talk.


    Revocation has to propagate

    Here is the design rule that would have saved Theo: one opt-out, every channel.

    The whitepaper says it directly in its email chapter: an unsubscribe received on any channel (SMS STOP, email unsubscribe, WhatsApp block) propagates to all channels automatically, and one opt-out stops all channels. Its regulatory appendix describes suppression lists propagated across channels.

    Whether to treat an opt-out as universal or scoped to one kind of message is a policy decision, and it is one for you and your counsel. But the plumbing has to make both possible. A revocation recorded in one place has to be visible everywhere that sends, and the default should lean toward the cautious reading.

    The mechanical version:

    1. A STOP arrives on SMS.

    2. The infrastructure records a revocation event against the contact.

    3. Every channel's next dispatch check reads the same record.

    4. The email agent, the voice agent, and the WhatsApp agent are all blocked, without having been told.

    No agent needed to remember anything. The wall is in the pipeline.


    Failure modes to design against

    Even with shared infrastructure, consent systems fail in ordinary ways. Some to test for:

  • Slow propagation. If a revocation takes a day to reach other channels, an agent can send in the gap. Aim for effectively immediate.
  • Identity mismatch. Theo texts from a phone and emails from an address. If the system cannot tell they are the same person, revocation on one will not cover the other. Identity resolution is part of consent.
  • Imported lists. A bulk upload from an old CRM can reintroduce people who opted out. Imports should be checked against the suppression record, not trusted.
  • Re-opt-in confusion. If someone later says START or fills in a form, the grant should be a new event with its own evidence, not a silent reset.
  • Wrong-number replies. Phone numbers get recycled. "Wrong number" should suppress that number too, and quickly.

  • Why put this in infrastructure at all

    You could build all of this in your application. Many teams do, once, and then maintain it forever, across every new channel and every new agent.

    The ACES argument is that compliance should move from the legal team (reactive, after the fact, expensive) to the infrastructure layer (proactive, automatic, cheap at scale). Checking consent at dispatch means the safest behavior is the default behavior, and the agent author does not need to be a regulatory expert to ship something responsible.

    That does not make you compliant by itself. It makes compliance something you can inspect: a record, a rule, and a log, in place of a hope.


    The takeaway

    Theo said STOP once. A good system lets that be enough.

    Treat consent as data that travels with the message. Check it at dispatch, outside the agent. Record grants and revocations as history. And make an opt-out on any channel apply everywhere it should.

    An agent that cannot forget a "no" is not a limitation. It is the reason people can trust it with a "yes." This is the kind of problem Dial is built to handle at the infrastructure layer, so your agents can be fast without being forgetful.

    Did you enjoy this post?

    0 claps