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

piighost 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 PIIAnonymizationMiddlewaremiddleware = 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
  • piighost

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

One limit worth knowing. piighost 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 piighost

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. piighost 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 → piighost

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

  2. piighost → Model

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

  3. Model → piighost

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

  4. piighost → Tools

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

  5. Tools → piighost

    Email sent to marie.lambert@acme.com

  6. piighost → Model

    Email sent to <<EMAIL:1>>

  7. Model → piighost

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

  8. piighost → 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, the CV proofreader and the redaction tool.

Quick start

Drop it into your agent framework

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

uv add 'piighost[langchain,gliner2]'
from langchain.agents import create_agentfrom 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 piighost 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 piighost 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 piighost 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 piighost GDPR compliant?
piighost 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. piighost'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 piighost 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 piighost, wire your detector, and keep PII out of the model.

uv add piighost