PII Redaction at the Gateway
Strip phone numbers, government IDs, and emails from inbound messages before they reach the LLM or your audit logs — KVKK / GDPR aligned.
- Plugins
pii-redactor- Channels
telegramwhatsappweb- Uses
pre_gateway_dispatch
When customers send messages, they include things they shouldn't: phone numbers, national IDs, account passwords, full emails. Most of the time, your agent doesn't need that data to answer — and storing raw PII in conversation logs is a compliance problem waiting to happen.
The pii-redactor plugin runs at the gateway boundary: every inbound message gets pattern-matched against a redactable set before any session work, LLM call, or audit log entry happens. By the time the agent sees the message, the PII is already replaced with placeholders.
What it does
- Inspects every inbound message via
pre_gateway_dispatchhook - Pattern-matches Turkish mobile (05XX-XXX-XX-XX), TC kimlik (11-digit), email
- Replaces each match with
[REDACTED_PHONE]/[REDACTED_TC]/[REDACTED_EMAIL] - Returns
RewriteActionso the message is mutated in place — the LLM and audit log never see the raw data - Logs redaction events to
~/.flowly/pii-redactor/log.jsonlfor compliance review
What you'll need
- The bundled
pii-redactorplugin enabled (or build your own — see below)
Setup
1. Enable the plugin
flowly plugins enable pii-redactorflowly service restart
Verify:
flowly plugins list# pii-redactor | enabled | provides_hooks: pre_gateway_dispatch
2. Test redaction
Send to your bot:
"Telefonum 0532 123 45 67, TC kimliğim 12345678901, ulaşırsanız sevinirim."
The agent receives:
"Telefonum [REDACTED_PHONE], TC kimliğim [REDACTED_TC], ulaşırsanız sevinirim."
Check audit log to confirm raw values didn't land:
tail -1 ~/.flowly/pii-redactor/log.jsonl# {"ts": ..., "session": "telegram:...", "redacted": {"phone": 1, "tc": 1, "email": 0}}
Only the counts are logged — the raw values aren't.
3. Customise patterns (if needed)
For other locales / domains — US SSN, IBAN, credit card, internal
employee IDs — add patterns to the plugin's __init__.py:
_SSN_RE = re.compile(r"\b\d{3}-\d{2}-\d{4}\b")_IBAN_RE = re.compile(r"\bTR\d{2}\s?(\d{4}\s?){5}\d{2}\b")def _redact(text):text = _PHONE_RE.sub("[REDACTED_PHONE]", text)text = _SSN_RE.sub("[REDACTED_SSN]", text)text = _IBAN_RE.sub("[REDACTED_IBAN]", text)return text
Restart the gateway. New patterns apply to subsequent messages only — old conversations are not retroactively scrubbed.
4. Pair with audit retention
Configure the audit retention policy in ~/.flowly/config.json:
{"audit": {"enabled": true,"retention_days": 90,"max_size_mb": 500}}
Older entries auto-rotate. With redaction in place, even retained logs are PII-free.
Tips
- Test patterns against real messages. A regex that's correct on
paper may fail in practice — Turkish phone formats vary
(
+90 532 …,0532-…,5321234567). Run a sample of recent conversations through the redactor in dry-run mode first. - Don't redact what you need. If the agent legitimately needs the user's email to send a confirmation, don't redact email. Be specific about what's truly excess data.
- Layer it. Redaction at the gateway + payload field whitelisting in your tools (don't pass user-provided fields you don't need) + audit log redaction. Three lines of defence.
- KVKK / GDPR alignment is real. Even without enforcement, you reduce blast radius from a future breach. The cost of building this is one afternoon; the cost of not building it can be your business.
- Document what's redacted. Customers should know — a one-liner in your terms or onboarding: "Personal data in messages is automatically redacted before processing." This is also a trust-building feature.