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
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 valuesThe 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
User → piighost
Send case #ACME-9123 to marie.lambert@acme.com
piighost → Model
Send case <<ID:1>> to <<EMAIL:1>>
Model → piighost
send_email(to=<<EMAIL:1>>)
piighost → Tools
send_email(to=marie.lambert@acme.com)
Tools → piighost
Email sent to marie.lambert@acme.com
piighost → Model
Email sent to <<EMAIL:1>>
Model → piighost
Case <<ID:1>> was sent to <<EMAIL:1>>.
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.
piighost
The core library. Build PII de-identification pipelines for AI agents.
Learn morepiighost-api
A REST server that hosts one piighost pipeline behind HTTP.
Learn morepiighost-chat
A demo chatbot that de-identifies messages before the LLM sees them.
Learn morepiighost-proofreader
An LLM CV proofreader that de-identifies documents before any LLM call.
Learn morecaviardage
An app that redacts a Word deed in the browser. Nothing of the document leaves the tab.
Learn more<<PROJECT_NAME:2b1f4a>>
More to come.
<<PROJECT_NAME:7c43e9>>
More to come.
<<PROJECT_NAME:9af0d2>>
More to come.
<<PROJECT_NAME:1e8c75>>
More to come.
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".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?
<<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?
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?
pip install 'piighost[client]'.Which frameworks are supported?
base_url change.Is piighost GDPR compliant?
What is the difference between anonymization and de-identification?
What is actually sent to the model?
<<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.
LlamaIndex
GLiNER2
spaCy
Presidio