Skip to Content
DocsMemoryGDPR ops

GDPR ops

Every memory backend implements three operations for GDPR compliance:

OperationPurpose
profile(user_id=)Inspect what the agent knows about a user.
forget(user_id=, ...)Right-to-be-forgotten. Full or scoped erasure.
export(user_id=)Data-portability dump (DSAR).

These are built-in methods on the Memory protocol, not optional add-ons. Plumbing through the backend is the framework’s job.

profile(user_id=)

profile = await agent.memory.profile(user_id="alice") # MemoryProfile( # user_id="alice", # episode_count=12, # fact_count=5, # last_seen=datetime(...), # recent_sessions=["conv_42", "conv_43"], # sample_facts=[ # Fact(subject="alice", predicate="works_at", object="Acme"), # ... # ], # )

Use this in:

  • Customer support tickets (“here’s what we know about you”).
  • Internal admin tools.
  • Compliance reviews.

forget(user_id=, ...)

Full erasure of one user’s data:

await agent.memory.forget(user_id="alice")

Or scoped. Just one conversation, just data older than a date:

# Just one session await agent.memory.forget(user_id="alice", session_id="conv_42") # Just data before a cutoff from datetime import datetime, UTC await agent.memory.forget( user_id="alice", before=datetime(2025, 1, 1, tzinfo=UTC), )

What gets deleted:

  • Episodes (chat transcripts).
  • Working memory blocks.
  • Facts (in the bi-temporal store).
  • Per-user budget bucket (resets the running totals).

What does NOT get deleted automatically:

  • The audit log (immutable; legal-hold). Filter / redact at query time if you need to.
  • The runtime journal (used for replay). Drop the whole journal DB if compliance requires it.

export(user_id=)

Returns a structured MemoryExport you can serialize to JSON for a Data Subject Access Request:

export = await agent.memory.export(user_id="alice") # MemoryExport( # user_id="alice", # episodes=[Episode(...), ...], # facts=[Fact(...), ...], # blocks={"profile": "...", ...}, # exported_at=datetime(...), # ) import json payload = export.model_dump_json(indent=2)

The MemoryExport is a Pydantic model, .model_dump_json() gives you a stable serialization with ISO-8601 dates.

Auditing the request

When audit_log= is wired, GDPR ops emit audit entries with action memory_forget / memory_export. The HMAC signature covers user_id, so a tampered log loses verification.

Backend coverage

Backendprofileforgetexport
InMemoryMemory
SqliteMemory
ChromaMemory
PostgresMemory
RedisMemory

All five backends share the same surface; the implementation differs underneath but the contract is identical.

Forget is a hard delete. There’s no “soft delete” mode. Once you call forget(), the data is gone from memory. Test in a non-prod environment first; back up the underlying database if you might need recovery.

Wrap the operation in a tool so it’s auditable per-call and gated by your permissions policy:

from loomflow import Agent, tool, get_run_context @tool(destructive=True) async def gdpr_forget(target_user_id: str) -> str: """Erase all data for the given user. Requires admin approval.""" agent_ctx = get_run_context() if not agent_ctx.metadata.get("is_admin"): return "ERROR: requires admin role" await agent.memory.forget(user_id=target_user_id) return f"forgot {target_user_id}"

With permissions=StandardPermissions(mode=Mode.DEFAULT) and a Slack approval handler, every forget call requires an explicit human approval and lands in the audit log with user_id attribution.

Last updated on