Anonymization for Privacy-Safe RAG

Anonymize sensitive data before storage and retrieval in RAG pipelines to prevent PII leakage.

In agentic workflows, such as RAG and multi-step agents, use AI Developer Edition to anonymize sensitive data before storage and retrieval. This prevents PII leakage through embeddings, prompts, or outputs.

Anonymization removes who while preserving what happened. Names, identifiers, and contact details are replaced or suppressed, but the events, patterns, and relationships that make data useful for AI reasoning remain intact. This lets your agents learn from real data, retrieve relevant context, and produce accurate insights — without exposing the individuals behind the records.

The Problem with RAG and Sensitive Data

Documents with PII → Embeddings → Vector DB → Retrieval → LLM → Output
     ↑                    ↑                         ↑            ↑
  Names, IDs        PII in vectors        PII in context    PII in response

At every stage, real identities can leak:

  • Embeddings encode PII into vectors that can be extracted
  • Retrieved context passes real names/IDs to the LLM
  • Agent outputs may include identities from retrieved documents
  • Logs capture the full RAG pipeline with PII

The Solution - Anonymize Before RAG

Documents → Anonymize → Embeddings → Vector DB → Retrieval → LLM → Output
              ↑                                                         ↑
         Remove PII                                          No PII possible
         Keep utility                                        Safe insights

How Anonymization Works

OriginalAnonymizedUtility Preserved
John Smith filed complaint#4521Person_001 filed complaint#4521Complaint pattern
sarah@company.com reported buguser_001@example.com reported bugBug report context
SSN 123-45-6789 in record[SSN_REDACTED] in recordField structure
Employee E1001 earned $170,000Employee_A earned $170,000Compensation data

Best Practices

  1. Anonymize before embedding. Never store real PII in vector databases. Anonymize documents before generating embeddings so that identities cannot be extracted from stored vectors.
  2. Preserve data utility. Keep patterns, relationships, and structure intact during anonymization. The anonymized data should support the same reasoning and retrieval quality as the original.
  3. Use consistent pseudonyms. Map the same person to the same pseudonym across all records. This preserves relationship tracking so agents can follow connections without seeing real identities.
  4. Test for information loss. After anonymizing, verify that the data still supports your use case. Run sample queries or training tasks to confirm that utility is preserved before deploying.
  5. Use irreversible anonymization for training. Apply one-way anonymization to any data used for model training. Training data should never be linkable back to real individuals.
  6. Document what was removed. Keep metadata about which fields were anonymized and what method was used. This supports compliance reporting and lets you audit your anonymization pipeline over time.

Example 1: Anonymize Documents for RAG Pipeline

Cursor Prompt

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition Anonymization, anonymize all documents before storing them in my vector database for RAG retrieval. The agent should be able to retrieve and reason on content without exposing real identities.

Implementation

"""
Anonymization for Privacy-Safe RAG Pipeline
"""
import protegrity_developer_python

protegrity_developer_python.configure(
    endpoint_url="http://localhost:8580/pty/data-discovery/v2/classify",
    named_entity_map={
        "PERSON": "NAME", "EMAIL_ADDRESS": "EMAIL", "SOCIAL_SECURITY_ID": "SSN",
        "PHONE_NUMBER": "PHONE", "LOCATION": "ADDRESS"
    },
    masking_char="#",
    classification_score_threshold=0.6,
    method="redact",
    enable_logging=True,
    log_level="info"
)

# Original documents containing PII
documents = [
    {
        "id": "doc_001",
        "content": "Sarah Johnson (employee E1001) filed a harassment complaint "
                   "against her manager David Chen on March 15, 2025. HR Director "
                   "Maria Lopez reviewed the case. Contact: sarah.j@company.com, "
                   "SSN: 123-45-6789."
    },
    {
        "id": "doc_002", 
        "content": "Performance review for James Smith (E1002): Exceeded expectations "
                   "in Q4 2025. Salary adjustment from $130,000 to $145,000 approved "
                   "by VP Emily Brown. James's address: 456 Oak Ave, Chicago, IL."
    },
    {
        "id": "doc_003",
        "content": "Customer complaint from Robert Davis (account #ACC-789012): "
                   "Unauthorized charge of $4,500 on card ending 9012. Customer phone: "
                   "555-0198. Email: r.davis@email.com"
    }
]

