Skip to content
Security
Skill

/serving-openmed-rest-api

Stand up OpenMed's FastAPI REST service for clinical NER, PII extraction, and de-identification, with health checks, model keep-alive/unload, optional dynamic batching, and no-PHI logging. Use when the user wants to serve OpenMed over HTTP, deploy a de-id/NER REST API, run an

BOOST
From plugin
openmed
5.7k74 skills
Install
$ npx -y skills add maziyarpanahi/openmed --skill serving-openmed-rest-api --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/serving-openmed-rest-api

Context preview

The summary Claude sees to decide when to auto-load this skill.

Stand up OpenMed's FastAPI REST service for clinical NER, PII extraction, and de-identification, with health checks, model keep-alive/unload, optional dynamic batching, and no-PHI logging. Use when the user wants to serve OpenMed over HTTP, deploy a de-id/NER REST API, run an

SKILL.md

serving-openmed-rest-api.SKILL.md
name: serving-openmed-rest-api
description: "Stand up OpenMed's FastAPI REST service for clinical NER, PII extraction, and de-identification, with health checks, model keep-alive/unload, optional dynamic batching, and no-PHI logging. Use when the user wants to serve OpenMed over HTTP, deploy a de-id/NER REST API, run an inference endpoint for clinical text, add a /analyze or /pii/deidentify route, or containerize OpenMed as a service. Covers the service extra, launching create_app with uvicorn, the real endpoints (/health, /analyze, /pii/extract, /pii/deidentify, /models/loaded, /models/unload), request/response shapes, ServiceRuntime env-var configuration, and self-hosted auth/CORS/TLS notes."
license: Apache-2.0
metadata:
  project: OpenMed
  category: deployment-ops
  pairs: adjacent
  version: "1.0"

Serving OpenMed over REST

`openmed.service` is a hardened **FastAPI** app exposing OpenMed's NER, PII extraction, and de-identification over HTTP. It is built to be **self-hosted**: models run on-device, there's no telemetry, and the request schemas reject raw PHI from spilling into errors. Use it when callers need request/response inference; use `batch-processing-clinical-text` for corpora.

When to use this skill

To put OpenMed behind an HTTP endpoint your own apps call — an internal de-id microservice, an NER backend, a containerized inference tier. For agent/tool integration prefer the MCP server (`deploying-openmed-mcp`); for offline bulk work use batch processing.

Quick start

pip install "openmed[service]"          # FastAPI + uvicorn + pydantic

# Launch the ASGI app (factory create_app, or the module-level `app`)
python -m openmed.service.logging --host 127.0.0.1 --port 8000
# Or build it in-process (e.g. to mount under a parent app / add middleware):
from openmed.service import create_app
app = create_app()
curl -s localhost:8000/health
# {"status":"ok","service":"openmed-rest","version":"...","profile":"prod"}

curl -s localhost:8000/analyze -H 'content-type: application/json' -d '{
  "text": "Patient received 75mg clopidogrel for NSTEMI.",
  "model_name": "disease_detection_superclinical"
}'

curl -s localhost:8000/pii/deidentify -H 'content-type: application/json' -d '{
  "text": "John Doe called 555-123-4567 on 01/15/2020.",
  "method": "mask"
}'

Endpoints (confirmed in `openmed/service/app.py`)

| Method & path | Purpose | Request schema | | --- | --- | --- | | `GET /health` | liveness + version + active profile | — | | `GET /models/loaded` | cache/keep-alive status of resident models | — | | `POST /models/unload` | unload one model or all inactive models | `ModelUnloadRequest` (`model_name` or `all=true`) | | `POST /analyze` | clinical NER | `AnalyzeRequest` | | `POST /pii/extract` | detect PII/PHI spans | `PIIExtractRequest` | | `POST /pii/deidentify` | mask/remove/replace/hash/shift-dates PHI | `PIIDeidentifyRequest` |

Request fields (from `openmed/service/schemas.py`, strict — unknown fields are rejected):

  • **`AnalyzeRequest`**: `text` (required), `model_name`

(`"disease_detection_superclinical"`), `confidence_threshold` (0.0), `group_entities`, `aggregation_strategy` (`simple|first|average|max`), `sentence_detection`, `sentence_language`, `sentence_clean`, `use_fast_tokenizer`, `keep_alive`.

  • **`PIIExtractRequest`**: `text`, `model_name`

(default `OpenMed/OpenMed-PII-SuperClinical-Small-44M-v1`), `confidence_threshold` (0.5), `use_smart_merging`, `lang` (`en/fr/de/it/es/nl/hi/te/pt/ar/ja/tr`), `normalize_accents`, `keep_alive`.

  • **`PIIDeidentifyRequest`**: same base plus `method`

(`mask|remove|replace|hash|shift_dates`, default `mask`), `confidence_threshold` (0.7), `keep_year`, `shift_dates`, `date_shift_days`, `keep_mapping`, `policy`, `use_smart_merging`, `use_safety_sweep`.

Responses are the OpenMed result `to_dict()` (e.g. `{text, entities[...], ...}`). Errors use a stable envelope: `{"error": {"code", "message", "details"}}` with `422` validation_error, `400` bad_request, `504` timeout, `500` internal_error.

Configuring the runtime (env vars)

`ServiceRuntime.from_env()` reads the process environment at startup (`openmed/service/runtime.py`):

| Env var | Effect | | --- | --- | | `OPENMED_PROFILE` | config profile (`prod` default) | | `OPENMED_SERVICE_PRELOAD_MODELS` | comma list of models to warm at startup | | `OPENMED_SERVICE_KEEP_ALIVE` | default idle keep-alive before unload | | `OPENMED_SERVICE_MAX_RESIDENT_MODELS` | cap resident models (warm pool) | | `OPENMED_SERVICE_BATCHING_ENABLED` | enable dynamic request batching | | `OPENMED_SERVICE_BATCH_MAX_SIZE` | max dynamic batch size (default 8) | | `OPENMED_SERVICE_BATCH_MAX_WAIT_MS` | batch-collection window (default 5ms) |

OPENMED_SERVICE_PRELOAD_MODELS="disease_detection_superclinical" \
OPENMED_SERVICE_BATCHING_ENABLED=true \
python -m openmed.service.logging --host 0.0.0.0 --port 8000

Preloading avoids first-request latency; the warm pool keeps hot models resident and idle-unloads the rest. `/analyze` and `/pii/extract` coalesce concurrent requests when batching is enabled.

Workflow

1. **Install + launch.** `pip install "openmed[service]"`, then run `python -m openmed.service.logging` (or build with `create_app()`). 2. **Configure the runtime** via env vars before start: set `OPENMED_PROFILE`, preload your hot models, and decide keep-alive / max resident / batching to fit the box. 3. **Front it with auth/TLS.** Place a reverse proxy or gateway (API keys/mTLS, CORS allow-list) ahead of the app — it has none built in. 4. **Health-check + warm.** Poll `GET /health`; preloaded models warm during the lifespan startup so the first real request isn't cold. 5. **Call the endpoints** (`/analyze`, `/pii/extract`, `/pii/deidentify`) with the strict JSON schemas; handle the `{"error": {...}}` envelope. 6. **Manage memory** with `GET /models/loaded` and `POST /models/unload` as traffic

Read more
Ships withopenmed

Local-first healthcare AI: clinical NER and HIPAA PII de-identification on hardware you control. 2,200+ medical models, 35 model-backed PII languages, and Python, MLX, Android and browser runtimes. Apache-2.0 SDK.

Get the whole plugin

Other skills on openmed.