Redact PII before it reaches the model, not after
kRouter can strip names, emails, keys and IDs out of a request before it leaves your machine for any provider -- and reject the request outright if redaction fails, rather than sending it anyway.
Every request an AI coding agent makes carries more than you meant to send. A stack trace with a customer email. A config file with an internal hostname. A git log with your colleagues' names. None of it is the thing you asked about; all of it goes to whichever provider the router picked.
kRouter now has a redaction layer that runs before any of that leaves your machine. It was contributed by manindersarao, whose reasoning was exactly right: "I didn't want my personal data ending up in unknown LLM providers by accident."
Where the layer sits
your IDE -> kRouter -> redaction -> Presidio -> providerThe middleware pulls every piece of user text out of the request, hands it to a local Microsoft Presidio service, and puts the redacted result back before the request continues upstream. Presidio does the detection -- an ML model for names, emails, phone numbers, locations and card numbers, plus whatever regex patterns you add.
Nothing goes to a third party to do the redacting. The Presidio service runs next to kRouter on your own machine.
The part that matters: it fails closed
Most redaction tooling fails open. If the scanner is down, the request goes through unredacted, because blocking traffic feels worse than a missed scan.
That is the wrong default here. A redaction layer you cannot rely on is worse than none, because you will act as if it worked. So if the redactor is unreachable, slow, or returns something unusable, the request is rejected rather than forwarded:
503 Redaction service unavailableYou can opt out with REDACTION_FAIL_OPEN=true, but the name is deliberately unflattering. If you set it, you no longer have the guarantee.
What actually gets scanned
This is where redaction tools usually disappoint. Covering "the user's message" is easy and nearly useless for an agent, because the bulk of an agent request is not the user's message.
Covered:
- Chat messages, both plain strings and multimodal text blocks
- The Anthropic top-level
systemprompt - Responses API
inputandinstructions - Tool traffic --
role:"tool"results,tool_resultblocks, tool descriptions
That last one is the important one. When your agent reads a file, greps a repo, or runs a command, the output comes back as tool content. That is routinely the richest personal data in the entire request, and it is what most redaction layers miss.
Tool call arguments get special handling. They are a JSON string the provider parses, so a redaction that breaks the quoting would turn a valid tool call into a malformed one. The redacted version is only used if it still parses; otherwise the original is kept and a warning logged. A leaked value affects one field. A broken tool call breaks the request for everyone.
What is not covered
Being explicit, because a vague answer here is how people get burned:
/v1/embeddings,/v1/audio/speech,/v1/images/generations,/v1/videos/*do not pass through the middleware- Binary content -- images, PDFs, audio -- is not scanned
- Anything you sent before enabling it
Custom patterns
The ML model catches the common categories. Your own identifiers need patterns, which you write in the dashboard as YAML:
rules:
- entity: "INTERNAL_TICKET"
pattern: "\\bJIRA-\\d{4,6}\\b"
description: "Internal ticket references"
- entity: "DEPLOY_TOKEN"
pattern: "\\bdpl_[A-Za-z0-9]{32}\\b"
description: "Deployment tokens"Patterns are validated before they are saved, and the sidecar hot-reloads them without a restart.
Turning it on
It is off by default. If you never enable it, nothing about kRouter changes.
With Docker:
export KROUTER_INITIAL_PASSWORD="$(openssl rand -base64 24)"
docker compose up -dkRouter itself has no Python dependency, so on an npm install you run the redaction service separately and point kRouter at it with SIDECAR_URL. The setup guide covers both.
Then enable Presidio Sidecar and PII Redaction in Dashboard → Presidio.
What this is and is not
It reduces accidental exposure. That is a genuinely useful thing and it is what most people need.
It is not a compliance control. Detection is probabilistic -- Presidio will miss unusual formats, and non-English text considerably more often. If data must never reach a third party, do not send it: route that work to a local model instead, which kRouter also supports.
The honest framing is that this catches the accident, not the adversary.
Common questions
Does redaction slow requests down?
It adds one round trip to a local service, and Presidio analyses texts in a serial loop, so the cost scales with conversation size rather than request count. REDACTION_TIMEOUT_MS defaults to 15 seconds for that reason. For short prompts the overhead is small; for very long contexts it is noticeable.
Does the model still give good answers on redacted text?
Usually, and sometimes not. If a name or identifier is load-bearing for the task, removing it removes context the model needed. The fix is narrower patterns, not disabling redaction wholesale.
Can I see what was redacted?
The redacted request is what gets sent, and the dashboard's request detail shows it. The original is not stored anywhere by the router.
Does this send my data to Microsoft?
No. Presidio is an open-source library that runs in a container on your own machine. Nothing is sent anywhere to perform the redaction.
What happens if the redaction service crashes mid-session?
Requests are rejected with a 503 until it comes back. That is the fail-closed behaviour working as intended rather than a fault.
Is it on by default?
No. Both presidioEnabled and presidioPiiRedaction default to off, and the published Docker image is unchanged for anyone who does not enable it.
Related
Klaw is the Kodelyth AI agent. He writes drafts, runs the benchmarks, and tracks every cost number in this post live through kRouter. Humans review before publish.
Install kRouter