DEV Community

Adrian Kereky
Adrian Kereky

Posted on Fully Autonomous

Giving an LLM a patient's record without dumping the whole FHIR bundle

Disclosure: I work on Anpheros, the platform used in the examples. The approach (budgeted, provenance-labelled context) applies to any FHIR backend.

If you have ever pushed a FHIR $everything Bundle into a prompt, you know the problem: a few months of vitals is already thousands of Observations. Most of it is irrelevant to the question, all of it costs tokens, and the model has no way to tell a lab-measured value from one the patient typed in or one an earlier AI step guessed.

Three things matter when a model reads a medical record:

  1. Relevance. A medication review before a cardiology visit needs blood pressure trends, current medications and a few labs, not every step count.
  2. A budget. You decide how many tokens the record may take, and you want to know what was left out.
  3. Provenance. Each fact should carry who wrote it (device, practitioner, patient, import, AI) and from where. AI-generated values should never be mixed with measured ones.

Doing it by hand

On a plain FHIR server you would: search Observations by LOINC code and date, compute weekly trends, pull active MedicationStatements and Conditions, look up each resource's Provenance, rank, trim to a token count, and keep a list of what you dropped. It is all doable, and it is a week of work you will redo for every new question type.

Asking the backend for a context instead

Anpheros exposes this as one call. Get a free sandbox key (sign in with Google at platform.anpheros.com/dashboard → Get a sandbox key); every sandbox project comes with 30 synthetic patients with six months of history.

npm install @anpheros/sdk
export ANPHEROS_KEY=sk_test_...
Enter fullscreen mode Exit fullscreen mode
import { Anpheros, apiKey } from '@anpheros/sdk';

const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });

const { data: patients } = await anpheros.patients.list();
const patient = patients[0];

// Raw data is still there when you need it
const labs = await anpheros.observations.list(patient.id, { category: 'laboratory', limit: 10 });

// A budgeted context for a specific task
const ctx = await anpheros.context.build({
  patient: patient.id,
  task: 'weekly check-in',
  budget_tokens: 1500,
  format: 'text',
});
Enter fullscreen mode Exit fullscreen mode

The same call over HTTP:

curl -X POST "https://platform.anpheros.com/v1/context" \
  -H "Authorization: Bearer $ANPHEROS_KEY" -H 'content-type: application/json' -d '{
  "patient": "'$PID'",
  "task": "medication review before a cardiology visit",
  "question": "How did blood pressure evolve over the last 3 months?",
  "budget_tokens": 1500,
  "format": "text"
}'
Enter fullscreen mode Exit fullscreen mode

What comes back: sections (summary, conditions, medications, allergies, labs, vitals with weekly trends and before/after-treatment markers, symptoms, timeline, documents); every item labelled with author_type and source; a list of what was omitted to fit the budget; warnings; and a manifest_id that ties the call to the audit log, so you can later answer "what exactly did the model see?". Values produced by AI only appear under ai_notes.

You can also be explicit: "needs": ["labs:4548-4", "vitals:trend:85354-9", "timeline:180d"] (HbA1c, blood pressure trend, last 180 days).

Writing back, honestly

Every write says who produced the value. A reading from a glucometer:

curl -X POST "https://platform.anpheros.com/v1/patients/$PID/observations" \
  -H "Authorization: Bearer $ANPHEROS_KEY" -H 'content-type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" -d '{
  "code": "2339-0", "display": "Glucose", "category": "laboratory",
  "value": 112, "unit": "mg/dL", "effective_at": "2026-09-19T08:10:00Z",
  "author_type": "device"
}'
Enter fullscreen mode Exit fullscreen mode

A value your model produced goes in with "author_type": "ai". If you omit the field, it defaults to import, never patient. Every write creates a FHIR Provenance, and /fhir/R4/Observation/{id}/_history keeps prior versions.

Real patients need consent, not keys

API keys only see your own project's patients (its sandbox copies and the ones it created). To read a person's existing record you go through OAuth 2.1 + PKCE (SMART on FHIR standalone launch, SMART v2 scopes); the person picks what to share and for how long, and can revoke. Both SDKs implement the flow.

Limits worth knowing

Sandbox data is synthetic only. The platform is in private beta; EHR launch and Bulk Data are not supported. Anpheros does not run the model; you bring your own (hosted or local).

Links

Top comments (0)