AgentSkillsCN

azure-fhir-developer

借助Azure API for FHIR的专业知识,更快地构建FHIR R4应用,涵盖资源结构、编码系统(LOINC、SNOMED CT、RxNorm),以及Azure特有的认证模式。

SKILL.md
--- frontmatter
name: azure-fhir-developer
description: "Build FHIR R4 applications faster with specialized knowledge of Azure API for FHIR, including resource structures, coding systems (LOINC, SNOMED CT, RxNorm), and Azure-specific authentication patterns."

FHIR Developer Skill (Azure)

Connect healthcare systems faster with specialized knowledge of HL7 FHIR R4 for healthcare data exchange, including resource structures, coding systems, validation patterns, and Azure Health Data Services integration.

Target Users: Healthcare developers, integration engineers, EHR developers

Key Features:

  • FHIR R4 resource reference with required fields
  • Common coding systems (LOINC, SNOMED CT, RxNorm, ICD-10)
  • Azure-specific authentication (SMART on FHIR, Managed Identity)
  • Pydantic v2 model generation patterns
  • Bulk data export and import
  • Azure Health Data Services integration

Quick Reference

HTTP Status Codes

CodeMeaningWhen Returned
200OKSuccessful GET, successful search
201CreatedSuccessful POST creating new resource
204No ContentSuccessful DELETE
400Bad RequestInvalid FHIR resource, validation failure
401UnauthorizedMissing or invalid token
403ForbiddenToken valid but insufficient scope
404Not FoundResource doesn't exist
409ConflictVersion conflict on update
412Precondition FailedIf-Match header doesn't match
422Unprocessable EntityBusiness rule violation

Required Fields by Resource

ResourceRequired Fields
Patientidentifier OR name (one must be present)
Observationstatus, code, subject
ConditionclinicalStatus, code, subject
MedicationRequeststatus, intent, medication[x], subject
Encounterstatus, class, subject
Procedurestatus, code, subject
DiagnosticReportstatus, code, subject
AllergyIntoleranceclinicalStatus, patient
Immunizationstatus, vaccineCode, patient, occurrence[x]
CarePlanstatus, intent, subject

Coding Systems

LOINC (Logical Observation Identifiers Names and Codes)

System URL: http://loinc.org

Use for: Laboratory observations, vital signs, clinical documents

CodeDisplayCategory
8867-4Heart rateVital Signs
8310-5Body temperatureVital Signs
8480-6Systolic blood pressureVital Signs
8462-4Diastolic blood pressureVital Signs
8302-2Body heightVital Signs
29463-7Body weightVital Signs
59408-5Oxygen saturationVital Signs
8478-0Mean blood pressureVital Signs
2339-0Glucose [Mass/volume] in BloodLab
2093-3Cholesterol [Mass/volume] in Serum or PlasmaLab
718-7Hemoglobin [Mass/volume] in BloodLab
4548-4Hemoglobin A1c/Hemoglobin.total in BloodLab

Example:

json
{
  "coding": [{
    "system": "http://loinc.org",
    "code": "8867-4",
    "display": "Heart rate"
  }]
}

SNOMED CT (Systematized Nomenclature of Medicine)

System URL: http://snomed.info/sct

Use for: Clinical findings, procedures, body structures, organisms

CodeDisplayCategory
73211009Diabetes mellitusCondition
38341003Hypertensive disorderCondition
195967001AsthmaCondition
40055000Chronic kidney diseaseCondition
427623005Chronic obstructive pulmonary diseaseCondition
414545008Ischemic heart diseaseCondition
80146002AppendectomyProcedure
27737000Cesarean sectionProcedure
174776001Total hip replacementProcedure

Example:

json
{
  "coding": [{
    "system": "http://snomed.info/sct",
    "code": "73211009",
    "display": "Diabetes mellitus"
  }]
}

RxNorm (Normalized Drug Names)

System URL: http://www.nlm.nih.gov/research/umls/rxnorm

Use for: Medications, drug ingredients, brand names

CodeDisplayType
197361Metformin 500 MG Oral TabletSCD
311700Lisinopril 10 MG Oral TabletSCD
310798Atorvastatin 20 MG Oral TabletSCD
197319Omeprazole 20 MG Delayed Release Oral CapsuleSCD
314076Aspirin 81 MG Oral TabletSCD

ICD-10-CM (International Classification of Diseases)

System URL: http://hl7.org/fhir/sid/icd-10-cm

Use for: Diagnoses (billing/administrative)

CodeDisplay
E11.9Type 2 diabetes mellitus without complications
I10Essential (primary) hypertension
J45.909Unspecified asthma, uncomplicated
N18.9Chronic kidney disease, unspecified
J44.9Chronic obstructive pulmonary disease, unspecified

Azure Authentication Patterns

SMART on FHIR (Patient-Facing Apps)

typescript
// Configure MSAL for SMART on FHIR
const msalConfig = {
  auth: {
    clientId: process.env.CLIENT_ID,
    authority: `https://login.microsoftonline.com/${process.env.TENANT_ID}`,
    redirectUri: process.env.REDIRECT_URI
  }
};

// Request FHIR scopes
const loginRequest = {
  scopes: [
    `${process.env.FHIR_URL}/.default`,
    'openid',
    'profile',
    'launch/patient'
  ]
};

Managed Identity (Backend Services)

typescript
import { DefaultAzureCredential } from '@azure/identity';

const credential = new DefaultAzureCredential();
const token = await credential.getToken(
  `${process.env.FHIR_URL}/.default`
);

