> ## Documentation Index
> Fetch the complete documentation index at: https://docs.akumi.eu/llms.txt
> Use this file to discover all available pages before exploring further.

# PII firewall

> Pseudonymize personal data before it reaches a model.

The PII firewall pseudonymizes personal data in a request before it reaches a model, then restores the original values in the response. Names, emails, phone numbers and similar identifiers are swapped for stable placeholder tokens on the way in, and swapped back on the way out, so the model never sees the raw data while your application still gets a normal answer.

You will find the PII firewall under **Services > PII firewall**.

## Turning the firewall on

Use the **Enabled** switch in the top right of the page. It takes effect immediately, with no separate save step. The firewall is on by default for new organisations: routing personal data to a model is treated as something you opt out of, not into.

## How pseudonymization works

When a request runs through the firewall, detected entities are replaced with tokens such as `<PERSON_1>` or `<EMAIL_1>`. The mapping from token to original value lives only for the duration of the request and is never sent to a provider. After the model responds, the tokens in the output are replaced with the original values before the response is returned to you.

Because the same value always maps to the same token within a request, the model can still reason about relationships: two mentions of the same person stay consistent.

## What the firewall does when it finds something

A workspace picks one of three actions.

* **Log.** Pseudonymize and carry on. The default, and the one that never interrupts anybody.
* **Ask.** Suspend the request and let a person decide, one value at a time.
* **Block.** Refuse the request outright.

**Ask needs somewhere to ask.** Akumi Chat can suspend a run and put the question on screen; `/v1/chat/completions` cannot, so a workspace set to Ask gets a typed refusal there rather than a silent downgrade to Log. That is deliberate: quietly weakening the action you chose is worse than telling you it does not apply.

The question names what was found, shows the value rather than the placeholder it would become, and says where in the conversation it came from, including which command printed it when a client tells us. A person cannot judge "PERSON detected" on a file listing; they can judge their own username appearing in a path.

## Remembering what somebody allowed

Answering **always allow** records the value so it is never proposed again. Exactly that value, matched case-insensitively and never as a pattern: allowing `jellespekken` does not exempt `jelle@customer.com`.

Exemptions have two tiers.

* **Personal.** Applies only to messages attributable to the person who answered. Anyone may create one.
* **Workspace-wide.** Applies to everybody's messages. Creating one needs the PII firewall permission.

The split exists because names collide. If somebody exempts their own name and a customer happens to share it, a workspace-wide entry would leave that customer's name unprotected for everyone, decided by a person with no authority to decide it. A personal entry cannot reach anybody else's text.

Both tiers are readable and revocable over the chat API, and both directions are audited with who decided. Removing an exemption re-arms masking immediately, including on conversations that were already stored.

**Allowing once limits what the model sees, not what the platform keeps.**

Answering **allow once** masks the value for that request. If the workspace has Recall, the same message is also read for durable facts, and that reading happens on the original text rather than the masked form. So a colleague's name you allowed once is stored in memory as the name.

That is deliberate. A memory of `<PERSON_1>` is worth nothing: it cannot be matched against a later question, and a person asking what the assistant knows about them would be shown a placeholder. The store is Akumi's own and EU-resident, and a stored fact is masked again every time it re-enters a prompt, because recalled facts are injected before the firewall and pseudonymised with everything else.

What it means in practice is that "allow once" is a decision about one request rather than about the record. Erase the fact if you want it gone: memory is readable and erasable per person, and erasing is the control for what the platform keeps.

**An exemption reaches Guard as well as the firewall.** Guard scores what the model writes against ten content categories, one of which is also called PII, and it can be set to refuse an answer outright. Without this, a value you had declared not personal would still get answers refused for containing it: you would have answered the question and been asked again, by something that does not take an answer.

So an allowed value is taken out of the text before Guard's moderation detector reads it. Only that detector, and only that text. A term an admin blocked still blocks, because blocked terms are a different rule about different things, and none of the other nine categories change.

This is wider than "stop asking me about my own name", which is what most people are answering when they allow a value. Read it as: the value is not personal data here, and in what the assistant writes back.

Be aware of what an exemption cannot do: it stops a value being *detected*, so it cannot distinguish two people who share a name. Exempting "Jan Jansen" means Jan Jansen is not masked in your messages, whichever Jan Jansen is meant.

## Detection drivers

The firewall can detect entities with either a built-in pattern driver or an external analysis service, depending on how your organisation is configured. Both produce the same token format, so switching drivers does not change how your application consumes the response.

What it looks for: names, email addresses, phone numbers, street addresses, IBANs, credit card numbers, IP addresses, and four document numbers that are checked rather than merely matched. The Dutch **BSN** is validated against its checksum, the German **tax identification number** against its own, **EU VAT numbers** against the per-country format, and **passport numbers** by shape. Validating rather than pattern-matching is what keeps an order reference that happens to be nine digits long from being treated as somebody's national identifier.

A workspace can add **custom terms** on top: literal strings, matched whole-token and case-insensitively, for the codenames and internal identifiers no general detector can know about.

## Routing to external models

Pseudonymized data is still personal data. Sending it to a non-EU or third-party model remains a data transfer with its own obligations. External routing is only allowed when the firewall is active for the request, or when an administrator has recorded an explicit acknowledgement that accepts responsibility for the transfer. Without one of those, the request is refused rather than sent.

## What is recorded

Each firewalled request records that the firewall ran and how many entities were handled, never the original values. You can review this activity in the audit log.

The firewall governs what leaves the platform, not what other services you enable store. A [Recall](/guides/recall) thread keeps the conversation as you sent it, the [Cache](/guides/cache) stores the final answer with the real values restored, and [Observability](/guides/observability) payload capture stores what each stage was given, pseudonymized wherever the firewall ran. Each of those pages says what it keeps and how to delete it.
