Redact PII from AI Agent Logs Without a Gateway
TL;DR: AI agents generate evidence trails that leak PII through tool calls and retrieved context. PII-Shield's in-process WASM approach uses deterministic hashing to sanitize logs without a separate redaction gateway, making audit trails compliant while preserving correlation for debugging.
The Problem: AI Agents Create a New Logging Surface
Traditional applications log user input and application state. But AI agents introduce a new logging surface: evidence trails.
When an AI agent reasons through a task, it leaves behind:
- Tool call arguments: What the agent passed to APIs, databases, or external services
- Reasoning traces: The LLM's step-by-step thinking, which may include retrieved documents or context
- Tool outputs: Results from external systems that may contain sensitive data
- RAG-retrieved context: Document fragments or database records pulled into the agent's working memory
Here's the trap: PII often leaks not from direct user input, but from retrieved context. A customer support agent pulls a support ticket that contains an email address. The reasoning trace logs that ticket verbatim. Suddenly, your audit logs contain raw PII that has nothing to do with what the user typed.
This creates a regulatory nightmare. HIPAA, GDPR, and SOC 2 all require audit trails—you must log what the agent did. But those logs become a liability if they contain raw PII.
Two Architectural Approaches: Gateway vs. In-Process
There are two ways to solve this. Each has tradeoffs.
| Gateway-Based (Treza, Gravitee) |
In-Process WASM (PII-Shield) |
|
|---|---|---|
| Architecture | Separate redaction service. Logs flow: agent → gateway → storage | Embedded in agent process. Logs sanitized in-memory before emission |
| Redaction type | Reversible (detect, redact, can restore if you have the key) | Irreversible deterministic hashing (one-way function) |
| Latency | Adds a network hop — single-digit to low double-digit milliseconds depending on gateway location (illustrative, not a measured benchmark) | Sub-millisecond, no network call (measured p50 ≈0.03ms, p95 ≈0.04ms — see note below) |
| Best for | Chatbots that need to show the user their own data ("Hi [NAME]") | Audit logs where correlation > disclosure risk |
| Operational burden | Extra service to run, monitor, scale | Part of the agent binary, no extra infrastructure |
Neither is universally "better." The right choice depends on your use case.
Why Deterministic Hashing Fits Audit Trails Better Than Reversible Redaction
Reversible redaction makes sense when the system needs to know the original value for functional reasons. If a chatbot says "Hi Sarah," it needs to restore "Sarah" from a redacted form. Once the user sees the output, the data has already been disclosed to them—so reversible redaction doesn't hurt.
Audit logs are different. The goal is not functional disclosure—it's correlation. You want to link events together without exposing the raw data:
- Without hashing: "Agent X retrieved customer 12345, looked up email foo@example.com, called tool Y with foo@example.com."
Compliance problem: the log contains the email. - With deterministic hashing: "Agent X retrieved customer 12345, looked up email [HIDDEN:a1b2c3], called tool Y with [HIDDEN:a1b2c3]."
The hash is the same both times, so you can still ask "what events involved this customer?"—without storing raw PII.
The key insight: deterministic hashing provides correlation without disclosure. Using HMAC-SHA256 with a shared salt, the same email always produces the same hash. You can't reverse it, but you can group events together for debugging or audit queries.
For audit trails, this is often enough. And it's simpler: no need for a separate gateway, no latency hit, no operational overhead.
Case Study: How GuardSpine Code Uses PII-Shield
GuardSpine Code is a GitHub Action for AI-assisted PR review. It's an early-stage, source-available project (5 stars at the time of writing)—not a large enterprise deployment. We're covering it here because the specific problem it solves with PII-Shield is one a lot of teams building AI-mediated review pipelines will eventually hit.
Every AI-assisted code review sends diff content to a language model—Claude, GPT, Gemini, or a local Ollama instance. That diff can contain hardcoded API keys, database credentials in migration files, or PII in test fixtures. GuardSpine Code also produces a hash-chained evidence bundle for every PR decision, designed so that anyone can verify it without trusting GuardSpine—which means that bundle can't contain raw secrets either, since it may be retained and handed to auditors years later.
PII-Shield sits in their pipeline as a sanitization step, not as the source of truth for the diff:
PR Diff (raw)
|
+-- SHA-256 hash (raw diff preserved for integrity proof)
|
+-- PII-Shield sanitize -----> Sanitized diff
| |
| AI model review
| |
+-- PR Comment, Evidence Bundle, SARIF (all sanitized)
The raw diff itself is never modified or sent anywhere unsanitized—PII-Shield operates on copies destined for the AI model and for anything that leaves the runner. A few details of the integration are worth calling out:
- Entropy + bigram detection, not a catalog of secret-format regexes: their docs describe it as "Shannon entropy analysis combined with bigram frequency detection"—the bigram check is what separates an actual secret from a long, high-entropy code identifier that just happens to look similar. (PII-Shield does support a regex whitelist and optional custom patterns; what it doesn't do is rely on a built-in list of known key formats.)
- Hash fields have to be carved out before sanitization: a bundle's own integrity hashes (
content_hash,chain_hash,root_hash) are high-entropy by construction—exactly what an entropy detector is built to flag. GuardSpine Code extracts those fields before running PII-Shield and reinjects them afterward, so the cryptographic structure survives sanitization intact. - One salt, org-wide: the same HMAC salt has to be used by every service that produces or consumes their bundles. Their docs are explicit that using different salts per service "breaks cross-bundle correlation and audit trail consistency"—the salt is meant to live in a shared secret manager, not be re-generated per integration.
- Local or remote, by config: PII-Shield can run in-process via WASM (
pii_shield_mode: local) or against a hosted endpoint (pii_shield_mode: remote)—teams in air-gapped or regulated environments tend to run it local; others point it at an internal endpoint instead.
It's a narrower use case than "AI agent logging" in general—this is specifically about keeping secrets out of PR comments, evidence bundles, and SARIF output in a code-review pipeline. But the underlying shape of the problem—sanitize before it reaches an AI model or long-term storage, without breaking the integrity guarantees you've built everything else on—shows up well beyond code review.
When This Approach Doesn't Fit
In-process deterministic hashing is powerful for audit logs, but it's not a universal solution. Here's when you might need a different approach:
- You need to restore the original value: If your agent must show the user their own email or phone number in the output, irreversible hashing won't work. You'd need reversible redaction or a gateway that strips PII only before external storage.
- You need ML-based NER detection: PII-Shield finds secrets through Shannon-entropy and bigram-frequency analysis, with sensitive-key matching and a configurable regex whitelist—but no built-in NER. It catches high-entropy secrets and structured PII well, yet has no model of names in free-form text. For unstructured prose with proper names, consider an ML-based NER model (higher CPU, but more accurate).
- You want enterprise compliance dashboards out-of-the-box: PII-Shield is a library/sidecar. It doesn't provide dashboards, reporting, or audit UIs. If you need those, consider a full compliance platform (higher cost, but more features).
- You operate across disconnected environments: Deterministic hashing requires a shared salt. If your agents run in isolated networks without a shared secret, you can't correlate hashes across environments. A centralized gateway might be simpler in that case.
Try It Yourself
You can run PII-Shield as an in-process WASM module in Node.js or Python. Here's a quick example:
// Install: npm install @pii-shield/wasm
import { initWasm, redact } from '@pii-shield/wasm';
const wasmModule = await initWasm();
const agentLog = {
action: "retrieve_customer",
customer_email: "alice@company.com",
timestamp: "2026-06-19T10:30:00Z"
};
const sanitized = redact(
JSON.stringify(agentLog),
{ salt: "your-governance-salt" }
);
console.log(sanitized);
// Output:
// {
// "action": "retrieve_customer",
// "customer_email": "[HIDDEN:60beb2]",
// "timestamp": "2026-06-19T10:30:00Z"
// }
The hash is deterministic: the same salt and email always produce the same hash. Use this to correlate events across your audit trail without storing raw data.
⚠️ Use the same salt across every service that needs to correlate events—a different salt per service breaks cross-log correlation.
Next Steps
1. Evaluate your use case: Do you need reversible redaction (user-facing disclosure) or audit-trail hashing (correlation without disclosure)?
2. If you choose hashing: Grab the PII-Shield repository and try the WASM module in your agent framework.
3. Set a salt: Use a strong, random string as your salt. Store it securely (Kubernetes Secret, HashiCorp Vault, etc.). Share it across agents that need to correlate events.
If you're building something similar to a PR-review pipeline, see how GuardSpine Code wires PII-Shield into theirs.
Common questions
Ready to build compliant AI agent logs?
Check out the PII-Shield repository on GitHub, explore the WASM API, and join the community. If you find it useful, drop a star!