Privacy gateway for AI
AI Guard
A gateway that replaces personal data before it reaches an LLM and restores it in the answer.
In development, not in production yet
1Your prompt
Write an email to Anna Schmidt (anna.schmidt@
example.com): she has to pay invoice RE-2026-0417 by 15 Dec 2026. 2What the model sees
Write an email to Mira Vogt (m.vogt@
mail-example.com): she has to pay invoice RE-2026-8852 by 3 Dec 2026. 3What the model answers
To: m.vogt@
mail-example.com Dear Ms Vogt, please pay invoice RE-2026-8852 by 3 Dec 2026. Best regards 4What you get
To: anna.schmidt@
example.com Dear Ms Schmidt, please pay invoice RE-2026-0417 by 15 Dec 2026. Best regards
Real dataReplacement data
An example with made-up data.
Core skills
- LLMs and agents
- Security and privacy
- Reliability
- Real-time systems
- Backend and APIs
- Testing and verification
Tech stack
- TypeScript
- NestJS
- OpenAI SDK
- Docker
- GLiNER
- onnxruntime
- Custom grammars
- LLM
- Vitest
- Leak corpus
- Benchmarks
The hardest part
The fake name must never slip through
Where a stream splits is random. Code must never rely on it.
The whole story
What it looked like
The model writes its answer piece by piece. The replacement name “Mira Vogt” can arrive as “Mi”, “ra Vo” and “gt”. Find and replace never catches it, and you read a stranger's name in your email.
What was really going on
The pieces split mid-word, purely at random. Pass everything straight through and you see the fake name. Collect it all until the answer is finished and you stare at an empty screen for a long time.
The fix
Only the characters that could still be the start of a replacement name are held back. Everything else flows straight through, so the answer still types itself out as usual.
- 512
- tests in Guard
- ~99%
- detection in free text per its own spec, not a guarantee
- 4
- detection layers
In plain words
Many companies want to use AI but can't send it customer data. Guard sits in between: to the model, “Max Müller” becomes an invented name, and the answer you read says “Max Müller” again.
When text goes to an LLM, personal data often goes with it, from phone transcripts or customer emails, for example. Guard solves that in one place: a gateway with an OpenAI-compatible API, in front of any LLM app.
How it works
Step 1 of 5
Request
The app sends its request to Guard instead of the LLM provider. Only the URL changes on the client.
What was built
- An OpenAI-compatible API that can sit in front of existing LLM apps
- Layered detection: deterministic grammars, an LLM, local NER and redact by default
- Realistic surrogates, so the model can still work with the text properly
- Restoration inside a live stream too, without ever splitting a token
- Hard-case benchmarks, a long generated document with ground truth and a leak-test corpus as a gate
How those skills were used
- LLMs and agents
- Multi-stage PII detection, local inference with GLiNER on ONNX, and evaluation with custom benchmarks
- Security and privacy
- Privacy as architecture: mask locally, fail closed and only promise what can be proven
- Reliability
- Fail closed: if a layer goes down, the data doesn't pass through unprotected
- Real-time systems
- A streaming buffer that holds partial tokens until it knows whether they belong to a surrogate
- Backend and APIs
- A NestJS gateway plus stateless mask and demask primitives
- Testing and verification
- 512 tests of its own and a leak corpus that acts as a gate
My role
Concept, architecture, directing the agents and verification. Claude Code wrote most of the code, inside an agent workflow I developed myself.
See the Context Observer project