Skip to Content
Polyant is open source under AGPL-3.0 — star us on GitHub.

GDPR opt-out

On this page

GDPR opt-out (an agent’s Governance group, ?tab=privacy) is the mechanism that lets an end user stop receiving messages, and lets an operator silence or re-enable a single contact.

It and the retention policy were briefly merged into one Data & privacy section, on the argument that a GDPR opt-out and a data TTL answer the same question. They were split back apart: one is a per-contact switch an operator flips daily, the other a destructive schedule nobody touches for months, and reading them as one form served neither.

Enforcement is deterministic. The agent is never asked to decide whether a contact is opted out - a gate at the top of the message handler and a check on every proactive send do it in code.

The contact list is read with agent.governance:read, and a contact’s status is changed with agent.governance:write. The configuration itself lives on the agent record and travels with it: reading it is agent:read, changing it agent:write.

Configuration

  • Enable - master switch. Off (the default) means no gate runs and no contact is ever suppressed.
  • Stop keywords - comma-separated. Default STOP. A subscribed contact sending exactly one of these (case-insensitive, whitespace-trimmed, whole message) is recorded as opted out.
  • Resume keywords - comma-separated. Default START. An opted-out contact sending one of these is re-subscribed.
  • Closing message - sent once on opt-out. Leave empty for a silent opt-out.
  • Resume message - sent once on resume. Leave empty for a silent resume.
  • Inject prompt hint - on by default. Adds an informational section to the system prompt so the agent can tell a user how to unsubscribe. The section explicitly instructs the agent not to process the opt-out itself.

The keyword match is exact, not substring: “STOP sending these” does not opt anyone out.

How the gate behaves

The gate runs before Room/task routing and before context preparation, so a stop keyword is always honoured first - even mid-burst.

Contact statusMessageOutcome
Subscribeda stop keywordrecorded as opted out, closing message sent (if set), turn ends
Subscribedanything elsenormal turn
Opted outa resume keywordre-subscribed, resume message sent (if set), turn ends
Opted outanything elsesilently dropped - no model call, no reply

A resume keyword wins over a repeated stop keyword: an opted-out contact can always get back in.

Both transitions are persisted to the conversation (the user’s keyword plus the confirmation) so the exchange is visible in Conversations. Persisting is best-effort - a write failure never prevents the opt-out from being honoured.

What opt-out does not cover

  • Synthetic channels. The agent, scheduled, and room channel types never participate - there is no real end-user contact behind them.
  • Automated task messages are exempt from the gate.
  • Closing and resume confirmations are always delivered, even though the contact is opted out at that moment. Every other proactive outbound send to an opted-out contact is suppressed.

An opt-out status lookup that errors is treated as “not suppressed”, so an infrastructure fault never silently blocks legitimate traffic.

Contacts

Opt-out is per (agent, channel type, contact id). A contact with no stored row is subscribed; there is nothing to create for the normal case.

The contacts table lists channel, contact, date, and source - how the status was set:

  • user - the contact sent a stop or resume keyword.
  • admin - an operator set it from this tab.
  • agent - a tool call set it, on agents where the opt-out tool is enabled. Setting is idempotent: a contact already opted out is left untouched, so an earlier user-initiated opt-out is not overwritten.

From the table an operator can re-enable a contact, or opt one out manually by entering its channel type and contact id.

See also

  • Retention - deleting conversation data after a period, the other half of the data-privacy story.
  • Governance - content policy gates.
  • Channels - where channel types and contact ids come from.
Last updated on