# Extract Clinical Entities To Fhir

> Extract clinical entities from synthetic or already de-identified text with OpenMed and map them into deterministic FHIR R4 resources and a Bundle. Use when an agent must turn local clinical NER output into Conditions, MedicationStatements, Observations, or other FHIR resources without inventing terminology codes.

- Skill: `maziyarpanahi/extract-clinical-entities-to-fhir` (Agent Skill)
- Install (CLI): `npx skillmds@latest add maziyarpanahi/extract-clinical-entities-to-fhir`
- Raw SKILL.md: https://api.skillmd.com/api/skills/maziyarpanahi/extract-clinical-entities-to-fhir/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: maziyarpanahi (https://skillmd.com/u/maziyarpanahi)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/maziyarpanahi/extract-clinical-entities-to-fhir

---


# Extract clinical entities to FHIR

Separate extraction from clinical coding. OpenMed finds spans and supplies the
mechanical FHIR builders; the application decides which resource type and
status are clinically appropriate.

## Procedure

1. Keep the source synthetic, or de-identify it inside the trusted boundary
   before extraction.
2. Run `openmed.analyze_text` with the task-appropriate clinical model.
3. Filter predictions by label and confidence; preserve offsets in a
   PHI-safe audit record.
4. Map each accepted span to the correct FHIR resource type.
5. Add terminology codes only from a user-approved mapping or terminology
   service. Never invent a code.
6. Assemble resources with `to_bundle` and validate against the target profile.

## Runnable synthetic example

Install the model runtime first with `python -m pip install "openmed[hf]"`.

```python
import json

from openmed import analyze_text
from openmed.clinical.exporters.fhir import to_bundle

note = "Assessment: type 2 diabetes mellitus is stable on metformin."
result = analyze_text(
    note,
    model_name="disease_detection_superclinical",
    confidence_threshold=0.5,
)

resources = [{"resourceType": "Patient", "id": "synthetic-patient"}]
for index, entity in enumerate(result.entities, start=1):
    if entity.label.upper() not in {"CONDITION", "DIAGNOSIS", "DISEASE"}:
        continue
    resources.append(
        {
            "resourceType": "Condition",
            "id": f"condition-{index}",
            "clinicalStatus": {
                "coding": [
                    {
                        "system": (
                            "http://terminology.hl7.org/CodeSystem/"
                            "condition-clinical"
                        ),
                        "code": "active",
                    }
                ]
            },
            "verificationStatus": {
                "coding": [
                    {
                        "system": (
                            "http://terminology.hl7.org/CodeSystem/"
                            "condition-ver-status"
                        ),
                        "code": "confirmed",
                    }
                ]
            },
            # A text-only CodeableConcept is preferable to an invented code.
            "code": {"text": entity.text},
            "subject": {"reference": "Patient/synthetic-patient"},
        }
    )

if len(resources) == 1:
    raise RuntimeError("No condition spans met the label and confidence rules")

bundle = to_bundle(resources, doc_id="synthetic-note-001")
print(json.dumps(bundle, indent=2))
```

## Safety checks

- Do not put raw identifiers, source text, or reversible mappings in logs,
  `OperationOutcome.diagnostics`, or trace metadata.
- Keep a patient identity service separate from extracted clinical facts.
- Preserve negation, temporality, and experiencer context before asserting a
  resource as active or confirmed.
- Use a text-only `CodeableConcept` when no approved code is available.
- Validate the Bundle against the receiver's FHIR and profile requirements.
- Do not bundle restricted terminologies; use the user's licensed service.

## Repository example

Read and run
[the redaction-to-FHIR walkthrough](../../examples/first_five_minutes_redact_extract_fhir.py)
for an offline-friendly pipeline with deterministic extraction.

