Personal data reaches an LLM provider in three ways: a user pastes it into a prompt, your own code puts it in a system message or a tool result, or an agent fetches it from a database and sends it back as an argument. Stopping it takes three things: a place in the request path where every call passes through, detection that validates rather than pattern-matches, and a rewrite of the request itself before it is forwarded, so the provider receives a placeholder and your audit trail records the match without the value.
This guide is the practical version of that sentence. It covers where detection has to sit, which identifiers need a checksum rather than a regex, what each action (redact, block, flag) is for, how the main categories of tool differ, and what to write to the log so an auditor can follow it.
What tools sit between an application and an LLM to remove PII from requests?
Four kinds, and they are not interchangeable. The difference that matters is where the value is removed.
| Kind | Where it runs | What it redacts | Fits when |
|---|---|---|---|
| A proxy or gateway | Between your app and the provider, on the request path | The request itself, before it is forwarded | You need the provider never to receive the value |
| An observability SDK | Inside your app, around the provider call | The copy it stores for you; the provider still receives the original | You want logs and cost tracking, and PII in logs is the concern |
| A detection library (for example Microsoft Presidio) | Inside your app, wherever you call it | Whatever you pass it; you write the plumbing | You want full control and can own the integration and its tests |
| Provider-side controls | At the provider | Nothing in flight; data-handling terms, retention and training opt-outs | As a contract layer underneath one of the above, not instead of it |
A proxy is the only one of the four that changes what the provider sees, which is why it is the right answer to the question in the heading. The cost is that it is in the request path, so it has to be fast and it has to fail safely — more on that below.
How do I redact PII before it reaches an LLM?
Step by step, for a proxy-based setup:
- Route every call through one place. Point your OpenAI or Anthropic client at the proxy's base URL and add the proxy's key as a header. If a request can skip the proxy, the guarantee is gone; make the direct provider URL unreachable from production code.
- Scan the flat text of the request. Messages, the system prompt, tool-call arguments and tool results all carry text. Scan each string, not just the last user message — agents leak through tool arguments more often than through prompts.
- Validate every match. A regex finds candidates; a validator confirms them. A 16-digit number is a card only if it passes Luhn; a Swedish personnummer, a Dutch BSN or a UK NINO each has its own check. Without validation, invoice numbers and order IDs get redacted and the model's answer degrades.
-
Rewrite the request, not just the log. Replace each confirmed match in place with a typed placeholder such as
[REDACTED:pii], re-encode the message structure exactly as it came in, and forward that. The model sees that something was there and what kind; it never sees the value. - Fail closed. If a match cannot be masked with certainty — a value that only appears after JSON decoding, a structure the rewriter does not understand — refuse the request rather than forwarding it unchanged. A redaction tool that silently falls through is worse than none, because it changes what people believe about their logs.
- Record the match, never the value. The audit record carries the rule that fired, the type of identifier, the decision, and a reference to the request. It does not carry the number.
For an SDK-based setup, steps 2 to 4 apply to the copy you store, and you should say so in your own documentation: with an SDK the provider still receives the original text. That is fine for a log-hygiene requirement and not fine for a data-minimisation one.
Which identifiers should you detect?
Start with the global formats — email addresses, phone numbers, card numbers, IBANs, IP addresses — and then add the national identifiers for every country your users are in. That second list is where regex-only tools fall down, because national IDs look like ordinary numbers until you check them:
- Nordic: Swedish personnummer, Danish CPR, Finnish henkilötunnus, Norwegian fødselsnummer, Icelandic kennitala — each has a check digit or date structure.
- EU: German Steuer-ID, Dutch BSN (11-proef), Spanish DNI and NIE, French NIR, Italian codice fiscale, Belgian RRN, Polish PESEL, Irish PPSN, Estonian isikukood, Portuguese NIF, Austrian SVNR, and EU VAT numbers.
- UK and Switzerland: NINO, NHS number, AHV.
- US: SSN and NANP phone numbers, both with structural rules that reject most random digit strings.
Two consequences. First, false positives matter as much as misses: a tool that redacts every nine-digit number will be switched off within a week. Validation is what keeps it on. Second, which identifiers you enable is a per-application decision — a German HR tool and a US support bot need different lists — so the tool should let you choose by region rather than ship one global default.
Redact, block or flag: which action when?
- Redact when the request is legitimate and the value is incidental — a support ticket that happens to contain a phone number. The request proceeds; the provider gets the placeholder.
- Block when the value should never be in the request at all — a medical record number in a consumer chatbot, an API key in a code assistant. The request is refused with a clear error your application can show.
- Flag (allow and record) when you are measuring before enforcing. It is the right first week for a new application and the wrong permanent state; an auditor reading "flagged, allowed" a thousand times will ask why.
Set the action per rule and per environment. Flag in staging, redact in production, block for secrets everywhere is a common and defensible configuration.
How do LLM observability platforms handle privacy, PII redaction and data retention?
Most observability products are SDKs by design: they see the call from inside your application, send a copy to their own store, and give you dashboards. For privacy that means three settings to check, in this order:
- Does redaction happen before the copy leaves your process? If the SDK ships raw text and redacts server-side, the value has already crossed a boundary.
- What is the retention, and can you set it per application? Thirty days of prompts is a different risk from a year of them.
- Is the stored payload encrypted at rest with a key you can rotate, and is the metadata around it (model, token counts, decision) the only thing left in plaintext?
None of those settings changes what the provider received. If your requirement is "the provider must not see the value", an observability SDK is not the control; a proxy is, and you can run both.
How do you stop users from sending PII to an LLM?
You don't — not reliably, and not without making the product worse. People paste what they have. The realistic goal is that it doesn't matter when they do: detection on the request path, redaction before forwarding, and a record that shows it happened. User-facing hints ("don't include personal data") reduce volume and are worth having; they are not a control an auditor will accept.
What goes in the audit record?
For each request where a rule matched:
- the rule and the identifier type (for example PII · Swedish personnummer)
- the decision (redacted, blocked, flagged)
- the application, environment, model and provider
- a request identifier and a timestamp
- tool-call names and the hash of their arguments, if the request carried any
- not the matched value, and not the raw prompt unless your retention policy explicitly keeps encrypted payloads
That record is the evidence half of the control. Detection without a durable, queryable record is a feature; detection with one is something you can hand to an auditor. The complete guide to AI audit logging covers the fields in depth.
GDPR and HIPAA: what the regulations actually ask for
GDPR asks for data minimisation and a lawful basis for every transfer. Redacting before the provider receives the data is minimisation in the most literal sense, and the audit record is how you demonstrate it. If the provider is outside the EU, redaction also shrinks what the transfer mechanism has to cover. The EU AI Act's logging requirements add record-keeping duties for high-risk systems on top of this.
HIPAA asks for a business associate agreement with anyone who receives protected health information, and for the minimum necessary standard. A proxy that strips identifiers before the provider sees them reduces what the BAA has to cover and is a direct implementation of "minimum necessary". It does not remove the need for the agreement where PHI still flows.
SOC 2 and GDPR for LLM applications goes through the controls an auditor maps this to.
How SignalVault does it
SignalVault is a proxy. Your OpenAI or Anthropic client points at its base URL and sends one extra header; the Python and Node SDKs exist for teams that cannot change the base URL, and they redact what SignalVault stores rather than the forwarded request.
Through the proxy, every request is scanned before it is forwarded. The catalog covers 29 identifiers across 19 countries — personal identity numbers from the 5 Nordic countries and national ID or tax numbers from 14 EU states among them — each validated by check digit where the identifier has one, and you choose per application which regions are on. A match is redacted, blocked or flagged per rule: a redacted request is rewritten in place, so the provider receives [REDACTED:pii] or [REDACTED:secret] where the value was, and a request whose match cannot be masked with certainty is refused rather than forwarded. The audit record keeps the rule, the type and the decision, never the value. How detection works lists every identifier; the proxy and rules pages cover setup.
If you want to see what your current logs would have caught, start with the free trial and send a few real requests from your staging environment.
Frequently asked questions
How do you detect and redact PII from LLM inputs before they reach the model?
Put a proxy on the request path, scan every string in the request (messages, system prompt, tool arguments), validate matches with checksums, rewrite the request in place with typed placeholders, and refuse the request if a match cannot be masked. Log the match type and decision, not the value.
Can an AI gateway redact PII in tool calls and streaming responses, not just prompts?
Tool-call arguments and tool results are text and can be scanned and rewritten like any message. Streaming responses are harder: a value can be split across chunks, so a gateway either buffers until the value is complete or scans the response after the fact and records it. Ask any tool you evaluate which of those it does.
What is the difference between PII detection and PII redaction?
Detection finds a value and records that it was there. Redaction replaces it before it goes further. A tool can detect without redacting (flag), and most observability SDKs redact only their own stored copy. Only a request-path proxy redacts what the provider receives.
Which PII detection approach has the fewest false positives?
Validated patterns: a regex to find candidates, a checksum or structural rule to confirm them. Named-entity models catch names and addresses that patterns miss, at the cost of latency and more false positives on ambiguous words; most teams run patterns on every request and reserve NER for specific flows.
Does redacting PII before the LLM break the model's answer?
Rarely, if placeholders are typed. "Reply to the customer at [REDACTED:pii]" still reads as an email address to the model. Partial masking ("j*@example.com") is worse on both counts: it leaks and it confuses.
How long should PII-related audit records be kept?
As long as your retention policy says, and no longer. The record of a redaction (rule, type, decision, timestamp) carries no personal data and can be kept for the audit window; encrypted payloads, if you keep them at all, should follow a shorter, per-application retention.
What should a developer do first, today?
Point staging at a proxy with detection on, set every rule to flag, and read the records for a week. You will learn which identifiers your users actually send before you decide what to redact and what to block.