Skip to main content
Every LLM-backed endpoint redacts your text server-side before any model sees it, restores your real values in the answer, and attaches a receipt.

What is removed, and what is kept

Replaced with placeholders

Malaysian IC (old and new formats), MRN, passport, phone, names, emails, account numbers.

Deliberately preserved

Ages, relative dates like “day 3 post-op”, vitals, dosages — all clinical content.
This is not blanket scrubbing, and the distinction is the point: an answer built on redacted clinical detail would be worthless. The model receives placeholders for who the patient is, and the full clinical picture of what happened. The placeholder→value mapping lives in the request’s memory only and is never stored.

The receipt

Every LLM-backed response carries a redaction_receipt:
object
What was found, by type — counts only, never the values.
boolean
Whether every placeholder was substituted back.
integer
How many were not. If a model altered one of our placeholders, the receipt says so rather than silently handing you residue.
string
failed_closed on the 503 below — the request never left us.

Fail-closed

If the redactor fails, the request is refused with a 503 (redaction_failed_closed). It never reaches a model unredacted.A redactor outage therefore looks like downtime rather than like a silent leak. That is the intended trade.
There is no client-side flag that skips redaction for API keys. You cannot assert “this text is already de-identified” to bypass it.

Two v1 limits, both refusals rather than silent degradation

Placeholders split across chunk boundaries, and models rewrite them mid-stream, so a half-substituted answer is worse than a slower complete one.Send redact_only=true to stream — nothing is substituted back, so there is nothing to split.
A tool call can carry context straight back out, which needs its own exfiltration review. Refused with a 400 rather than dropped, so you never believe your tools were honoured when they were not.

Measured recall

On a held-out corpus the engine’s authors never saw: 99.5% name recall and 100% structured-identifier recall. Read those two numbers precisely. They are the current measurement. Our CI re-measures on every change to the redactor and enforces floors of ≥95% names and ≥99% structured identifiers — the floors are what a change cannot ship below, not what we claim today.