Configuration¶
OpenMed configuration spans local config files, auth files, session storage, workflow output directories, and environment variables.
Files And Directories¶
| Path | Purpose |
|---|---|
~/.openmed/auth.json |
Single OpenMed OAuth credential file created by openmed login |
~/.openmed/provider_secrets.json |
Optional per-user OpenAI / Anthropic / OpenRouter API keys created by openmed config provider-set |
~/.openmed/audit.json |
Optional private audit-trail destination and PHI payload policy |
~/.openmed/traces/ |
Local audit trace store and HF-write fallback path |
~/.openmed/sessions/ |
Persisted TUI session data |
~/.config/openmed/config.toml |
General CLI configuration |
~/.config/openmed/profiles/ |
Custom configuration profiles |
~/.config/openmed/skills/ |
User-installed local skills |
~/.config/openmed/mcp_servers.json |
MCP server configuration |
~/.config/openmed/mcp_tools_cache.json |
Cached MCP tool discovery results |
~/.openmed/cache/openrouter_models.json |
Cached OpenRouter model capability metadata (24h) |
./.openmed/OPENMED_PLAN.md |
Human-readable durable global plan for long workspace-scoped runs |
./.openmed/OPENMED_PLAN.json |
Machine-readable durable global plan ledger and validation state |
/tmp/openmed/artifacts/ |
Default workflow artifact root |
/tmp/openmed/cases/ |
Default case-run root |
Runtime Settings¶
OpenMed loads per-project and per-user runtime settings that control permission policy, tool filtering, and result persistence. These are separate from the general CLI config and profiles.
| Path | Purpose |
|---|---|
./OPENMED.md |
Project instructions injected into the system prompt (loaded from git root) |
./.openmed/settings.json |
Project-level runtime settings (loaded from git root) |
~/.openmed/settings.json |
User-level runtime settings |
Settings cascade: CLI arguments > project settings > user settings > defaults.
Supported runtime settings keys:
| Key | Type | Default | Purpose |
|---|---|---|---|
permission_mode |
auto / acceptall / denyall / plan |
auto |
Tool execution gating mode |
allow_tools |
list of tool name patterns | none | Tools always allowed (supports wildcards) |
deny_tools |
list of tool name patterns | none | Tools always blocked (supports wildcards) |
ask_tools |
list of tool name patterns | none | Tools that always prompt for approval |
tool_result_persist_threshold_chars |
integer | 50000 |
Oversized results written to disk above this threshold |
In acceptall, ask_tools does not trigger per-call approval prompts; use deny_tools to block tools that should never run in full-access mode.
Use /config in the TUI to see the effective runtime configuration at any time.
Core Environment Variables¶
Provider credentials and provider-specific tuning (OPENAI_API_KEY, ANTHROPIC_API_KEY, OPENROUTER_*, OPENMED_ANTHROPIC_*) are documented on the Providers page.
| Variable | Purpose | Default / behavior |
|---|---|---|
OPENMED_HOME |
Override the ~/.openmed root used for global auth and sessions |
~/.openmed |
OPENMED_CONFIG |
Override the config file path | ~/.config/openmed/config.toml |
OPENMED_PROFILE |
Select a config profile at runtime | unset |
OPENMED_WORKFLOW_ARTIFACTS_DIR |
Override workflow artifact root | /tmp/openmed/artifacts |
OPENMED_WORKFLOW_CASES_DIR |
Override case-run root | /tmp/openmed/cases |
OPENMED_SKILLS_DIR |
Override the user skills directory | ~/.config/openmed/skills |
Audit And Trace Storage¶
Audit trails are off by default. When enabled, OpenMed writes one JSON trace per agent run to a private destination owned by the operator.
Supported destinations:
hf_dataset— private Hugging Face Dataset repo, recommended for versioned audit historyhf_bucket— private Hugging Face Storage Bucket, when your localhuggingface_hubsupports bucket APIslocal— local JSON traces only
Enable a private dataset destination:
export OPENMED_AUDIT_HF_TOKEN=hf_...
openmed audit enable --destination hf_dataset --dataset "<user-or-org>/openmed-traces"
Environment variables:
| Variable | Purpose | Default |
|---|---|---|
OPENMED_AUDIT_ENABLED |
Override audit on/off at runtime | config file / off |
OPENMED_AUDIT_DESTINATION |
hf_dataset, hf_bucket, local, or none |
config file / none |
OPENMED_AUDIT_HF_TOKEN |
HF token for private audit writes | HF_TOKEN fallback if present |
OPENMED_AUDIT_HF_REPO |
Target private HF dataset repo | config file |
OPENMED_AUDIT_HF_BUCKET |
Target private HF bucket | config file |
OPENMED_AUDIT_PHI_PAYLOAD |
none, fingerprint, preview, or payload |
payload |
OPENMED_AUDIT_FLUSH_MODE |
per_run or manual |
per_run |
OPENMED_AUDIT_LOCAL_FALLBACK |
Write local trace if HF write fails | 1 |
OPENMED_AUDIT_LOCAL_PATH |
Local audit trace path | ~/.openmed/traces |
Default phi_payload=payload stores full private transcript and tool payloads. Use preview, fingerprint, or none for smaller traces. See Audit Trail for the trace schema and CLI commands.
Model Providers¶
Credentials, model selection, and per-provider behaviour for OpenAI, Anthropic, and OpenRouter now live on their own page.
See Providers for API keys and ~/.openmed/provider_secrets.json, ChatGPT OAuth sign-in, the OpenRouter model list and recommended models, Anthropic prompt caching and rate-limit guards, and how a provider is selected from the model you pick.
Context And Compaction¶
OpenMed sends its full tool schema (~21,000 tokens) plus the system prompt (~4,500) on every turn — about 25,300 tokens of fixed overhead before any patient content. Long sessions therefore need compaction: older turns are summarized so the request keeps fitting.
How OpenMed decides when to compact¶
Compaction runs when the estimated request crosses a fraction of the model's context window (0.80 by default, lower for some models). That requires knowing the window, which OpenMed resolves in this order:
| Provider | Source of the window |
|---|---|
| OpenAI / Codex / Anthropic | Curated per-model table |
| OpenRouter | The model's own metadata, using the window the routed provider actually serves (not the model's theoretical maximum, which can be several times larger) |
| Custom endpoint | The server's own /models listing (max_model_len), read at startup |
| Anything else | Unknown |
An unknown window disables automatic compaction
OpenMed does not guess a context window. If it cannot determine one, it
turns proactive compaction off rather than compact against a fabricated
number — summarizing is lossy and irreversible, and in a clinical session the
transcript is the record. You will see a one-time notice in the TUI, and
/compact remains available to compact manually.
A guessed window is wrong in both directions: too small and OpenMed compacts a session that had plenty of room; too large and it never compacts until the server errors.
Compaction still runs reactively in all cases: when a provider reports that the request no longer fits, OpenMed compacts once and retries. Rate limits are explicitly not treated as overflow, so a throttle never destroys history.
Making an unknown window known¶
For a self-hosted or custom endpoint, run the doctor:
vLLM and SGLang report max_model_len on /v1/models, which the doctor reads
directly. If your server does not report a window, the doctor fails the
context check and tells you what to set.
Silent truncation¶
Some servers do not error when a prompt exceeds their context — they drop the front of it. The front is exactly where OpenMed's system prompt and tool schemas live, so the symptom is a model that appears to ignore its instructions and refuses to call tools, with nothing in any log. llama.cpp defaults to a 4096-token context, and Ollama's default auto-scales with available VRAM and can land at 4k.
endpoint-doctor detects this with a canary: it places a unique token at the
very start of the system prompt, pads to the size of a real turn, and asks the
model to echo it back. If the token comes back, the front survived.
[FAIL] truncation: The model could not see a token placed at the START of the
system prompt, and the server returned no error — it is silently
truncating.
A server that errors on an over-long prompt passes this check — refusing is the honest behaviour.
Setting context explicitly on your server¶
| Engine | Flag | Default if unset |
|---|---|---|
| vLLM | --max-model-len 65536 |
The model's maximum (can OOM the KV cache) |
| SGLang | --context-length 65536 |
The model's maximum |
| llama.cpp | --ctx-size 65536 |
4096 — truncates every turn |
| Ollama | OLLAMA_CONTEXT_LENGTH=65536 before ollama serve |
Auto-scales; can be 4k. Verify with ollama ps |
| Variable | Purpose | Default |
|---|---|---|
OPENMED_COMPACTION_THRESHOLD |
Override the fraction of the window at which compaction triggers | per-model, typically 0.80 |
Web Search¶
Web search is off by default on every provider, including OpenAI and ChatGPT OAuth. Enabling it sends queries — which may contain clinical detail — to a third-party search vendor, so it is an explicit operator decision. Full setup and privacy guidance: Web Search.
Both parts are required: a key alone does nothing, so adding one for another purpose can never silently start sending clinical queries.
When search has never been enabled the search_web tool is hidden from the
model entirely, so it does not spend schema budget on a capability that cannot
work. If you enable search but the backend is misconfigured, the tool stays
visible and explains exactly what is wrong.
Provider-native search (OpenAI and Codex OAuth)¶
OpenAI's Responses API — used by both the OpenAI provider and ChatGPT OAuth — can run a server-side search where the model searches and returns prose. OpenMed does not request it by default, for two reasons: it is unavailable on Anthropic, OpenRouter and local models, so behaviour would differ by provider; and its results never reach OpenMed as inspectable sources, so a claim drawn from them cannot be traced to a page you can open.
If you accept that trade — for non-clinical research use, for example — enable it per session:
| Variable | Purpose | Default |
|---|---|---|
OPENMED_BUILTIN_WEB_SEARCH |
Request the provider's server-side web_search tool on OpenAI / Codex OAuth |
0 (off) |
This is independent of OPENMED_WEB_SEARCH: the two can be used together, and
the client-side tool is the one that produces citable sources.
Native Medical Services¶
OpenMed ships native medical tools, but many of them use OpenMed's native medical service plane rather than an embedded local model binary.
These are native OpenMed tools. They are not remote MCP servers.
The service split is intentional:
- extraction and de-identification run on a dedicated native service plane
- terminology, HCC, RAF, RxNorm, LOINC, MedlinePlus, and PubMed run on a dedicated native service plane
The point of that split is not locality for its own sake. It is to keep sensitive or high-volume clinical processing on dedicated service planes that are easier to govern, faster on long unstructured inputs, and more cost-efficient than routing every page through a frontier-model path. General agent reasoning still uses the configured model provider.
During preview, OpenMed operates these native medical services for approved evaluators. Later deployments can keep the same workflow surface while moving the service tier to customer-managed cloud or on-prem infrastructure.
Preview binaries are provisioned for approved evaluators. Request preview access if you do not have an install link yet.
See Native Medical Services for the deployment story and hosting patterns.
MCP Configuration¶
| Variable | Purpose | Default |
|---|---|---|
OPENMED_MCP_CONFIG_PATH |
Override MCP config file path | ~/.config/openmed/mcp_servers.json |
OPENMED_MCP_TOOLS_CACHE_PATH |
Override tool-cache path | ~/.config/openmed/mcp_tools_cache.json |
OPENMED_MCP_TOOLS_CACHE_TTL_SECONDS |
Override discovery cache TTL | 3600 |
OPENMED_MCP_<SERVER_ID>_ENABLED |
Override a server's enabled state | unset |
OPENMED_MCP_<SERVER_ID>_URL |
Override a server's URL | unset |
OPENMED_MCP_<SERVER_ID>_HEADERS_JSON |
Override a server's auth headers | unset |
Session PHI Mode¶
OpenMed exposes a session PHI mode in the CLI/TUI:
fulldeidstrict
This mode is stored in session state and shown in the UI. It should be treated as workflow context, not as a universal enforcement layer by itself. Real PHI handling still depends on the tool path and active service boundaries.
Profiles¶
See Profiles for built-in and custom profile details.