Dev.to AI 🤖 Ai 👁 0 📖 4 min read

Generating a validated International Patient Summary from a patient-held record (0 errors, and what we deliberately left out)

A patient summary sounds like the easiest document in health IT: allergies, medications, problems, a few results. In practice it is where most "interoperable" systems quietly fail, because the receiving clinician has to

A patient summary sounds like the easiest document in health IT: allergies, medications, problems, a few results. In practice it is where most "interoperable" systems quietly fail, because the receiving clinician has to trust it in a context where nobody can ask follow-up questions: an emergency department in another country, a new GP, a telehealth visit at 2 a.m.

We build Anpheros, a patient-held health record. Every person can produce their summary as an HL7 International Patient Summary (IPS) document via GET /fhir/R4/Patient/{id}/$summary. This post covers what it took to get that document to 0 errors against the official HL7 validator (hl7.fhir.uv.ips#1.1.0, FHIR 4.0.1, tx.fhir.org), and, more interesting, the places where we chose to say less rather than say something false.

The shape of the document

The output is a FHIR Bundle of type document:

  • a Composition coded LOINC 60591-5 (Patient summary Document);
  • the three sections IPS makes mandatory: Allergies and adverse reactions (48765-2), Medication use (10160-0), Problem list (11450-4);
  • the recommended sections when there is data: Immunizations (11369-6), Results (30954-2, laboratory Observations only), Vital signs (8716-3);
  • the referenced resources, a Device as author (the platform software, with version) and an Organization as custodian, every entry with a fullUrl under the server base so relative references resolve by Bundle rules.

Profiles (Bundle-uv-ips, Composition-uv-ips, AllergyIntolerance-uv-ips, Observation-results-laboratory-uv-ips, and so on) are declared only on resources that actually pass the section's checks. A laboratory Observation without a LOINC coding, for example, is not given the IPS lab profile and pushed through anyway. It is left out of the document and reported in a response header (Anpheros-Summary-Excluded) so the calling system knows exactly what was dropped and why. One bad resource never makes the whole summary fail.

"No information" is not "nothing"

IPS forbids emptyReason on the mandatory sections (section.emptyReason 0..0) and requires entry 1..*. That forces a decision most record systems avoid:

  • if nothing is recorded, the section carries the IPS absent/unknown code no-allergy-info, no-medication-info, no-problem-info: we do not know;
  • only when an application has explicitly recorded the negation (no-known-allergies, or the SNOMED CT equivalent 716186003) does the document say the patient has none.

The distinction matters clinically. "No known drug allergies" changes what an emergency physician is willing to administer; "no allergy information" should not. A platform cannot infer one from the other, so we do not try. The truthful statement is the only safe default.

Consent shapes the document, not the other way round

Access in Anpheros is scoped by the patient: by resource type, by Observation category, and by time. When a requesting application's consent does not cover a section, the summary does not present that section as empty knowledge:

  • the section narrative states that it was not shared with this application;
  • a mandatory section still carries the IPS "no information" entry;
  • the Composition carries the REDACTED security label (HL7 Data Segmentation for Privacy), so the recipient knows the summary is partial.

The redaction decision is computed from the scopes alone, never from the data. Otherwise the shape of a redacted document would leak whether something sensitive existed behind it.

The warnings we kept on purpose

"0 errors" is the headline. The warnings are where the design choices live:

  • "All observations should have a performer." For vital signs captured by a phone or a watch, we do not invent one. For laboratory results, where the IPS profile requires a performer, an unknown source lab becomes performer.display = "Laboratory not recorded (patient-provided result)". It is ugly, and it is accurate.
  • "None of the codings are in the value set (recommended)." IPS recommends SNOMED CT for problems, medications and allergies. We record ICD-10, ATC and free text. A SNOMED mapping is a terminology project in its own right, not something to fake inside a document generator.
  • coding.display removed from the copies. Application-supplied display strings are frequently not the terminology's official text, and the validator rightly flags them. Codes and text stay; the display goes.

Each of these could be "fixed" to make the validator report cleaner. Each fix would make the document less honest.

Narrative is part of the contract

Every section has a human-readable XHTML table (name, code, date, value or status), the document has its own top-level narrative, and every included resource has a one-line text. Content coming from data is escaped, with no script, style or event attributes. Bundle.language and Composition.language follow ?lang=, and every narrative carries lang / xml:lang. A clinician reading the document in a browser, without any FHIR tooling, should still get the full picture.

Why this matters for medical AI

Most of the current discussion around clinical LLMs is about the model. In our experience the harder problem is the input: a longitudinal, coded, provenance-aware record with explicit uncertainty. An IPS document is a surprisingly good contract for that: bounded, standardised, consent-aware, and explicit about what is unknown. Handing a model "no allergy information" instead of an empty list is the difference between a cautious answer and a confidently wrong one.

Try it

The developer sandbox has 30 synthetic patients. GET /fhir/R4/Patient/{id}/$summary on any of them returns a validated IPS document, and you can reproduce the result with:

java -jar validator_cli.jar summary.json -version 4.0.1 -ig hl7.fhir.uv.ips#1.1.0

Docs and sandbox: https://developers.anpheros.com

Still missing and on the list: Procedures, Medical devices, Diagnostic reports, Social history, Pregnancy, Functional status, Plan of care and Advance directives. If you work on IPS in production, I would love to hear which of these your receiving systems actually read.

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.