How Agentmemory's Privacy Filter Protects Sensitive Information

Agentmemory's privacy filter protects sensitive information by automatically redacting personally identifiable information (PII) through the stripPrivateData function before any data reaches the persistent store or API responses.

Agentmemory is an open-source memory system designed for AI agents that require persistent state management without compromising user privacy. The agentmemory privacy filter implements a defense-in-depth strategy by processing every payload through the mem::privacy function before persistence. According to the rohitg00/agentmemory source code, this ensures that sensitive data never touches the SQLite-backed state store or external interfaces.

How the Privacy Filter Works

The privacy filter operates as a mandatory middleware layer registered in src/index.ts. When invoked, it executes the core stripPrivateData routine defined in src/functions/privacy.ts to sanitize data structures recursively.

The Six-Step Redaction Process

The stripPrivateData function implements a deterministic pipeline that examines every field in a data structure:

  1. Input Validation: The function validates that incoming payloads are objects or arrays, creating shallow copies to avoid mutating caller references. This prevents accidental side effects while ensuring consistent data handling.

  2. Recursive Traversal: All enumerable fields are visited recursively using depth-first processing. This guarantees that nested objects and arrays receive the same scrutiny as top-level properties.

  3. Pattern Matching: For each string value, the filter applies specific regular expressions to detect:

    • Email addresses: /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i
    • URLs: /https?:\/\/[^\s/$.?#].[^\s]*/i
    • Phone numbers: /\+?\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{1,4}[-.\s]?\d{1,9}/
    • Credit card numbers: /\b(?:\d[ -]*?){13,16}\b/
    • IP addresses: /\b\d{1,3}(?:\.\d{1,3}){3}\b/
  4. Redaction: Matching substrings are replaced with the [REDACTED] placeholder. This preserves the original data shape and types while ensuring no raw PII persists.

  5. Allowlist Handling: Fields specified in an optional allowlist bypass redaction. This preserves essential non-PII metadata such as internal IDs while maintaining privacy protection.

  6. Audit Logging: The recordAudit function logs which fields were stripped, creating traceability for compliance without exposing the original sensitive content.

Critical Integration Points

The filter creates a hard barrier at two architectural boundaries:

  • Incoming API calls: In src/functions/observe.ts, request bodies pass through stripPrivateData before any kv.set operation writes to the state store.
  • Outgoing responses: When retrieving memories via mem::view, the filter processes data before transmission, preventing accidental leakage from persisted logs.

Implementation Examples

Direct SDK Usage

Developers can invoke the privacy function directly through the III SDK:

import { sdk } from "iii-sdk";

const result = await sdk.trigger({
  function_id: "mem::privacy",
  payload: {
    notes: "Contact me at [email protected] or +1-555-123-4567",
    url: "https://my-secret-site.com",
    internal_id: "user_12345"
  },
});

// Result:
// {
//   notes: "Contact me at [REDACTED] or [REDACTED]",
//   url: "[REDACTED]",
//   internal_id: "user_12345"
// }

Automatic Incoming Data Protection

The observer pattern automatically sanitizes inputs before persistence:

// src/functions/observe.ts (conceptual implementation)
import { stripPrivateData } from "./privacy.js";

sdk.registerFunction("mem::observe", async (data) => {
  const safePayload = stripPrivateData(data);
  await kv.set("memory_key", safePayload);
  return { success: true, sanitized: true };
});

Retrieval Sanitization

When reading from the store, the filter ensures safe output:

// Implementation pattern from the codebase
import { stripPrivateData } from "./privacy.js";

const rawMemory = await kv.get(memoryId);
const safeResponse = stripPrivateData(rawMemory);
return { status_code: 200, body: safeResponse };

Security Architecture Benefits

The filter provides several security-by-design advantages:

  • Deterministic Redaction: The same regex patterns apply universally across all endpoints, ensuring consistent behavior regardless of the data source.
  • Stateless Implementation: The function operates without external service dependencies or secrets, eliminating credential leakage risks.
  • Library-Level Enforcement: Because the filter runs before persistence and network layers, downstream components cannot accidentally bypass protection.

Source File Reference

Key implementation files in the rohitg00/agentmemory repository:

Summary

  • Agentmemory implements privacy protection through the stripPrivateData function in src/functions/privacy.ts, which applies regex-based redaction to emails, URLs, phone numbers, credit cards, and IP addresses.
  • The filter operates recursively on all data structures, replacing sensitive matches with [REDACTED] while preserving object shape and optional allowlisted fields.
  • Integration points in src/functions/observe.ts and retrieval handlers ensure PII never reaches the SQLite state store or API responses.
  • The stateless, deterministic design provides universal protection without depending on external services or secrets.

Frequently Asked Questions

What specific types of PII does the agentmemory privacy filter detect?

The filter detects emails, URLs, phone numbers, credit card numbers, and IP addresses using specific regular expressions. These patterns match common formats including international phone numbers with various separators and standard IPv4 addresses.

Can I whitelist specific fields to prevent over-redaction?

Yes. The stripPrivateData function accepts an optional allowlist parameter containing field names that should bypass redaction. This preserves essential metadata like internal IDs while maintaining protection for user-generated content.

Where exactly does the privacy filter run in the data lifecycle?

The filter executes at two critical points: before writing to the persistent store (in src/functions/observe.ts) and before returning data to clients. This creates a hard boundary that prevents PII from entering the database or leaking through API responses.

Is the privacy filter tested against edge cases and false positives?

Yes. The repository includes test/privacy.test.ts, which exercises the filter against various PII formats and edge cases. This automated validation ensures that regressions in pattern matching are caught during development.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →