Playbook 13 · Privacy

Mask PII before the model ever sees it

Goal: the model provider gets a masked copy, and your own systems keep the truth. Card numbers, emails, phones, and identifiers you define are redacted in every message bound for the LLM, while the session history, the audit chain, and the human handover ticket retain the real transcript, because your teammate resolving a case needs the actual account number the customer typed.

No external provider. Redaction is a built-in Zolva plugin driven by a pattern file. There are no third-party calls to verify; masking happens in-process, before the provider request is built.

The shape: the redactor wraps your model adapter. Only the outbound provider call sees the masked text; everything else on the bus, sessions, audit, handover, sees the original. Patterns are config, so compliance can widen coverage without a code change.

Prerequisites #

  • A running AgentApp.
  • The identifiers specific to your bank you want masked (a loan reference format, an internal customer id), as regular expressions.
  • Python ≥ 3.11 and pip install zolva.

Step 1 · Declare the patterns #

Enable the built-in patterns you need and add your own. Built-ins cover common PII; custom entries are named regexes for identifiers only you have.

policies/redaction.yaml
builtin: [card, email, phone]
custom:
  loan_ref: "LN-\\d{6}"
  cust_id:  "CUST-[A-Z0-9]{8}"

Available built-ins include card, email, phone, aadhaar, and ssn. An unknown built-in name fails validation, so a typo is caught at load, not in production.

Step 2 · Attach it to the app #

One argument wires the redactor in. From here, every message the agent sends to the provider is masked first.

app.py
from zolva import AgentApp

app = AgentApp.from_config("agents/", redaction="policies/redaction.yaml")

A customer who types "my card 4111 1111 1111 1111 was declined" sends my card [CARD] was declined to the model, but the session, the audit entry, and any human handover keep the real number. The agent still reasons and replies correctly, because the masking is consistent within the conversation.

Step 3 · Mask training exports too #

The same pattern file de-identifies data on its way out to fine-tuning. If you run the feedback-to-fix loop, export accepted failures with redaction applied so no raw identifier leaves your systems in a dataset.

terminal
zolva export-dataset failures.db dataset.jsonl \
  --redaction policies/redaction.yaml

What is and is not masked #

  • Masked: only the copy sent to the model provider, and, on request, the dataset export. That is the text that would otherwise leave your perimeter.
  • Not masked: the session history, the audit chain, and the human handover ticket, all keep the true transcript, because your own systems and staff need it to resolve the case and to answer an auditor.
  • Patterns are config: compliance can add a new identifier regex without touching code, and validation rejects an unknown built-in at load.
  • Layer it: redaction reduces what leaves your VPC; run the model itself in your VPC too with the self-hosted gateway playbook and even the masked copy never reaches a vendor.

← All playbooks