Skip to main content
Once detection marks a span, Masker replaces it with a token. The token travels to your LLM in place of the real value. On the response leg, Masker swaps it back before the text reaches your caller. The LLM never sees real PHI; your caller never hears a placeholder. Every token Masker produces shares four properties:
  • Format-stable — the same shape regardless of input length, so the model is never surprised by a short or long token
  • Type-aware — the LLM can still tell a phone from a name from a date
  • Reversible — Masker can rehydrate the original on the response leg
  • Non-revealing — given only the token, you cannot recover the original value

Token format

All tokens follow this structure:
A masked phone number looks like:
The LLM sees this in the message thread, recognizes it as a phone-shaped argument, and generates a response that references it naturally. Masker rehydrates the real number when streaming the response back to your voice agent.

Two tokenization schemes

Masker offers two schemes. You choose one per agent.
Algorithm: HMAC-SHA256 of (kid_secret || normalized_input) → first 16 bytes → base32-encoded.Storage: A row is written to a SQLite vault at /data/vault.db on the Fly volume.Scheme prefix: MSKV1

Properties

Use vault-deterministic when you want same-value → same-token behavior across a session — for example, so the LLM can refer to “the patient” consistently across multiple turns.

Choosing a scheme

The healthcare-default policy ships with vault-deterministic tokenization. You can change it per agent in the portal or via the create-agent API.

Rehydration

On the response leg, Masker scans the LLM’s output for any token matching the pattern MSK*.*.*.*. For each match:
  • Vault deterministic: look up the original value in /data/vault.db, replace inline.
  • Reversible AEAD: decrypt with the kid key, replace inline.
If a token cannot be rehydrated — the key was rotated out, the vault row is missing, or the token is malformed — Masker emits a rehydration_failed event and replaces the token with [REDACTED:KIND]. The failure is recorded in the audit log.
A [REDACTED:KIND] in your TTS output means rehydration failed for that span. Check the audit log for rehydration_failed events to identify the cause — typically a key rotation that dropped a key while live tokens still referenced it.

Key management

Each kid is a logical key identifier mapped to actual key material in your environment:
You can have multiple active kids at once to support key rotation:
Masker uses the active key for new tokenization, and tries every registered key during rehydration. To rotate:
1

Add the new key

Set MASKER_KEY_K_HEALTHCARE to the new key material. Keep the old key registered as MASKER_KEY_K_HEALTHCARE_OLD.
2

Update the policy

Switch your agent’s policy to reference the new kid. New tokens will use the new key; existing live tokens still rehydrate via the old key.
3

Drop the old key

Once no live tokens still reference the old key — typically after the longest call session you run — remove MASKER_KEY_K_HEALTHCARE_OLD. Tokens minted with it will no longer rehydrate.
For production, store key material in your secret manager of choice: Fly Secrets, AWS Secrets Manager, GCP Secret Manager, or HashiCorp Vault. Masker does not ship its own key escrow.