# Anonymize before vector storage using find_and_redact
anonymized_docs = []
for doc in documents:
    anonymized_content = protegrity_developer_python.find_and_redact(doc["content"])
    anonymized_docs.append({"id": doc["id"], "content": anonymized_content})

Anonymized Output

# What gets stored in vector DB:
{
    "id": "doc_001",
    "content": "Person_001 (employee EMP_A) filed a harassment complaint "
               "against their manager Person_002 on March 15, 2025. HR Director "
               "Person_003 reviewed the case. Contact: [EMAIL_REDACTED], "
               "SSN: [SSN_REDACTED]."
}
{
    "id": "doc_002",
    "content": "Performance review for Person_004 (EMP_B): Exceeded expectations "
               "in Q4 2025. Salary adjustment from $130,000 to $145,000 approved "
               "by VP Person_005. Person_004's address: [ADDRESS_REDACTED]."
}
{
    "id": "doc_003",
    "content": "Customer complaint from Person_006 (account #[ACCT_REDACTED]): "
               "Unauthorized charge of $4,500 on card ending [REDACTED]. Customer phone: "
               "[PHONE_REDACTED]. Email: [EMAIL_REDACTED]"
}

RAG Retrieval and Reasoning

# Agent retrieves anonymized content and reasons safely
query = "What harassment complaints have been filed recently?"
# Retrieved context (anonymized)
context = vector_db.retrieve(query)
# → "Person_001 filed a harassment complaint against their manager Person_002..."
# Agent reasons without knowing real identities
response = agent.reason(context)
# → "There was a harassment complaint filed on March 15, 2025. 
#    HR reviewed the case. The complaint involved a manager-subordinate relationship."
#   Insight provided without exposing Sarah Johnson, David Chen, or Maria Lopez

Example 2: Train & Test AI Agents with Real Data Without Exposing Identity

The Scenario

An AI agent needs to:

  • Analyze customer feedback and support logs
  • Learn patterns from real data
  • Make predictions about customer behavior
  • Without ever seeing who the data belongs to

Cursor Prompt

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition Anonymization, prepare our customer support logs for agent training. Remove all identities but keep the patterns and insights intact so the model can learn from real behavior.

Implementation

"""
Anonymization for AI Training: Customer Support Logs
"""
import protegrity_developer_python
import pandas as pd

protegrity_developer_python.configure(
    endpoint_url="http://localhost:8580/pty/data-discovery/v2/classify",
    named_entity_map={"PERSON": "NAME", "EMAIL_ADDRESS": "EMAIL"},
    classification_score_threshold=0.6,
    method="redact",
    enable_logging=True,
    log_level="info"
)

# Real support logs with PII
support_logs = pd.DataFrame([
    {"ticket_id": "T001", "customer": "Alice Wong", "email": "alice.w@email.com",
     "issue": "Login failed after password reset", "resolution": "Reset MFA token",
     "satisfaction": 4, "resolution_time_hrs": 2.5},
    
    {"ticket_id": "T002", "customer": "Bob Martinez", "email": "bob.m@company.org",
     "issue": "Billing discrepancy on invoice #4521", "resolution": "Credit issued",
     "satisfaction": 3, "resolution_time_hrs": 48.0},
    
    {"ticket_id": "T003", "customer": "Carol Chen", "email": "carol@startup.io",
     "issue": "API rate limiting affecting production", "resolution": "Upgraded plan",
     "satisfaction": 5, "resolution_time_hrs": 1.0},
])

# Anonymize PII columns by redacting each value
for col in ["customer", "email"]:
    support_logs[col] = support_logs[col].apply(protegrity_developer_python.find_and_redact)

print("Anonymized Training Data:")
print(support_logs[["customer", "email", "issue", "satisfaction"]].to_string())

Output

Anonymized Training Data:
    customer              email                              issue  satisfaction
0  Customer_001  user001@example.com  Login failed after password reset             4
1  Customer_002  user002@example.com  Billing discrepancy on invoice #4521          3
2  Customer_003  user003@example.com  API rate limiting affecting production        5

What the Agent Learns without Identities

# Agent trains on anonymized data
model = train_support_model(training_data)
# Agent learns:
# Login issues → MFA reset resolves quickly (avg 2.5 hrs)
# Billing issues → Credits needed, longer resolution (avg 48 hrs)
# API issues → Plan upgrades, highest satisfaction
# Never learns: Alice Wong has login problems, Bob has billing issues

