Data Erasure Policy
The data-erasure policy category enforces pending erasure requests as required by GDPR Art-17 ("Right to Erasure") and CCPA §1798.105 (Right to Delete). When an end-user has filed an erasure request:
- Agents must NOT continue to process that subject's data
- New memory writes referencing the subject must be blocked
- The erasure must complete within the regulatory SLA (default 30 days)
This handler is the bridge between data-access (which enforces source allowlists but knows nothing about pending requests) and memory (which writes/reads but doesn't track deadlines).
Rules
| Rule | Type | Default | Description |
|---|---|---|---|
max_pending_days | integer | 30 | Hard SLA -- erasure must complete within N days of request (GDPR default 30) |
block_processing_for_subjects | boolean | true | Block any agent run scoped to a subject with a pending request |
block_writes_for_subjects | boolean | true | Block new memory writes referencing a subject with a pending request |
warn_threshold_days | integer | 25 | Warn when a request has been pending more than N days (approaching SLA) |
action_on_violation | string | "block" | Action on violation: "block" or "warn" |
How It Works
The data-erasure handler runs at before_workflow, mid_execution, and after_workflow. It performs four checks in order:
- SLA check -- any pending request past
max_pending_daysviolates the policy regardless of who the current run is for - Run-scoped check -- if this run's subject(s) overlap with pending requests, refuse to process
- Write-scoped check -- block memory writes whose string repr contains a pending-request subject id
- Warn check -- warn on requests approaching SLA so the tenant can prioritize
Context Attributes Read
| Attribute | Phase | Purpose |
|---|---|---|
context.metadata["erasure_requests"] | all | List of {sub_user_id, requested_at} or {user_id, requested_at} (tenant-populated) |
context._sub_user_identity / context.sub_user_identity | all | Resolve the run's subject (preferred over user_id) |
context.user_id | all | Fallback subject identifier |
context.memory_writes | all | Inspect each write for subject references |
requested_at accepts ISO strings or float epoch seconds.
Example Policy
{
"max_pending_days": 30,
"block_processing_for_subjects": true,
"block_writes_for_subjects": true,
"warn_threshold_days": 25,
"action_on_violation": "block"
}
SDK Integration
import waxell_observe as waxell
waxell.init()
@waxell.observe(agent_name="support-agent", enforce_policy=True)
async def handle_ticket(ticket: dict) -> dict:
return await respond(ticket)
Tenants populate erasure requests from their PrivacyAdmin service:
ctx.metadata["erasure_requests"] = [
{"sub_user_id": "user_123", "requested_at": "2026-05-01T10:00:00Z"},
{"sub_user_id": "user_456", "requested_at": "2026-05-20T14:30:00Z"},
]
Observability
| Field | Example |
|---|---|
| Category | data-erasure |
| Action | block |
| Reason | "Subject(s) ['user_123'] have pending erasure requests; further processing of their data is prohibited under GDPR Art-17." |
| Metadata | {"signal": "erasure_subject_processed", "subject_ids": ["user_123"], "gdpr": "Art-17"} |
Possible signal values: erasure_sla_overdue, erasure_subject_processed, erasure_subject_write, erasure_sla_approaching.
Common Gotchas
-
Write detection is substring-based. The handler does
str(write).lower()and checks for any pending-subject id as a substring. If your subject ids are short or numeric ("42"), you will get false positives on writes that happen to contain"42"anywhere. Use long, unique subject ids (UUIDs, prefixed slugs). -
erasure_requestsis tenant-populated. This handler does NOT query your privacy admin database. You must populatecontext.metadata["erasure_requests"]from your PrivacyAdmin service (typically via a middleware that injects it on every run). -
SLA violations block ALL runs, not just the affected subject's. If any pending request is past
max_pending_days, the handler blocks the current run regardless of who it is for -- this is intentional pressure on the tenant to complete erasure. -
Sub-user identity is preferred over
user_id. The handler reads_sub_user_identityfirst, falls back touser_id. If you have both, make sure they identify the same person -- or only set the one that matches yourerasure_requestsschema. -
Memory writes need to be on
context.memory_writes. Memory writes that bypass the context (direct DB inserts, raw cache writes) will not be detected. Wire memory operations through the runtime to get coverage. -
warn_threshold_days >= max_pending_daysis silently useless. SLA-overdue triggers first; the warn branch only fires for requests betweenwarn_threshold_daysandmax_pending_days.
Next Steps
- Privacy Policy -- PII detection (often the precursor to an erasure request)
- Data Access Policy -- Source allowlists; complements erasure enforcement
- Memory Policy -- Bounds on what can be persisted
- Compliance Policy -- Meta-validator for GDPR/CCPA
- Policy Categories -- All categories