Skip to main content
Engram provides defense-in-depth privacy protection by stripping sensitive content at two layers: the plugin layer (before data leaves the process) and the store layer (before any database write).

Privacy Tags

Wrap sensitive content in <private>...</private> tags to redact it from memory:
Becomes:
The sensitive content is permanently removed. Once stripped, it cannot be recovered from Engram’s database.

What Gets Redacted

Any content inside <private> tags is replaced with [REDACTED]:
  • API keys and secrets
  • Passwords and tokens
  • Personal identifiable information (PII)
  • Email addresses, phone numbers
  • Database connection strings
  • Any sensitive configuration values

Two-Layer Defense

Engram strips privacy tags at two independent layers to ensure sensitive data never reaches the database:

Layer 1: Plugin Layer (TypeScript)

For agents using Engram plugins (OpenCode, Claude Code), privacy tags are stripped before data is sent to the HTTP API. OpenCode Plugin (engram.ts):
When it runs:
  • Before sending observations to POST /observations
  • Before sending prompts to POST /prompts
  • Before any HTTP request leaves the plugin
Why? Defense in depth. Even if the store layer fails, sensitive data never leaves the process.

Layer 2: Store Layer (Go)

The SQLite store layer strips privacy tags before any database write, regardless of how the data arrives (HTTP API, MCP stdio, CLI). Implementation (internal/store/store.go):
When it runs:
  • Inside AddObservation() — strips title and content before INSERT
  • Inside UpdateObservation() — strips title and content before UPDATE
  • Inside AddPrompt() — strips content before INSERT
  • Inside passive capture — strips learning items before save
Why? Guarantees that the database never contains sensitive data, even if called directly via API or CLI without a plugin.

Pattern Details

Regex Pattern

Flags:
  • (?i) — Case-insensitive (matches <PRIVATE>, <Private>, etc.)
  • (?s) — Dot matches newlines (supports multiline content)
  • .*? — Non-greedy match (stops at first </private>)

Supported Variations

All of these work:

Nested Tags

The regex is non-greedy, so nested tags are handled correctly:
Becomes:

Usage Examples

Protecting API Keys

Stored as:

Protecting Connection Strings

Stored as:

Protecting User Data

Stored as:

When to Use Privacy Tags

Always Redact

  • API keys, tokens, secrets
  • Passwords, passphrases
  • Database credentials
  • Personal emails, phone numbers
  • Social Security Numbers, credit cards

Consider Redacting

  • Internal URLs with auth tokens
  • Server hostnames or IPs
  • User-specific identifiers
  • Proprietary business logic
  • Sensitive configuration values
Team collaboration consideration: If you’re using Git Sync to share memories with your team, privacy tags prevent sensitive data from being committed to the repository.Always wrap secrets in <private> tags before saving to memory.

MCP Tool Integration

When calling MCP tools directly (without a plugin), privacy tags are still stripped at the store layer:
The observation is saved with:

Verification

You can verify that privacy tags are working by:

1. Check the TUI

Navigate to the observation and verify that sensitive content shows [REDACTED].

2. Check the Database Directly

Verify that the content contains [REDACTED] instead of the sensitive value.

3. Export and Inspect

Should return nothing — no <private> tags should appear in the export.

Best Practices

1

Use privacy tags proactively

Don’t wait until you see a secret in memory. Wrap it in <private> tags before saving.
2

Tag entire values, not just parts

❌ Bad: API_KEY=abc<private>123</private>xyz✅ Good: API_KEY=<private>abc123xyz</private>
3

Use privacy tags in prompts too

When saving user prompts with mem_save_prompt, wrap sensitive content:
4

Review memories before syncing

Before engram sync, review recent memories in the TUI to ensure no secrets leaked through:

Limitations

What privacy tags do NOT protect:
  1. Secrets in file paths: If you save Fixed bug in /home/user/.ssh/id_rsa, the path is stored as-is. Wrap it: Fixed bug in <private>/home/user/.ssh/id_rsa</private>
  2. Secrets in tool output: If an agent runs a command that outputs secrets to its context, those won’t be automatically redacted unless the agent wraps them in privacy tags before saving.
  3. Inference from context: If you write “API key ends in 123”, an attacker with access to your memory could narrow down the key. Be mindful of indirect leakage.

Git Sync

Share memories safely with privacy tags

MCP Tools

Save memories with privacy protection

Export/Import

Export memories with redacted content

Architecture

Learn about Engram’s security layers