Protect sensitive data from AI models —
without changing how your team works.

Armos masks PII before it reaches any AI provider — names, emails, Aadhaar, PAN, card numbers. Works as a Python/Node SDK wrapper and as a Claude Code MCP. The model sees tokens. Your app gets real values back.

Get started Talk to founder
Open source Zero content logged Python · Node · Claude Code
Before
from openai import OpenAI

client = OpenAI()

response = client.chat
  .completions.create(
    model="gpt-4o",
    messages=[{
      "content": prompt
    }]
)
After — one word changed
from openai import OpenAI
from armos import ArmosOpenAI

client = ArmosOpenAI(OpenAI())

response = client.chat
  .completions.create(
    model="gpt-4o",
    messages=[{
      "content": prompt
    }]
)

The problem

Every prompt you send carries raw data.

Names, emails, phone numbers, financial identifiers — they reach the model provider's infrastructure with every API call. Most teams don't think about this until they have to.

Without Armos — what the model receives
"Customer John Smith (john.smith@acme.com) says his card 4111 1111 1111 1111 was charged twice on his account +91 98765 43210. Draft a refund email."
With Armos — what the model actually receives
"Customer [PII:NAME:a1b2] ([PII:EMAIL:c3d4]) says his card [PII:CARD:e5f6] was charged twice on his account [PII:PHONE:g7h8]. Draft a refund email."

The response comes back with real values restored. Your app sees John Smith, not the token.

Prompts you can now send safely with Armos
"Draft a refund email for John Smith at john.smith@acme.com" "What's the claim status for +91 98765 43210?" "Review the application — Aadhaar 2345 6789 0123" "Card 4111 1111 1111 1111 was charged twice — draft apology" "Summarize the ticket from Priya Patel" "Onboarding docs for alex.jones@techcorp.com starting Monday" "Tax liability for PAN ABCDE1234F this quarter" "Check IBAN GB29NWBK60161331926819 for anomalies" "Draft a refund email for John Smith at john.smith@acme.com" "What's the claim status for +91 98765 43210?" "Review the application — Aadhaar 2345 6789 0123" "Card 4111 1111 1111 1111 was charged twice — draft apology" "Summarize the ticket from Priya Patel" "Onboarding docs for alex.jones@techcorp.com starting Monday" "Tax liability for PAN ABCDE1234F this quarter" "Check IBAN GB29NWBK60161331926819 for anomalies"
"Performance review for Ankita Sharma, emp EMP-4821" "Audit access logs for key sk-abc123xyz789" "Discharge summary — patient Rahul Mehta, DOB 14-03-1985" "Reply to complaint from IP 192.168.1.100" "Schedule renewal call for sarah.d@enterprise.io" "Credit report for SSN 371-53-1234" "Translate letter addressed to Flat 4B, Koramangala" "Flag 4111 1111 1111 1111 transactions last 30 days" "Performance review for Ankita Sharma, emp EMP-4821" "Audit access logs for key sk-abc123xyz789" "Discharge summary — patient Rahul Mehta, DOB 14-03-1985" "Reply to complaint from IP 192.168.1.100" "Schedule renewal call for sarah.d@enterprise.io" "Credit report for SSN 371-53-1234" "Translate letter addressed to Flat 4B, Koramangala" "Flag 4111 1111 1111 1111 transactions last 30 days"
How it works

Detect. Mask. Forward. Restore.

Four steps, invisible to your application. Armos handles the full round-trip before and after every LLM call.

Your prompt
Detect PII
Mask + vault
LLM provider
Restore tokens
Full response
01
Detect
Presidio + armos-ner-en scan every prompt locally. Names, Aadhaar, emails, PAN, cards, API keys — found before anything leaves your process.
02
Mask
Detected entities are replaced with deterministic tokens like [PII:NAME:a1b2c3d4]. The same value always maps to the same token within a session.
03
Restore
After the LLM responds, tokens are swapped back to real values automatically. Your application receives the full, readable response — nothing changes from the outside.

What it does

What Armos actually does for you.

Not a firewall. Not a scanner. A privacy layer that sits between your code and any AI provider, invisibly.

PII never reaches the model

Detection and masking happen before your request leaves your infrastructure. The model provider only ever sees tokens — never actual names, emails, or ID numbers.

See the flow →

Your workflow doesn't change

Responses come back with real values restored. Your app sees John Smith, not a token. One wrapper line or one MCP command — nothing else in your code changes.

Get started →

Nothing content-wise is ever logged

Audit logs record entity types and counts — never the actual text. We know Armos masked 3 email addresses. We have no idea what those email addresses were.

About our audit log →

Works where you build

Python and Node SDK wrappers for your app. A Claude Code MCP for your editor. Same privacy guarantee, two integration paths — add both in under five minutes.

Two integration paths →

Detection

11 entity types, built-in.

Covers global PII — including Indian identifiers no other library handles reliably out of the box.

Person name
[PII:NAME:…]
John Smith · Priya Patel
Email address
[PII:EMAIL:…]
john@hospital.com
Phone number
[PII:PHONE:…]
+91 98765 43210
Credit / debit card
[PII:CARD:…]
4111 1111 1111 1111
API keys & secrets
[PII:APIKEY:…]
sk-abc… · AKIA… · ghp_…
Physical address
[PII:ADDRESS:…]
123 Oak Ave · Flat 4B, Koramangala
IP address
[PII:IP:…]
192.168.1.100
Aadhaar number 🇮🇳 India
[PII:AADHAAR:…]
2345 6789 0123
PAN card 🇮🇳 India
[PII:PAN:…]
ABCDE1234F
SSN 🇺🇸 US
[PII:SSN:…]
371-53-1234
IBAN 🌍 Global
[PII:IBAN:…]
GB29NWBK60161331926819
Custom entities Soon
[PII:CUSTOM:…]
Medical IDs, employee numbers, internal codes

Accuracy

Benchmarked across 10,000+ samples.

Tested on real Indian and Western names, addresses, and structured identifiers. Armos ships with armos-ner-en — a custom-trained spaCy NER model built specifically for PII detection, not adapted from a generic base.

99.3%
PERSON detection
Indian + Western names
100%
ADDRESS detection
Indian + Western formats
99.8–100%
Structured identifiers
Email, Phone, ID numbers
0%
False positive rate
All entity types

Features

Everything in the pipeline, handled.

Armos is a complete privacy layer — detection, tokenization, encryption, vault, and restore. Not just a scanner.

01
NER detection, built for real data
armos-ner-en is a custom-trained spaCy model built specifically for PII — not a general-purpose NER adapted for privacy. It handles Indian names, addresses, and identifiers that off-the-shelf models miss. 99.3% accuracy on person detection, zero false positives across all entity types.
mask same
02
Deterministic tokens, consistent across turns
The same PII value always maps to the same token within a session. John Smith is always [PII:NAME:a1b2] — not a different token each time. This means the model can reason about the same person across a multi-turn conversation without ever seeing the real name.
HKDF(api_key, token) key never persisted
03
AES-256-GCM encryption, key derived per-request
Each token's vault entry is encrypted with a key derived from AES-256-GCM(HKDF(api_key, token)). The encryption key is never stored — it's derived on demand from your API key and the token. Even if the Redis vault were compromised, the data inside is unreadable without the original API key.
AUDIT LOG entity type & count stored content never stored
04
Zero content in audit logs
Audit events record entity types detected, entity counts, model name, and provider — nothing else. Armos knows "3 NAME entities and 1 EMAIL entity were masked in a request to claude-sonnet-4-6." It has no record of what those entities actually were. Your prompts and responses are never stored anywhere.

Get started

Up and running in minutes.

Two integration paths. Pick the one that fits your stack.

01
Install
pip install armos
Requires Python 3.10+ · spaCy model downloads automatically on first use
02
Wrap your client — one word changed
from openai import OpenAI
from armos import ArmosOpenAI

client = ArmosOpenAI(OpenAI())
# or: ArmosAnthropic(Anthropic())
# or: ArmosAsyncOpenAI(AsyncOpenAI())
03
Use it — nothing else changes
response = client.chat.completions.create(
  model="gpt-4o",
  messages=[{"role": "user", "content": prompt}]
)
# PII masked in transit, real values in response
GitHub PyPI

Worried about what your team sends to AI?

We work directly with a handful of teams to understand their real data privacy challenges. 20 minutes, no pitch — just an honest conversation about your use case. You get early access and shape what we build next.

FAQ

Common questions

What's the difference between the Python SDK and the Claude Code MCP?
The Python SDK wraps your OpenAI or Anthropic client in your app — masking runs locally in your process, no Armos server involved. The Claude Code MCP runs a local HTTP proxy (port 3939) that intercepts Claude Code's API calls and routes them through proxy.armos.dev for masking before they reach Anthropic. Both give you the same privacy guarantee; the MCP path uses cloud-side detection to avoid running a Python process locally.
Does Armos log my prompts or responses?
No. Audit logs contain only metadata: entity types detected, entity counts, model name, and provider. We know "3 NAME entities and 1 EMAIL entity were masked in a request to claude-sonnet-4-6." We have no record of what those entities actually were. Zero prompt or response content is ever stored.
How do I mask PII before sending to OpenAI or Anthropic?
Replace OpenAI() with ArmosOpenAI(OpenAI()). Armos intercepts every request, masks PII before it leaves your server, and restores real values in the response automatically. For Claude Code, use the MCP path above.
Is Armos a Presidio wrapper?
Armos uses Presidio for detection but goes beyond it — adding tokenization, a reversible vault, and direct OpenAI and Anthropic SDK integration. Presidio detects PII; Armos masks it, manages the token vault, and wires everything into your LLM calls automatically.
Can I use Armos for HIPAA or GDPR workflows?
Yes. HIPAA and GDPR both require data minimization — sensitive data should only be shared when necessary and in the least identifiable form. Armos enforces that at the LLM layer. The model provider only ever sees anonymized tokens. If your team builds LLM workflows touching health records, financial data, or personal information, Armos handles the PII-in-transit problem so you can focus on the rest of your compliance stack.
Where does the token-to-value mapping live?
In the Python SDK: in-memory by default (ephemeral, nothing persists after the process ends). For multi-turn conversations across requests, use the Redis backend (pip install armos[redis]). In the Claude Code MCP path, the vault is managed by the Armos proxy using per-request AES-256-GCM encryption — the key is never stored. Everything stays in your own infrastructure.