Privacy & Security¶
OpenMed is built for environments where operators need to see what the system is doing, where data is stored, and which external services are in the loop. This page describes the product as it exists today, not an idealized future control plane.
Runtime boundary¶
OpenMed itself runs locally. The TUI, session files, plans, cards, workflow artifacts, and local file operations all happen on your machine.
That does not mean every clinical capability is fully offline. Many medical functions depend on remote service boundaries:
- The model or batch provider (
openmed login/OPENAI_API_KEY/ANTHROPIC_API_KEY/OPENROUTER_API_KEY/MIMO_API_KEY/DOUBLEWORD_API_KEY, or a configured custom endpoint) - OpenMed's native medical service plane for extraction, PII, de-identification, terminology, education, HCC, and RAF tooling
- User-added remote MCP endpoints
If you configure OpenRouter, prompts for general agent reasoning go to OpenRouter and on to whichever upstream provider serves the model you selected — one more hop than a direct OpenAI or Anthropic key. Review OpenRouter's privacy settings for how they handle and log your data. Provider credentials are never mixed: an OpenRouter key is only ever sent to OpenRouter, and an OpenAI or Anthropic key is never sent there.
With the MiMo provider, model requests go directly to
https://token-plan-ams.xiaomimimo.com/v1 using your tp token-plan key.
This is hosted inference; a token-plan subscription does not make the model
local or offline. Workflow helper requests use the same provider and selected
model. MiMo does not borrow another provider's credentials.
Doubleword real-time, Responses and Batch requests send their input to
https://api.doubleword.ai/v1 and to the infrastructure serving the selected
model. OpenMed stores the staged input and downloaded output/error JSONL under
~/.openmed/batches/ with owner-only permissions. It never stores the key in
that job record. Individual Responses request/output snapshots are stored under
~/.openmed/responses/ with owner-only permissions. Direct JSON/JSONL input is
not automatically de-identified, and TUI PHI mode does not transform it.
Responses background jobs retain remote state for retrieval. See
Doubleword before
submitting sensitive data.
OpenMed does not assume every task belongs on the same remote boundary. General agent reasoning uses the configured model provider, while extraction, PII, de-identification, terminology, HCC, and RAF paths can run on dedicated protected medical-service planes. This split is designed to improve control, throughput, and cost efficiency for sensitive or high-volume clinical processing. The actual privacy and compliance posture still depends on where those services are hosted and governed.
Approval And Review Model¶
OpenMed does not stop for a modal approval before every tool call.
What happens today:
- Deterministic workflows use a separate draft/finalize lifecycle, where final writes require an explicit host action plus a verified immutable draft snapshot
- Final workflow bundles are staged privately and committed atomically only to a new, empty, or matching OpenMed-owned output directory; protected state and arbitrary nonempty directories fail closed
- Approval dialogs for approval-gated tools such as
edit_fileare currently wired on the OpenAI SDK path - Read/search/extraction tools can run without a modal approval step, but their execution is still surfaced in the TUI with plans, tool-call messages, and results
If you need a stricter approval policy than that, the current docs should not imply you already have it.
Clinical file review¶
Start with the Clinical NLP guide for examples, redaction methods, language controls, PDF/image drafts and resumable batches.
For dedicated redaction, give deidentify_text the source file_path and requested
output_path directly. The tool reads supported content internally, sends it to the
configured NLP service, and returns counts, status and the output path. Reading
the raw file into the conversation first can disclose it to the chat model.
File privacy is off by default. Select its mode with a host command:
| Command | Effect |
|---|---|
/privacy-chat off |
Disable file privacy restrictions. Prompts do not turn them on. |
/privacy-chat on |
Activate restrictions immediately. /privacy-chat is a shorthand. |
/privacy-chat auto |
Clear any active restriction and wait for a recognized file privacy request. |
You can change modes in the same session after the current turn finishes or stops.
The command alone changes the setting without sending a model request. To also
send a request, append it: /privacy-chat on Deidentify /path/note.txt. The older
/privacy-chat Deidentify /path/note.txt form still enables privacy and sends the
request. Attachments and file aliases are retained.
Only opt-in auto mode uses local phrase recognition. Familiar explicit prompts
such as “Deidentify /path/note.txt” and “Mask personal info” with an attached file
activate the restriction. Actions such as "extract" must directly refer to personal
identifiers. Extracting clinical entities and mentioning patient identifiers
elsewhere in a report request does not activate it. Recognition does not cover
every language or wording; select on when it misses a request. Once triggered,
auto stays active across follow-ups until you select off or reselect auto.
Once active, the host allows only inspect_file, deidentify_text, extract_pii,
deidentify_batch and update_plan from its trusted built-in implementations.
General readers, code execution, external tools and provider built-ins are blocked,
including guessed tool calls and generic auto-approval. Attachments reach the chat
model as paths only. The setting persists across follow-ups, model changes, session
resume and forks, including whether auto has already activated. off restores
the tools allowed by the other session controls; it does not change PHI or access
mode. A fresh conversation with /clear starts with file privacy off. Ordinary
model requests and SDK history resets cannot release an active restriction.
SDK applications select SDKConfig(file_privacy="off") (the default),
SDKConfig(file_privacy="on") or SDKConfig(file_privacy="auto"). The legacy
SDKConfig(file_privacy_mode=True) opt-in still means on. Existing saved sessions
with an active legacy restriction reopen with it on; sessions without a setting
start off. Unknown saved modes fall back to off; an actual legacy boolean true
still restores the restriction. Malformed legacy flags do not enable privacy.
This restriction covers subsequent tool dispatch and attachment payloads. It does not scrub raw text pasted into a prompt, earlier conversation content or existing system instructions, and cannot undo earlier reads or tool side effects. A tool already running when the restriction activates has its later result, exception and progress withheld. Global FULL, DEID and STRICT modes remain separate controls. The dedicated privacy tools still send source content to the configured NLP service.
The v2 clinical profile accepts automatic or explicit language (de, DE,
de-DE), patient/clinician roles, redaction categories and clinical preservation.
It supports mask, remove, localized replacement, managed keyed hashing and explicit
date shifting. The full date of birth is redacted. A higher detection threshold
can leave more identifiers visible; it is not a general safety setting.
Unqualified model/language routes require explicit review_mode=true opt-in and
return needs_review. These outputs are drafts for inspection, not clinically
validated anonymization. Partial coverage and failed processing do not write an
output. Writes are atomic and owner-only; source collisions and existing outputs
are rejected unless a separate output is explicitly authorized for replacement.
In the TUI, /privacy opens a local review screen with language, method, role and
category controls. It requires FULL mode and never changes PHI mode itself. Preview
text stays outside the chat transcript and audit payload. “Save shown output”
writes that exact preview, rejects a changed source and makes no second model call.
Cancel closes an active preview request. The natural-language tool schema exposes
these controls; a tool
preview=true result is displayed in a transient local screen.
PDF, PNG and JPEG input is supported by the document preview endpoint when
the configured service has document ingestion enabled. Files are limited to
8,000,000 bytes and eight pages; the service also enforces image-pixel, OCR-word
and text limits. Set review_mode=true explicitly. The default output is .txt.
The tool sends the file bytes directly to the configured NLP service without
reading the file into the chat. It does not parse documents locally.
Default document output is an OCR text draft. OCR can
omit or change identifiers and clinical text, including entire blank-recognition
pages. Compare the draft with every source page before sharing. Document results
retain complete=false, source_content_completeness=unverified and
recognized_text_complete=true: the last flag describes processing of recognized
text only. Failures or incomplete recognized-text processing produce no file.
The original document is unchanged, including its metadata and text layers.
For a binary mask draft, use export_format="pdf" with PDF input and a .pdf
output path, or export_format="png" with PNG/JPEG input and a .png output
path. These exports require method="mask". The service burns padded whole-word
masks into fresh page images and returns an image-only PDF or lossless PNG with
no source metadata or searchable text layer. It verifies decoded pixels; the
Agent checks the returned byte hash, format, page geometry and mask receipt
against the OCR map before saving up to 32 MB atomically with owner-only access.
These checks do not establish that OCR or identifier detection found everything.
Use ocr_languages=["de"], ["en"] or ["de", "en"] (the default) to select
OCR packs. This is separate from language/lang, which controls privacy routing.
The /privacy screen exposes both language controls and an output-format selector.
Its text area is an OCR text preview, including when binary export is selected.
“Save draft for review” writes the returned binary after checking the source path,
bytes and format again, without another model call. “Open saved file” checks that
the file still matches the saved hash and opens it in the system viewer. Inspect
all exported pages alongside the source. Changing controls invalidates the preview.
Tool preview=true saves no file and displays only OCR text, never the binary.
Clinical/OCR qualification remains unfinished. These controls require a configured
service with document previews enabled; the hosted preview supports them.
Both file review and normal privacy tools use hosted NLP when configured with a hosted service. This is distinct from chat-model disclosure and does not make the operation local or offline. The global preflight retains explicit mode selection and rejects review-required or incomplete v1 adapter results.
Resumable batch files¶
deidentify_batch and /privacy-batch process UTF-8 text, CSV or JSONL through
the configured hosted NLP service. Choose the source, output, checkpoint, format
and selected text column/field. The current preview supports up to 1,000 records,
20 MB per source and 100,000 characters per selected field. The TUI requires an
explicit existing FULL mode; review mode starts unchecked.
For example: “Deidentify the clinical_text column of /path/notes.csv into
/path/notes.masked.csv. Use /path/notes.batch.json as the checkpoint. Mask
patient and clinician identifiers, language de. I accept an unqualified draft
for review.” The agent passes file paths directly to the tool. Source text and
transformed text do not appear in its summary.
Only the selected field is sent to NLP. Other fields remain local and are preserved in the output; they can still contain identifiers. Each row has a status. Pending and failed selected fields are blank. Plain-text output is written only when a complete usable result exists. Review-required results remain drafts, even when every row has finished processing.
New runs require new output and checkpoint paths. Both are written atomically
with owner-only permissions on macOS/Linux. The checkpoint stores opaque row
IDs, offsets, counts, hashes and job cursors; source/output text, keys and policy
term values are excluded. A persistent .lock file holds only a fixed marker.
Keep the original input, requested output and checkpoint together for resume.
Cancel saves completed rows and requests cancellation of active service work. Resume with the same paths and controls; only rows without a saved outcome are resubmitted after cancellation, job expiry or service restart. Resume rejects changed source/output bytes, owner, deployment, model, policy or hashing-key identity. A cooperating writer lock prevents simultaneous use of one checkpoint. Recovery reconciles interruptions between output and journal writes; it is not a transaction with unrelated programs editing the same files.
The remote job holds data in process memory until deletion or expiry (currently 15 minutes). The coordinator requests deletion after saving outputs; a lost connection can leave remote data until expiry. Managed authentication is refreshed between job requests. A timeout leaves the saved job identity available for an explicit resume. Bulk resume requires an attested service deployment and does not fall back to the legacy API. Neither hosted German qualification nor production promotion is implied by this workflow.
PHI Modes¶
OpenMed exposes three PHI modes in the CLI and TUI:
| Mode | Current meaning |
|---|---|
full |
General-purpose clinical workflow context |
deid |
Indicates a de-identification-first posture where the workflow/path supports it |
strict |
Indicates a conservative handling posture for highly sensitive runs |
Important caveat:
The current PHI mode setting is visible in the UI and persisted in session state, but it should not be treated as a universal enforcement layer by itself. Actual data handling depends on:
- Which tool path or workflow you invoke
- Whether that path explicitly calls
deidentify_textor another de-identification step - Which remote boundaries are in use for model, native medical-service, or MCP access
In other words: treat PHI mode as operator-visible workflow context, not as a standalone compliance guarantee.
Local Storage¶
OpenMed writes local state to files such as:
~/.openmed/sessions/for persisted TUI sessions~/.openmed/sessions/<session>/draft_snapshots/for private, immutable workflow drafts awaiting explicit finalization. The directory is owner-only, each snapshot expires after 24 hours by default (OPENMED_DRAFT_SNAPSHOT_TTL_SECONDS), and snapshots are removed after successful finalization, session clear/rollback, or session deletion. Non-session callers use the same default policy under~/.openmed/draft_snapshots//tmp/openmed/artifacts/and/tmp/openmed/cases/by default for workflow outputs~/.config/openmed/for config, MCP metadata, profiles, and user skills~/.openmed/auth.jsonfor OAuth credentials~/.openmed/audit.jsonand~/.openmed/traces/only when optional audit traces are enabled or HF audit writes fall back locally
Optional Audit Trail¶
Audit traces are opt-in and off by default. When enabled, they write directly from the user's machine to the configured private destination:
- private Hugging Face Dataset repo
- private Hugging Face Storage Bucket
- local-only trace directory
OpenMed does not send audit traces to OpenMed-owned infrastructure. Once audit is enabled, the default audit payload mode is payload, which stores the full private transcript and tool payloads in the configured destination. Use preview, fingerprint, or none when you need a smaller or less revealing trace.
phi_payload is separate from PHI mode:
- PHI mode describes the operator posture for the run
phi_payloadcontrols what the audit trace stores
Use openmed audit status and /audit to see the active audit posture. See Audit Trail for setup and trace contents.
Token Storage¶
openmed login stores credentials locally:
openmed loginwrites~/.openmed/auth.json- Project-local
./auth.jsonis deprecated and ignored
The current implementation writes a normal local JSON file and sets restrictive file permissions where supported by the operating system. Teams with stricter requirements should still rely on OS-level access controls.
Network Access¶
OpenMed can access the network for:
- Model traffic — prompts/responses with the configured LLM provider
- OAuth and auth validation — browser login flow plus token validation/status checks when invoked
- Native medical services — extraction, PII, de-identification, terminology, education, HCC, and RAF tooling
- Optional audit writes — private HF dataset or bucket writes only if
openmed audit enablehas been configured - Remote MCP servers — only if you configure them
- Self-update — release checks/downloads when you run
openmed update - Connectivity checks — commands such as
openmed mcp doctor
Outside those paths, the local runtime remains local.
See Native Medical Services for the deployment patterns behind those service planes.
No Telemetry¶
OpenMed Agent itself does not include in-product analytics, usage tracking, or background crash reporting. Public marketing and documentation pages may use lightweight site analytics to understand aggregate visitor traffic.
That statement does not cover third-party services you intentionally configure. Once you point OpenMed at a model provider, customer-managed native medical-service plane, or remote MCP server, the privacy and retention posture of that service becomes part of your real deployment boundary.
Practical Guidance¶
If you need the most defensible deployment story today:
- Keep sessions and artifacts on managed local storage
- Treat
~/.openmed/auth.jsonas the single OAuth credential file and protect the user account that owns it - For customer-managed deployments, run native medical services on infrastructure you control or have vetted contractually
- Treat PHI mode as operator context, and verify the exact tool/data path for any sensitive workflow
- Use draft/finalize workflows so reviewers can inspect outputs before final writes