PIIShade Everything the model can do. Nothing it doesn't need to know.

PIIShade replaces the confidential data in your prompts with placeholders before it reaches the model, then restores the real values in the response. Pluggable detectors (regex, NER or an LLM), and OpenAI- and Anthropic-compatible proxies through the piighost-api server.

Works with

  • LangChain
  • Pydantic AI
  • LlamaIndex
agent.py pipeline.py
from langchain.agents import create_agentfrom piighost.integrations.langchain import PIIAnonymizationMiddleware middleware = PIIAnonymizationMiddleware(pipeline=pipeline) agent = create_agent(    model="openai:gpt-5.6",    tools=[send_email],    middleware=[middleware],)# the model only sees placeholders; send_email receives the real values

The problem

You should not have to choose between good models and data privacy

  • Hosted model

    Quality
    yes, The best
    Data exposed
    no, All of it
    Constraint
    yes, None
    Gains
    yes, Yes
  • Local model

    Quality
    no, Degraded
    Data exposed
    yes, None
    Constraint
    no, GPUs and operations
    Gains
    partly, Partial
  • Ban it

    Quality
    no, None
    Data exposed
    yes, None
    Constraint
    yes, Nothing
    Gains
    no, None, and bypassed
  • PIIShade

    Quality
    yes, The best
    Data exposed
    yes, None
    Constraint
    partly, CPU infrastructure
    Gains
    yes, Yes

One limit worth knowing. PIIShade does pseudonymization in the GDPR sense, not anonymization: the mapping between values and placeholders is kept on your side for the duration of the conversation, and has to be protected like personal data.

Why PIIShade

More than a PII detector

Regex and NER detectors know how to find confidential data. De-identifying an exchange with an LLM also means replacing that data, tracking it from one message to the next, and restoring it. PIIShade orchestrates all of it for you.

Composable detectors

Regex, NER or LLM, in a single pipeline. You keep the one you trust.

Placeholders that come back on their own

The model reads <<PERSON:1>>, your user and your tools read the real name.

The same placeholder all along

A value keeps its placeholder from one message to the next, so the model never loses the thread.

One file, your infrastructure

The whole pipeline fits in a TOML file, validated from the command line, run on your side.

Supported detectors

  • Regex
  • GLiNER2
  • spaCy
  • Transformers
  • Presidio

How it works

A layer between your agent and the model

  1. User → piishade

    Send case #ACME-9123 to marie.lambert@acme.com

  2. piishade → Model

    Send case <<ID:1>> to <<EMAIL:1>>

  3. Model → piishade

    send_email(to=<<EMAIL:1>>)

  4. piishade → Tools

    send_email(to=marie.lambert@acme.com)

  5. Tools → piishade

    Email sent to marie.lambert@acme.com

  6. piishade → Model

    Email sent to <<EMAIL:1>>

  7. Model → piishade

    Case <<ID:1>> was sent to <<EMAIL:1>>.

  8. piishade → User

    Case #ACME-9123 was sent to marie.lambert@acme.com.

The model's column holds nothing but placeholders. Even what the tools return is de-identified before the model reads it.

The ecosystem

One privacy layer, many projects

Start with the library. Move to the server when several services share one pipeline, and see it all at work in the chat demo and the CV proofreader.

Quick start

Drop it into your agent framework

Add PIIShade to the framework you already use. Your agent code stays the same.

uv add 'piighost[langchain,gliner2]'
from langchain.agents import create_agent from piighost.components.detector.ner import Gliner2Detectorfrom piighost.pipeline import ThreadAnonymizationPipelinefrom piighost.integrations.langchain import PIIAnonymizationMiddleware # Any detector works: regex, NER, or an LLM.detector = Gliner2Detector("fastino/gliner2-multi-v1", labels=["PERSON", "LOCATION"])pipeline = ThreadAnonymizationPipeline(detector)middleware = PIIAnonymizationMiddleware(pipeline=pipeline) agent = create_agent(    model="openai:gpt-5.6-terra",    tools=[lookup_city],    middleware=[middleware],) # The model only sees <<PERSON:1>>; lookup_city still receives "Patrick".
Added by PIIShade The rest is your agent, unchanged

FAQ

Frequently asked questions

A question that is not here? The community and the documentation have answers.

Why de-identify instead of self-hosting the model?
Self-hosting protects best, but the GPU bill, security and updates are on you, and the model is often weaker. With PIIShade you keep the best models, and only placeholders like <<PERSON:1>> leave your infrastructure. It is one layer of defense, not a silver bullet. The Philosophy page walks through the tradeoff.
What do I need in production?
The library and a pipeline described in TOML, loaded with load_thread_pipeline for a conversation (load_pipeline for a one-off text). pip install 'piighost[config]' is enough for regex; add your detector's extra (gliner2, spacy, transformers or llm), and redis to share memory across processes. Several services? Deploy piighost-api.
Can I use PIIShade with Claude Code?
Yes, through its hooks. They de-identify your prompt and tool outputs, and put the real values back into tool inputs. They rely on a piighost-api server, installed with pip install 'piighost[client]'.
Which frameworks are supported?
LangChain, Pydantic AI and LlamaIndex, through a middleware, hooks and a node transform that de-identifies. For any other client, the OpenAI- and Anthropic-compatible proxies in piighost-api only need a base_url change.
Is PIIShade GDPR compliant?
PIIShade performs reversible pseudonymization in the GDPR sense: it helps compliance without replacing your own legal analysis. The mappings stay with you and must be protected like personal data.
What is the difference between anonymization and de-identification?
Anonymization is irreversible: nobody can link the data back to a person anymore, and it falls outside the GDPR. PIIShade's de-identification is reversible, so your tools and your users get the real values back: under the GDPR, it is pseudonymization. The mapping between values and placeholders stays on your side, and must be protected like personal data.
What is actually sent to the model?
Only the de-identified text, where each value has become a placeholder like <<PERSON:1>>. The mapping stays on your side for the length of the conversation, and PIIShade restores the values locally.

Everything the model can do.
Nothing it doesn't need to know.

Ship your AI features without handing over your customers' confidential data. Install PIIShade, wire your detector, and keep PII out of the model.

pip install piighost