Saklam Bridge + n8n — PII masking for your workflows
Every n8n automation that sends customer data to Claude, GPT or Mistral ships cleartext out of the house. Put the Bridge in front and only placeholders leave — and the response comes back with the real values restored. Both on-premises, one base-URL field, no code.
Tested and verified with self-hosted n8n (Docker) and saklam/bridge:latest — the walkthrough below is taken from an actual run.
Architecture
n8n (self-hosted, your infra)
Chat Trigger · AI Agent · any workflow
│
│ OpenAI credential, Base URL = http://saklam-bridge:4000/v1
▼
┌─ Saklam Bridge (Docker, same infra) ─────────────────────┐
│ 1. PII masking (300+ patterns, NER, German-optimized) │
│ 2. Forward to the provider with your API key (BYOK) │
│ 3. Response is unmasked locally │
└───────────────────────────────────────────────────────────┘
│ masked tokens only
▼
Anthropic / OpenAI / Mistral
Both run inside your network. No public endpoint required, no cleartext ever leaves your infrastructure, Saklam sees nothing.
Prerequisites
- A running Saklam Bridge — setup guide (5-minute install via docker compose)
- Self-hosted n8n (Docker). n8n Cloud works technically, but then the Bridge needs a publicly reachable HTTPS endpoint — you lose the on-prem advantage. Recommendation: self-hosted.
- A pay-as-you-go API key for your LLM provider (BYOK)
Setup in 3 steps
1. Shared Docker network
Bridge and n8n need to reach each other. Either put both services into one docker-compose.yml, or connect them after the fact:
docker network create saklam
docker network connect saklam saklam-bridge
docker network connect saklam n8n
2. Create the credential in n8n
Credentials → New → OpenAI (yes, even for Claude — see the note below):
| Field | Value |
|---|---|
| API Key | your BRIDGE_MASTER_KEY (or any value in localhost mode) |
| Base URL | http://saklam-bridge:4000/v1 |
Important: use the OpenAI node for Claude. n8n's Anthropic credential has no base-URL field and cannot be pointed at the Bridge. The OpenAI node can — and the Bridge translates the OpenAI wire format internally for every configured provider. Model name in the node e.g.
claude-haiku-4-5,gpt-4oormistral/mistral-large-latest.
3. Build the workflow
The standard shape for a masked chat:
Chat Trigger → AI Agent
└─ Chat Model: OpenAI Chat Model
(credential from step 2, any model)
That's it. Every workflow whose model node points at the Bridge is masked from now on — including non-chat workflows (email automations, extraction, classification).
Verify what actually leaves
Enable the Bridge debug log (PRIVACYLIGHT_DEBUG=true) and send a test prompt with sample data. From our test run, verbatim:
ORIGINAL (User Input):
Formuliere 2 Saetze Bestaetigung an Herrn Max Mustermann
(max.mustermann@beispiel-kanzlei.de), dass seine IBAN
DE89370400440532013000 hinterlegt wurde.
MASKED (Sent to LLM):
Formuliere 2 Saetze Bestaetigung an Herrn [PER_0f3b14eb]
([EMA_09ac6528]), dass seine IBAN [IBA_5e78bec2] hinterlegt wurde.
The chat response in n8n contains the real values again — unmasking happens locally in the Bridge before the response reaches your workflow.
Chat UI without building a frontend
The Chat Trigger node ships with both:
- Hosted chat: n8n serves a ready-made chat page at the node's chat URL.
- Embedded chat: the
@n8n/chatwidget embeds into any internal page (streaming, CORS control, CSS-customizable).
Which makes "privacy-conscious company chat on a frontier model" an n8n workflow plus one base-URL field.
n8n Chat Hub
n8n's built-in chat interface (Chat Hub, the "Chat" navigation item) works through the Bridge as well — same OpenAI credential, no workflow needed: pick the model in the picker, chat, masking runs. Tested and verified (Bridge ≥ v0.2.1).
Two notes: Chat Hub speaks the OpenAI Responses API — Bridge versions before v0.2.1 don't support it (docker compose pull is enough). And the model picker can only send concrete model names; claude-haiku-4-5 and claude-sonnet-4-6 ship preconfigured as of v0.2.1.
What about n8n's Guardrails node?
Since v2, n8n ships its own Guardrails node — and it's good at what it's built for: jailbreak detection, NSFW filtering, keyword checks and one-way sanitization. For PII masking in front of an LLM it has three structural limits (checked against the node definition v1/v2 and via a test run, as of July 2026):
- One-way. The node has
classifyandsanitize— no unmask, no mapping.<EMAIL_ADDRESS>stays<EMAIL_ADDRESS>, in the response too. Not enough for chat, email drafts or extraction, where the user needs the real values back. - International pattern set without a PERSON entity. On the same German test text, the Guardrails node caught email and IBAN — name, date of birth, address, German mobile number, court file number and ICD-10 code passed through in cleartext, and the German tax ID was classified as an Australian business number (
AU_ABN). The Bridge masked all nine entities, reversibly. - The LLM-based PII check sends cleartext to the connected model. In the Guardrails node, name detection only works via the LLM check — which by design feeds the unfiltered text to a chat model. If that's a cloud model, the data is already out before the protection layer kicks in.
In short: Guardrails node for policy checks, Bridge for masking. The two combine well — Guardrails checks jailbreaks, the Bridge sits once at the gateway and masks for all workflows instead of one node per workflow.
Pricing & license
Same license as in the setup guide: €99 / month or €990 / year (plus VAT), 1 Bridge instance, unlimited volume, covering all workflows and users of the n8n behind it. 7-day free trial.
Building n8n workflows for clients? Agencies and integrators who want to embed the Bridge in customer projects: drop me a line (stefan@saklam.com) — multi-instance terms are handled individually.