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.
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.
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.
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.
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.