Use Anonymization for Safe Code Debugging with Real Logs in Cursor

The Scenario

Developers debug production issues using real logs. These logs contain:

  • User emails and IDs
  • Session tokens
  • IP addresses
  • Request parameters with PII

Cursor Prompt

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition Anonymization, strip user data from these production logs before I send them to Cursor for debugging. Keep the error context intact.

Implementation

"""
Anonymization for Safe Debugging: Production Logs
"""
import protegrity_developer_python

protegrity_developer_python.configure(
    endpoint_url="http://localhost:8580/pty/data-discovery/v2/classify",
    named_entity_map={
        "PERSON": "NAME", "EMAIL_ADDRESS": "EMAIL", "PHONE_NUMBER": "PHONE"
    },
    classification_score_threshold=0.6,
    method="redact",
    enable_logging=True,
    log_level="info"
)

# Real production log with PII
real_log = """
[2025-03-15 14:22:33] ERROR - PaymentService
  User: john.smith@company.com (ID: USR-78901)
  Session: eyJhbGciOiJIUzI1NiIs...
  IP: 192.168.1.42
  Action: process_payment
  Card: 4532-1234-5678-9012
  Error: TimeoutException at PaymentGateway.charge()
  Stack: 
    at PaymentService.process(PaymentService.java:142)
    at OrderController.checkout(OrderController.java:89)
    at RequestHandler.handle(RequestHandler.java:45)
  Request: {"amount": 299.99, "customer_email": "john.smith@company.com"}
[2025-03-15 14:22:34] ERROR - PaymentService
  User: sarah.jones@email.org (ID: USR-45678)
  Session: eyJhbGciOiJSUzI1NiIs...
  IP: 10.0.0.15
  Action: process_payment
  Card: 5411-9876-5432-1098
  Error: TimeoutException at PaymentGateway.charge()
  Stack:
    at PaymentService.process(PaymentService.java:142)
    at OrderController.checkout(OrderController.java:89)
"""

# Anonymize for safe debugging - redact all PII while preserving error context
safe_log = protegrity_developer_python.find_and_redact(real_log)

What Cursor Sees as Anonymized

[2025-03-15 14:22:33] ERROR - PaymentService
  User: user_001@example.com (ID: USR-XXXXX)
  Session: [SESSION_REDACTED]
  IP: [IP_REDACTED]
  Action: process_payment
  Card: [CARD_REDACTED]
  Error: TimeoutException at PaymentGateway.charge()
  Stack: 
    at PaymentService.process(PaymentService.java:142)
    at OrderController.checkout(OrderController.java:89)
    at RequestHandler.handle(RequestHandler.java:45)
  Request: {"amount": 299.99, "customer_email": "[EMAIL_REDACTED]"}
[2025-03-15 14:22:34] ERROR - PaymentService  
  User: user_002@example.com (ID: USR-XXXXX)
  Session: [SESSION_REDACTED]
  IP: [IP_REDACTED]
  Action: process_payment
  Card: [CARD_REDACTED]
  Error: TimeoutException at PaymentGateway.charge()
  Stack:
    at PaymentService.process(PaymentService.java:142)
    at OrderController.checkout(OrderController.java:89)

Cursor Debugging Output

Cursor AI Analysis:
─────────────────
The TimeoutException occurs in PaymentGateway.charge() for multiple users 
at similar timestamps (14:22:33 and 14:22:34). This suggests:
1. Payment gateway is experiencing latency/outage
2. Not user-specific - affects multiple customers simultaneously
3. The call stack shows the timeout happens at the gateway level, 
   not in your application code
Recommendation:
- Add circuit breaker pattern in PaymentService.process()
- Implement retry with exponential backoff
- Add timeout configuration (currently using default)
- Set up health check for PaymentGateway endpoint

Result: Cursor diagnoses the issue perfectly without ever seeing real user identities.

Anonymization Methods

MethodDescriptionUse Case
PseudonymizationReplace with consistent fake valuesRAG, training
GeneralizationReplace specific → general (“New York” → “East Coast”)Analytics
SuppressionRemove entirely ([REDACTED])Logs, debugging
K-AnonymityEnsure each record matches K othersPublishing data
Differential PrivacyAdd calibrated noiseStatistical queries

Last modified : August 04, 2026