const response = await fetch(`${process.env.FHIR_URL}/Patient`, {
  headers: {
    'Authorization': `Bearer ${token.token}`,
    'Content-Type': 'application/fhir+json'
  }
});

Service Principal

bash
# Get token via Azure CLI
az account get-access-token \
  --resource https://{workspace}-{fhir-service}.fhir.azurehealthcareapis.com \
  --query accessToken -o tsv

Pydantic v2 Patterns

Patient Model

python
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import date

class HumanName(BaseModel):
    use: Optional[str] = None
    family: Optional[str] = None
    given: Optional[List[str]] = None

class Identifier(BaseModel):
    system: Optional[str] = None
    value: Optional[str] = None

class Patient(BaseModel):
    resourceType: str = Field(default="Patient", frozen=True)
    id: Optional[str] = None
    identifier: Optional[List[Identifier]] = None
    active: Optional[bool] = True
    name: Optional[List[HumanName]] = None
    gender: Optional[str] = None
    birthDate: Optional[date] = None

    model_config = {
        "populate_by_name": True,
        "json_schema_extra": {
            "example": {
                "resourceType": "Patient",
                "identifier": [{"system": "http://example.org", "value": "12345"}],
                "name": [{"family": "Smith", "given": ["John"]}],
                "gender": "male",
                "birthDate": "1970-01-01"
            }
        }
    }

Observation Model

python
class Coding(BaseModel):
    system: Optional[str] = None
    code: Optional[str] = None
    display: Optional[str] = None

class CodeableConcept(BaseModel):
    coding: Optional[List[Coding]] = None
    text: Optional[str] = None

class Quantity(BaseModel):
    value: Optional[float] = None
    unit: Optional[str] = None
    system: Optional[str] = Field(default="http://unitsofmeasure.org")
    code: Optional[str] = None

class Reference(BaseModel):
    reference: Optional[str] = None
    display: Optional[str] = None

class Observation(BaseModel):
    resourceType: str = Field(default="Observation", frozen=True)
    id: Optional[str] = None
    status: str  # required
    code: CodeableConcept  # required
    subject: Reference  # required
    effectiveDateTime: Optional[str] = None
    valueQuantity: Optional[Quantity] = None
    valueCodeableConcept: Optional[CodeableConcept] = None

Validation Patterns

Profile Validation

http
POST https://{fhir-server}.azurehealthcareapis.com/Patient/$validate
Content-Type: application/fhir+json

{
  "resourceType": "Parameters",
  "parameter": [{
    "name": "resource",
    "resource": {
      "resourceType": "Patient",
      "name": [{"family": "Smith"}]
    }
  }]
}

Bundle Validation

http
POST https://{fhir-server}.azurehealthcareapis.com
Content-Type: application/fhir+json

{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "fullUrl": "urn:uuid:patient-1",
      "resource": {
        "resourceType": "Patient",
        "name": [{"family": "Smith"}]
      },
      "request": {
        "method": "POST",
        "url": "Patient"
      }
    }
  ]
}

Search Parameters

Common Search Modifiers

ModifierExampleDescription
:exactname:exact=JohnCase-sensitive exact match
:containsname:contains=JoSubstring match
:missingemail:missing=trueField is/isn't present
:notstatus:not=cancelledNegation

Date Search Prefixes

PrefixMeaningExample
eqEqualsdate=eq2024-01-01
neNot equalsdate=ne2024-01-01
ltLess thandate=lt2024-01-01
leLess than or equaldate=le2024-01-01
gtGreater thandate=gt2024-01-01
geGreater than or equaldate=ge2024-01-01

Common Search Patterns

http
# Search patients by name and birthdate
GET /Patient?name=Smith&birthdate=1970-01-01

# Search observations by patient and code
GET /Observation?patient=Patient/123&code=http://loinc.org|8867-4

# Include related resources
GET /Patient?_id=123&_include=Patient:organization

# Reverse include
GET /Patient?_id=123&_revinclude=Observation:patient

# Paginated search
GET /Patient?_count=50&_offset=100

Bulk Data Operations

System Export

http
GET https://{fhir-server}.azurehealthcareapis.com/$export
Accept: application/fhir+json
Prefer: respond-async

# Response: 202 Accepted
# Content-Location: https://{fhir-server}/_operations/export/{job-id}

Export Status Check

http
GET https://{fhir-server}/_operations/export/{job-id}

# When complete (200 OK):
{
  "transactionTime": "2024-01-15T12:00:00Z",
  "request": "https://{fhir-server}/$export",
  "output": [
    {
      "type": "Patient",
      "url": "https://storage.blob.core.windows.net/export/Patient.ndjson"
    }
  ]
}

Azure-Specific Features

Private Link Configuration

bash
az network private-endpoint create \
  --name pe-fhir \
  --resource-group myRG \
  --vnet-name myVNet \
  --subnet default \
  --private-connection-resource-id $(az healthcareapis workspace show \
    --name myWorkspace --resource-group myRG --query id -o tsv) \
  --group-id fhir \
  --connection-name fhir-connection

Diagnostic Logging

bash
az monitor diagnostic-settings create \
  --name fhir-diagnostics \
  --resource $(az healthcareapis workspace fhir-service show \
    --name myFhir --workspace-name myWorkspace --resource-group myRG \
    --query id -o tsv) \
  --logs '[{"category": "AuditLogs", "enabled": true}]' \
  --workspace $(az monitor log-analytics workspace show \
    --name myLAWorkspace --resource-group myRG --query id -o tsv)

References

For detailed documentation, see: