English · 简体中文
Keep secrets local. Keep agents working.
A protocol-aware local privacy proxy for agents that use cloud LLMs.
Replace detected sensitive text before upload, then validate and restore handles in local response text and structured tool arguments.
Quick Start · How It Works · API Formats · Security · Docs
Requires Python 3.11 or newer.
git clone https://github.com/HKUDS/PrivacyFlow.git
cd PrivacyFlow
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e .
privacyflowTo install a tagged release into an existing environment instead:
python -m pip install "privacyflow @ git+https://github.com/HKUDS/PrivacyFlow.git@v0.1.0"Then open http://127.0.0.1:8765/ui/ and:
- add and enable an upstream provider;
- turn on the PrivacyFlow master switch;
- open Agent quick connect;
- choose an Agent and model, then click Quick connect.
PrivacyFlow validates the Agent's native protocol before changing its user-level configuration. Restore previous configuration returns the configuration to its exact pre-connection state. The built-in connectors cover Codex, Claude Code, DeepSeek Harness, and nanobot; other Agents can connect through PrivacyFlow's standard local endpoints.
See detailed setup and migration for manual endpoints, snapshot behavior, and legacy APG migration.
When users rely on agents for real work, they often need those agents to read
.env files, logs, configuration, source code, and tool arguments. Sometimes,
they must directly provide the agent with API keys, passwords, personal
information, private paths, or other sensitive values for the task. These values
may be discovered by the agent or intentionally supplied by the user. Either way,
the goal is for the agent to use them, not for the cloud LLM behind it to receive
them in plaintext. Sending the original values to a cloud model means trusting
every provider and intermediary that handles the request. Data policies vary;
some services may retain or reuse requests for model improvement or training.
Unofficial or personal API relays make retention, access, and reuse even harder
to assess: whoever operates the relay can log, resell, or reuse the plaintext
that agents send. Moving entirely to local models often means either investing
substantial compute resources or accepting less capable models.
Data use depends on the product, account type, and privacy settings. On several consumer services, model-improvement data use remains enabled until the user turns it off; some safety-review and feedback exceptions still apply after an opt-out. The providers' own documentation also warns users not to submit sensitive or confidential information.1
| Provider | Official policy |
|---|---|
| OpenAI | ChatGPT and Codex content may be used for training unless the user opts out. OpenAI also says not to share sensitive information in conversations. Data-usage policy · ChatGPT privacy guidance |
| Anthropic | Claude consumer chats and coding sessions may be used when Model Improvement is enabled, feedback is submitted, or a conversation is flagged for safety review; flagged conversations may still be used for internal safety-model training after the general setting is disabled. Anthropic explicitly says: “We encourage our users not to use our products and services to process personal data.” Consumer policy · Commercial policy |
| When Gemini Keep Activity is on, chats, files, screens, and photos may be used to improve services, including training generative AI models, with some data reviewed by humans. Google warns users not to enter confidential information they would not want a reviewer to see or Google to use for improvement. Turning Keep Activity off prevents future chats from being used for general model training unless feedback is submitted, though chats are still retained for 72 hours for service and safety purposes. Gemini Apps Privacy Hub | |
| DeepSeek | DeepSeek's privacy policy permits operational and statistical analysis of dialogue content to improve algorithmic models, service intelligence, and understanding of user input. Its user agreement separately tells users not to enter their own or other people's sensitive personal information; continuing to use the service constitutes acceptance of the policy rather than a separate training opt-in. Privacy policy · User agreement |
These policies do not mean that every provider trains on every request. But the providers' own warnings make the practical boundary clear: users should not assume that a cloud LLM is an appropriate place for plaintext personal data or secrets. PrivacyFlow enforces that boundary locally instead of relying on every user, agent, setting, and intermediary to handle sensitive values correctly.
The following public reports have not been independently confirmed by PrivacyFlow and do not by themselves prove a specific breach. Unexpected model output may also result from hallucination, context contamination, client bugs, or tool input. Reports about unofficial routers describe a different failure: the intermediary itself logging or reselling plaintext traffic. They nevertheless illustrate a practical problem: once sensitive data is sent upstream, users lose control over which systems process it, who can retain it, and whether it might reappear under unexpected conditions.
| Platform | Public report |
|---|---|
| Claude | After asking Claude to organize local files and run a Git command, a user received an unrelated comparison of layoff candidates containing roles, salaries, and skills. View the original post |
| Claude Code | A user reported that unrelated production-server connection details and credentials appeared in a session, after which the Agent connected to the server and modified a third-party database. View the issue |
| ChatGPT | Multiple users reported receiving responses unrelated to files they had uploaded. One response allegedly contained a document uploaded by a local lawyer. View the discussion |
| Gemini | After uploading audio for transcription, a user received an unrelated business-meeting transcript containing names, corporate email addresses, contracts, and document links. The poster said some of the people and details could be verified. View the original post |
| Third-party LLM router | A researcher reported buying a multi-terabyte traffic dataset from a popular Chinese LLM router. The dump still contained SSH keys, VPN configurations, Aliyun keys, and GitLab tokens associated with government organizations and major companies. View the original post |
PrivacyFlow does not need to assume that every anomaly is a data breach. It replaces values detected in supported textual fields before a request leaves the device. If an upstream service experiences incorrect routing, logging, context contamination, or another unexpected failure, those replaced values appear as placeholders rather than their original literals.
Exposing a secret can also interrupt the task itself. A safety-aligned model may warn the user to revoke a credential, refuse to continue, or avoid using the value—even when the intended operation is legitimate. The user is then forced to replace, paste, or manage sensitive values manually, adding friction and more human-in-the-loop work.
PrivacyFlow keeps a detected literal value local and gives the model a stable placeholder instead. The model only needs to know that a secret exists and where it should be used; it rarely needs to know the secret itself. PrivacyFlow verifies the handle and restores it in two protocol-defined response classes: ordinary client-visible text and recognized structured tool-call arguments. These are field classifications, not tool authorization or execution approval.
| Detect locally | Protect before upload | Restore locally |
|---|---|---|
| Credentials, PII, local paths, and optional high-entropy findings in scanned text fields | Signed placeholders and stable path aliases replace detected values | Verified values reappear in client-visible answers and recognized structured tool arguments |
PrivacyFlow ships with safe built-in detector pipelines and also exposes local, revisioned detector configuration. In the WebUI you can copy a preset, order and toggle modules, add deterministic or local-model detectors, choose fail-open or fail-closed behavior, dry-run the saved configuration, and activate it without restarting the gateway. Placeholder integrity and streaming-boundary safeguards remain fixed and cannot be disabled by a custom detector configuration.
- Transparent protection — the model works with stable placeholders; the local Agent client receives validated values back without manually decoding them.
- Local control plane — provider credentials are configured locally and used only for upstream authentication rather than returned to the Agent; mappings, detector configurations, audit records, and optional models stay on the machine.
- Defense against placeholder spoofing — materialization checks signature, session, workspace, mapping state, expiry, revocation, and response-field class.
- Inspectable behavior — dry-run detector configurations, review protected mappings, and audit every replacement and restoration without storing raw values in logs.
PrivacyFlow handles both directions locally. Before a request leaves the device, it
walks supported textual JSON fields, detects sensitive values, and replaces
them with signed placeholders or stable path aliases. When the model response
returns, PrivacyFlow treats ordinary response text as local_user and recognized
structured tool-call argument fields as local_tool, validates handles, and
restores their local mappings before returning the response to the Agent. These
labels describe protocol locations; PrivacyFlow does not approve or execute the tool.
Given this local input:
Email alice@example.test, open /Users/alice/private/project,
and use key sk-example-not-a-real-key.
the model sees:
Email <PF:v1:pii:...>, open /workspace/project-hash,
and use key <PF:v1:secret:...>.
After the model returns the placeholders, the client-visible local result is:
Email alice@example.test, open /Users/alice/private/project,
and use key sk-example-not-a-real-key.
If the model needs a protected value, it keeps the placeholder unchanged. PrivacyFlow verifies the placeholder and restores the original in ordinary local response text or a recognized decoded structured tool argument. A later request is scanned again before it can reach the model.
This contract covers supported textual JSON and SSE fields. Protocol identifiers
and opaque multimodal payload fields such as image_url, file_data, audio, and
image blocks are deliberately passed through unchanged to avoid corrupting the
wire format. PrivacyFlow therefore does not claim complete request-wide or multimodal
data-loss prevention.
On Windows PowerShell, activate the environment with
.venv\Scripts\Activate.ps1. The first start creates
.privacyflow/launcher.json, a random local Agent API key, and a signing secret.
PrivacyFlow then serves its loopback WebUI at http://127.0.0.1:8765/ui/.
Open the WebUI and:
- add a named upstream configuration;
- enter the provider Base URL and API key;
- save and enable the configuration;
- turn on the PrivacyFlow master switch.
Provider keys are written to the local launcher configuration with mode 0600
where supported and are never returned by the management API.
Every connection exposes the Chat Completions, Responses, and Anthropic Messages
entrypoints by default. PrivacyFlow selects the matching native upstream route from the
incoming endpoint and never converts between formats. If the provider does not
support that format, PrivacyFlow returns the actual upstream error.
The WebUI's Agent quick connect view configures installed Codex, Claude Code, DeepSeek Harness, and nanobot user-level instances. PrivacyFlow refreshes the upstream model catalog and performs a real probe using the Agent's native protocol before writing any file. DeepSeek Harness uses endpoint configuration; PrivacyFlow does not install a native dsh plugin.
Each Agent receives a dedicated local key. PrivacyFlow snapshots complete configuration files before connection. Restore previous configuration writes back the exact original bytes and permissions, or removes a file that did not previously exist. If a target already contains a reserved provider, preset, or environment key, the first attempt lists the affected paths and asks for explicit migration confirmation. PrivacyFlow only replaces the files after confirmation, and saves the complete pre-connect snapshot first; cancel leaves the configuration untouched. If a file changed after connection, PrivacyFlow requires confirmation and saves the current version as a safety backup first.
The Overview connection strip remains available for manually connecting other Agents with PrivacyFlow's Base URL and primary local API key.
Copy the Base URL and generated local API key from Agent connection in the WebUI. Select the model in the Agent itself—PrivacyFlow deliberately does not own model selection.
| Agent request format | PrivacyFlow Base URL |
|---|---|
| OpenAI Chat Completions | http://127.0.0.1:8765/v1 |
| OpenAI Responses | http://127.0.0.1:8765/v1 |
| Anthropic Messages | http://127.0.0.1:8765 |
Note
PrivacyFlow does not convert between Chat Completions, Responses, and Anthropic Messages. The Agent and upstream must support the same request format. To manage and quickly switch connection profiles across different Agents and model providers, consider using CC Switch alongside PrivacyFlow. CC Switch manages configurations; it is not PrivacyFlow's protocol conversion layer. Agent quick connect only writes model endpoints, model names, and local credentials; tool permission, tool execution, and local session logs remain the Agent's responsibility.
The repository-level ./privacyflow wrapper is available for development
checkouts. The old apg command remains a migration-release compatibility alias.
If an existing installation still uses .apg/, run privacyflow migrate once.
It copies the launcher, database, audit log, detector state, local-model state,
and Agent connector transactions into .privacyflow/, verifies the copy, and
upgrades the stored namespace while preserving valid custom detector configurations.
Malformed or unsupported detector state safely falls back to the built-in defaults
at startup rather than preventing PrivacyFlow from launching.
A separate, hash-verified, read-only backup copy is created at
.apg.legacy/<timestamp>/, including the untouched legacy detector file. The
original .apg/ tree remains in place and untouched: migration never moves,
edits, or deletes it. Remove the original only after checking the migrated state
and choosing to do so. Migration never edits shell startup files. During this
release, APG_* environment variables, legacy
X-APG-* headers, and <APG:v1:...> placeholders remain readable; PF_*,
X-PF-*, and <PF:v1:...> are the canonical forms. The APG command,
environment, directory, header, route, error-code, and placeholder fallbacks
are scheduled for removal in the next major release.
PrivacyFlow accepts three API formats:
| Format | Local endpoint |
|---|---|
| OpenAI Chat Completions | POST /v1/chat/completions |
| OpenAI Responses | POST /v1/responses |
| Anthropic Messages | POST /v1/messages |
PrivacyFlow forwards each request in its original API format and does not translate it into another protocol.
- built-in and custom ordered pipelines for credentials, API keys, personal information, local paths, entropy checks, and optional local models;
- a workspace-level exact-string watchlist that redacts registered values in every detector configuration, including the first request;
- session-bound signed placeholders and lifecycle-aware mappings;
- streaming-safe replacement and restoration;
- structured tool-argument materialization;
- per-module fail-open/fail-closed handling while placeholder-integrity safeguards remain fixed.
Risk levels are audit metadata. They do not change how protected data is
replaced; enforcement remains in the policy, mapping, placeholder, and
materialization layers. A detector finding whose suggested action is block
rejects the complete upstream request with a non-retryable PF_REQUEST_BLOCKED
error. Downlink responses still fold such values instead of forwarding them as
placeholders.
- one-click PrivacyFlow master switch;
- multiple named upstream configurations;
- all three native API entrypoints on every upstream configuration;
- random local Agent API-key generation;
- bilingual English/Chinese WebUI;
- detector presets, ordering, enablement, duplication, dry runs, and advanced settings;
- protected-value review, revocation, and retention controls;
- replacement and restoration audit views;
- responsive desktop and mobile management UI.
The Local model management page accepts a Hugging Face repository/URL or an existing local directory. Add and prepare performs:
inspect → prepare isolated runtime → download → real inference verification
PrivacyFlow does not install PyTorch into its own environment. It creates a versioned
runtime under .privacyflow/runtimes/, stores managed model data under .privacyflow/models/,
and communicates with a local worker over private JSON Lines. Remote custom code
is disabled, and local model directories remain read-only.
PrivacyFlow protects detected values in supported textual fields of traffic that actually passes through PrivacyFlow. Its scope is intentionally narrower than a DLP, sandbox, or endpoint security product.
| PrivacyFlow does | PrivacyFlow does not |
|---|---|
| Detect and replace sensitive values before upstream transmission | Stop an Agent process from reading local files directly |
| Let Agent clients use a local key instead of the provider key, and never return provider keys in management responses | Approve tool calls or control the Agent's permissions |
| Validate signed placeholders before local restoration | Control destinations contacted by locally executed tools |
| Keep mappings, configuration, models, and audit state local | Replace a secrets manager, network policy, EDR, or OS sandbox |
| Record sanitized replacement/restoration operations | Make a remotely exposed management endpoint safe |
Scanning is limited to supported textual protocol fields. Opaque multimodal payloads and protocol identifiers pass through unchanged. Structured tool-call arguments are classified by their response shape; PrivacyFlow does not verify that the named tool is local, permitted, or safe before restoring a valid handle.
The management API and WebUI intentionally have no application-layer
authentication. They must remain loopback-only. Never publish port 8765,
reverse-proxy the management routes, or bind PrivacyFlow to an untrusted network.
A prompt-injected model can still request a local tool call that sends a materialized secret to an attacker. The Agent harness must gate tool execution and outbound destinations.
Read the full design and threat model, WebUI security notes, and security policy.
The WebUI is the recommended configuration path.
Advanced environment configuration
export PF_UPSTREAM_API_KEY='provider-key'
export PF_UPSTREAM_BASE_URL='https://api.openai.com'
export PF_UPSTREAM_PROTOCOL='openai_chat_completions'
export PF_SIGNING_SECRET='long-random-local-secret'
export PF_LOCAL_API_KEYS='long-random-agent-key'
export PF_PORT=8765PF_UPSTREAM_PROTOCOL accepts:
openai_chat_completionsopenai_responsesanthropic_messages
Useful optional settings:
export PF_ADMIN_ENABLED=true
export PF_PII_MODE='pseudonymize' # pseudonymize, redact, or allow
export PF_GC_INTERVAL_SECONDS=60
export PF_AUDIT_LOG_MAX_BYTES=16777216
export PF_AUDIT_LOG_BACKUPS=5
export PF_HISTORY_RETENTION_SECONDS=2592000See config/example_policy.yaml for policy
settings.
Local state defaults to .privacyflow/:
| Path | Contents |
|---|---|
launcher.json |
Named upstream profiles, provider keys, local Agent key |
state.sqlite3 |
Protected-value mappings and operation records |
audit.jsonl |
Sanitized audit events, rotated at 16 MiB with five private backups by default |
detector-control.json |
Revisioned detector configurations, template module overrides, the global protection toggle, and the workspace exact-string watchlist |
agent-connections.json |
Agent quick-connect snapshots, dedicated connector keys, and restore transactions |
local-models.json |
Local-model catalog and validation state |
models/ |
PrivacyFlow-managed Hugging Face cache |
runtimes/ |
Isolated model runtime |
Secret-bearing files are created with restrictive permissions where supported. Provider keys and active mapping values are stored locally in plaintext rather than encrypted by PrivacyFlow. Place the state directory on encrypted storage and restrict access to the PrivacyFlow process user.
The main branch keeps the standard regression suite:
| Layer | Purpose | Command or evidence |
|---|---|---|
| Unit and API regression | Proxy, detector, mapping, stream, UI, and security behavior | pytest -m 'not integration' |
| Deterministic E2E harness | Scenario fixtures, leak assertions, and report generation | pytest e2e_agent_tests/tests/test_e2e_harness.py |
| Networked local-model integration | Isolated runtime download and real Worker inference | PF_RUN_LOCAL_MODEL_INTEGRATION=1 pytest -m integration tests/test_local_models_integration.py |
Real Claude Code / OpenCode matrices are opt-in, consume provider capacity, and are not stored in git. Keep raw artifacts and exported trajectories on the maintainer machine.
| Start here | What it covers |
|---|---|
docs/README.md |
Public docs versus maintainer-local lab notes |
docs/design.md |
Architecture, trust boundaries, placeholders, and materialization |
docs/webui.md |
Management behavior, persistence, raw-value review, and UI security |
docs/threat_model.md |
Threats, mitigations, assumptions, and residual risk |
docs/harness_integration.md |
Agent and tool-harness integration |
docs/roadmap.md |
Planned work and open design areas |
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
pytest -m 'not integration'
node --check src/gateway/webui/app.js
node --check src/gateway/webui/i18n.js
ruff check .Networked local-model integration is intentionally excluded from normal tests:
PF_RUN_LOCAL_MODEL_INTEGRATION=1 pytest -m integration \
tests/test_local_models_integration.py| Path | Purpose |
|---|---|
src/gateway/ |
Gateway, detection, storage, proxy, model worker, and WebUI |
tests/ |
Unit, API, stream, security, and WebUI regression tests |
docs/ |
Public design, operations, and threat-model docs |
examples/ |
Minimal client and security examples |
Contributions are welcome. Start with CONTRIBUTING.md, read
the CODE_OF_CONDUCT.md, and open an issue before large
architectural or API contract changes.
Please never include real credentials, protected values, private paths, or unsanitized Agent transcripts in issues or pull requests.
PrivacyFlow is licensed under the
Apache License 2.0. Bundled third-party notices are kept under
docs/vendor/.
Footnotes
-
Business and API products often have stronger default data policies than consumer products. Refer to the terms for the specific provider, product, and account. ↩