Agent privacy as a data-flow architecture
A privacy policy describes intent. A privacy data plane decides what an agent can see, disclose, and remember — and leaves reconstructable evidence for every decision.
Problem
Most agent privacy programs start with documents and endpoints: a privacy notice, provider settings, perhaps a PII filter before the model call. That treats privacy as a property of one request. Agents create a continuing data path across context assembly, tool arguments, intermediate values, caches, and long-term memory. The leak happens at the boundary nobody modeled.
The category error is treating privacy as content moderation. The real questions are structural: which fields entered model context, what crossed into a tool provider, what became persistent memory, under whose scope, for which purpose, and until when? If the system cannot answer those questions from its runtime data path, the policy document is a statement of aspiration rather than a control.
Constraints
The build is deliberately local and deterministic. Personal data must be minimized before context assembly, not merely redacted from logs afterward. Tool adapters must receive an allowlisted projection rather than the agent's full working state. Every memory write must carry subject scope, purpose, provenance, and retention at creation time. Audit evidence must explain each decision without copying raw PII into the ledger. Most importantly, the model may not decide whether its own access is lawful.
Decisions
- Labels travel with fields. The build rejects untyped dictionaries passed between agent components. Every field carries a privacy class, subject scope, purpose, provenance, and retention category, so policy is evaluated on typed data rather than guessed at the final hop.
- Each boundary receives a projection, not shared context. The context guard keeps required public and internal values, replaces personal data with a stable subject-scoped token, denies secrets, and omits fields unrelated to the declared purpose. The same minimization principle drives tool egress: the adapter receives only fields and classes named in its contract. This makes the argument in agent privacy is a data-flow problem load-bearing.
- Memory expires unless policy retains it. The memory schema keys records by subject and purpose and assigns expiry when the write occurs. A preference receives a bounded 30-day TTL; sensitive identifiers are refused. Scope and retention are storage properties, not reminders in a prompt — the governance-first order argued in agent memory needs governance before embeddings.
- The ledger records decisions, not payloads. Every boundary appends field names, privacy classes, actions, reasons, principal, purpose, and policy digest to one hash-chained SQLite ledger. Raw field values do not enter the audit stream. Replay reconstructs what crossed each boundary; verification detects a mutated decision.
- Deterministic policy remains authoritative. The build rejects model-based privacy judgment on the load-bearing path. A production classifier may eventually add probabilistic PII recognition, but allow, transform, and deny remain executable policy decisions. This follows the same security boundary as treating prompt injection as a permissions problem.
Outcome
The working Python reference implementation proves all three boundaries in one deterministic support-agent run. Model context contains the issue and account tier, a tokenized email, no API key, and no irrelevant debug note. The ticket adapter receives only its declared case_id and summary. Memory retains a language preference within one subject scope and TTL while refusing a government identifier. Four ledger events reconstruct the sequence, and hash-chain verification passes.
The artifact includes ten behavioral tests, strict typing and lint checks, a verbose offline demo, and five self-checking scenarios for context minimization, tool-call egress, scoped memory retention, cross-subject isolation, and audit tamper detection. No network, API key, live model, or tool provider is required. The full source is public at github.com/Dhristhi/agent-privacy-dataflow.
What you can run
git clone https://github.com/Dhristhi/agent-privacy-dataflow
cd agent-privacy-dataflow
uv sync --extra dev
uv run pytest -q
uv run python -m privacy_demo.demo
for s in scripts/scenario_*.py; do uv run python "$s"; done
The honest caveat: this proves the architecture and its enforcement seams, not regulatory certification or production PII-recognition recall. Expired SQLite rows are excluded from reads but require a production deletion or compaction path for physical erasure. The hash chain is tamper-evident, not non-repudiation against an administrator who can rewrite the entire database. And a real deployment still needs organization-specific purposes, retention schedules, legal bases, and measured classifier recall. The narrower claim holds: privacy can be made an executable property of the data path rather than a promise made beside it.