
Initial Release
A multi-agent clinical AI platform powered by InterSystems IRIS for Health. Features agents for triage, specialist consultation, and pharmacy safety, grounded by IRIS Vector Search RAG.
IRIS FHIR Agents orchestrates four LangChain-powered AI agents that work together to deliver clinical intelligence directly on top of a live FHIR R4 server:
| Agent | Role | Key Capability |
|---|---|---|
| Triage Agent | Patient intake | Urgency classification · FHIR Observation writes · SNOMED CT codes |
| Specialist Agent | Condition analysis | Comorbidity review · Referral planning · ServiceRequest writes |
| Pharmacy Agent | Medication safety | Drug interaction checks · Allergy conflict detection · MedicationRequest writes |
| FHIR Server Agent | FHIR exploration | Natural language FHIR queries · IRIS SQL · Capability explorer |
| Custom Agents | User-defined specialty | No-code Agent Builder · Configurable tools · 5 clinical templates · Routes automatically via orchestrator |
Every agent is grounded by IRIS Vector Search RAG — 50 clinical guidelines from CDC, AHA, FDA, WHO, and KDIGO embedded into IRIS and retrieved semantically at query time. No guideline citation means no recommendation.
VECTOR(DOUBLE, 1536) in IRIS; queried with VECTOR_COSINE for semantic similarity; every agent recommendation is guideline-grounded| Layer | Technology |
|---|---|
| AI Agents | LangChain · GPT-4o-mini · ConversationBufferMemory |
| RAG / Vector Search | InterSystems IRIS Vector Search · text-embedding-3-small · VECTOR(DOUBLE, 1536) |
| FHIR Server | InterSystems IRIS for Health · FHIR R4 (4.0.1) |
| Clinical Standards | FHIR R4 · SNOMED CT · LOINC · UCUM · HL7 |
| Backend | Python 3.11 · FastAPI · httpx · SSE |
| Frontend | Vanilla HTML/CSS/JS · Syne · JetBrains Mono · Lato |
| Infrastructure | Docker Compose · two containers |
| Guidelines | CDC · AHA/ACC · FDA · WHO · KDIGO · AAAAI · ADA |
iris-fhir-template/
├── docker-compose.yml
├── .env ← your secrets (never commit)
├── Dockerfile ← iris
├── Dockerfile.api ← application
├── iris.script ← Setup the FHIR server
├── merge.cpf ← iris
├── module.xml ← ZPM
│
├── src/python/
│ ├── api/
│ │ └── main.py ← FastAPI server, all HTTP routes
│ │
│ ├── agent/
│ │ ├── config.py ← centralised configuration
│ │ ├── dynamic_agent.py ← create custom agent
│ │ ├── orchestrator.py ← LLM router + session management
│ │ ├── triage_agent.py ← patient intake agent
│ │ ├── specialist_agent.py ← condition analysis agent
│ │ ├── pharmacy_agent.py ← medication safety agent
│ │ ├── fhir_agent.py ← FHIR server exploration agent
│ │ ├── fhir_tools.py ← shared FHIR R4 tools
│ │ └── knowledge_base.py ← IRIS Vector Search RAG
│ │
│ └── static/
│ ├── index.html ← Triage Chat
│ ├── dashboard.html ← Analytics Dashboard
│ ├── vitals.html ← Live Vitals Monitor
│ ├── fhir_agent.html ← FHIR Server Agent
└── agent_builder.html ← Build Custom Agent
│
└── data/
├── fhir/
│ ├── demo_patients.json ← FHIR Synthetic Data
│
└── guidelines/
└── clinical_rag_guidelines.csv ← 50 guidelines for RAG
gpt-4o-mini and text-embedding-3-smallgit clone https://github.com/your-username/iris-fhir-agents.git
cd iris-fhir-agents
cp .env.example .env
Open .env and set your OpenAI API key:
OPENAI_API_KEY=sk-your-real-key-here
All other defaults work out of the box with the Docker setup.
docker-compose up -d --build
This starts two containers:
fhir-agents-iris — InterSystems IRIS for Health on ports 32782 / 32783 / 32784fhir-agents-api — FastAPI application on port 8000First startup takes some time while IRIS initialises and the RAG knowledge base embeds 50 guidelines into IRIS Vector Search. Watch the logs:
docker logs fhir-triage-api --tail=50 -f
You should see:
RAG: Loaded 50 guidelines from CSV
RAG: Embedding 50 guidelines into IRIS Vector Search...
RAG: Initialisation complete — 50 new guidelines embedded and stored
INFO: Uvicorn running on http://0.0.0.0:8000
Synthetic FHIR data is loaded during container build from the data/fhir/demo_patients.json file.
| Page | URL |
|---|---|
| Triage Chat | http://localhost:8000 |
| Analytics Dashboard | http://localhost:8000/dashboard |
| Live Vitals Monitor | http://localhost:8000/vitals |
| FHIR Server Agent | http://localhost:8000/fhir-agent |
| Agent Builder | http://localhost:8000/agent-builder |
| Patient ID | Name | Conditions | Key Demo |
|---|---|---|---|
demo-010 |
James Anderson, M/68 | CAD · Hypertension · Atrial Fibrillation | Pharmacy — Warfarin on board + Aspirin allergy (high) · Antiplatelet alternative needed |
demo-011 |
Maria Gonzalez, F/37 | T1DM · Septicaemia · DKA | Emergency — BP 88/54 · Lactate 4.2 · Glucose 22.4 · pH 7.22 · ICU critical care |
demo-012 |
Robert Davis, M/60 | T2DM · HTN · Diabetic Retinopathy · CKD3 | Specialist — HbA1c 7.8% · eGFR 38 · Microalbuminuria · Nephrology + ophthalmology referrals |
demo-013 |
Patricia Taylor, F/75 | HFrEF · T2DM · CKD3 · Hypertension | Emergency — BNP 845 · BP 96 hypotension · eGFR 42 · EF 28% · Decompensated HF |
Click on Browse patients to select the patient OR Type My patient ID is demo-010 to start.
The Analytics Dashboard (/dashboard) provides a real-time population-level view of all clinical data in IRIS, alongside a live record of every FHIR resource written by the AI agents during triage sessions.
Overview
The landing view — four summary stat cards showing total counts of Patients, Conditions, Medications, and Allergies queried live from IRIS FHIR R4. Beneath them, three panels sit side by side:
Patients
A paginated roster of every patient in IRIS. Each row shows Patient ID, name, date of birth, and gender. Click any patient to expand an inline detail panel with four sub-sections: Demographics, Active Conditions, Known Allergies, and Current Medications — all fetched live from FHIR. An Open in Triage Chat button starts a session for that patient directly.
Conditions
A full ranked bar chart of all active conditions across the population. Clicking a condition bar drills down to a list of affected patients with their IDs and names. Useful for population analytics queries such as “how many patients have both diabetes and CKD?”.
AI Observations
Every FHIR Observation resource written by the Triage Agent during chat sessions. Shows the symptom recorded, severity, patient reference, and timestamp. This tab is the live audit trail of AI clinical activity — judges can verify that the agents are genuinely writing structured FHIR data to IRIS, not just generating text.
Service Requests
Every FHIR ServiceRequest written by the Triage and Specialist agents. Shows the referral type, priority (routine / urgent / asap), patient reference, and the clinical reason recorded. Demonstrates the full FHIR write pipeline end to end.
The Live Vitals Monitor (/vitals) is a real-time bedside monitoring simulation that streams patient vitals via Server-Sent Events (SSE), writes every reading to IRIS as a FHIR Observation, and automatically triggers the Triage Agent when critical values are detected — without any user action required.
Five vital sign cards update every 2 seconds, each with a colour-coded status indicator and a mini sparkline chart showing the trend of the last 20 readings:
| Vital | Unit | Status colours |
|---|---|---|
| Heart Rate | beats/min | 🟢 Normal · 🟡 Warning · 🔴 Critical |
| Blood Pressure | systolic/diastolic mmHg | 🟢 Normal · 🟡 Warning · 🔴 Critical |
| SpO₂ | oxygen saturation % | 🟢 Normal · 🟡 Warning · 🔴 Critical |
| Temperature | degrees Celsius | 🟢 Normal · 🟡 Warning · 🔴 Critical |
| Respiratory Rate | breaths/min | 🟢 Normal · 🟡 Warning · 🔴 Critical |
The patient sidebar loads live from IRIS FHIR R4 on every page open via GET /analytics/patients. Whoever is in your FHIR server appears automatically — no hardcoding, no configuration needed. Add new patients to IRIS and they appear on the next page refresh.
Each patient pip in the sidebar turns amber or red as their vitals status changes, giving a at-a-glance overview of all monitored patients simultaneously.
Each reading arrives via GET /vitals/stream/{patient_id} — a long-lived SSE connection. The backend generates a realistic reading every 2 seconds with occasional simulated spikes to demonstrate critical escalation. Every reading — normal or critical — is immediately written to IRIS as a FHIR Observation.
The FHIR Write Counter in the sidebar footer increments with each reading, confirming live persistence to IRIS. The FHIR Observation Writes panel on the right shows the last 20 readings in real time with HR, BP, SpO₂, Temperature, and timestamp per row.
When any vital crosses a critical threshold, the platform automatically dispatches an assessment to the Triage Agent — no user input needed. A 30-second cooldown prevents repeated alerts from the same sustained critical episode.
The complete flow per critical reading:
SSE reading arrives → FHIR Observation written to IRIS
↓
Critical threshold crossed → Triage Agent dispatched
↓
RAG searches IRIS Vector Knowledge Base for relevant guidelines
↓
AI assessment returned → AI Critical Alert Feed panel updated
↓
FHIR ServiceRequest written if referral is warranted
The AI Critical Alert Feed panel shows each automated assessment with:
AI alert polling runs every 5 seconds via GET /vitals/alerts so assessments appear immediately.
Below the vital cards, a scrollable history table shows the last 15 readings with full detail:
| Column | Description |
|---|---|
| Time | Reading timestamp |
| Heart Rate | bpm |
| Blood Pressure | systolic/diastolic |
| SpO₂ | percentage |
| Temperature | degrees Celsius |
| Respiratory Rate | breaths/min |
| Status | Normal / Warning / Critical badge |
| FHIR | ✓ confirming write to IRIS |
Every row confirms the FHIR write — this table is the live audit trail proving that every vital sign is persisted as a structured FHIR Observation in IRIS.
Step 1 — Open http://localhost:8000/vitals. The sidebar loads patients directly from IRIS — no hardcoded list.
Step 2 — Select demo-003 (Mohammed Al-Farsi — HFrEF + BNP 845). His cardiac profile makes critical vital spikes produce particularly detailed Triage Agent assessments.
Step 3 — Wait for a critical spike. The status banner flashes 🚨 CRITICAL — AI Alert Triggered Automatically and within a few seconds the AI Critical Alert Feed panel updates with the Triage Agent’s assessment — zero user input.
Step 4 — Point to the FHIR write counter in the sidebar footer. Show it incrementing every 2 seconds — live proof of continuous writes to IRIS.
Step 5 — Scroll down to the Vitals History table. Show that every reading is captured and every row has a FHIR ✓ confirmation.
Step 6 — Switch to pt-003 (Michael Williams — HFrEF + Digoxin + K⁺ low). Any cardiac critical reading triggers an AI alert that specifically references the Digoxin toxicity risk — demonstrating that the AI is reading and reasoning from the patient’s actual FHIR record, not generating generic responses.
Step 7 — Switch themes using the Dark / Light / Clinical button to show the UI adapts cleanly across modes.
The FHIR Server Agent (/fhir-agent) provides two complementary ways to explore your InterSystems IRIS FHIR R4 server — a live visual Capability Explorer and a natural language AI chat interface that can query patients, run IRIS SQL, and cross-reference clinical guidelines.
AI Chat (default tab)
A conversational interface powered by GPT-4o-mini with 11 FHIR tools. Ask anything about your IRIS data in plain English — the agent fetches, analyses, and synthesises responses grounded in live FHIR data.
FHIR Capability Explorer
A live visual breakdown of everything your IRIS FHIR server supports — loaded directly from the CapabilityStatement at startup. No static data — every chart and table reflects the actual server configuration.
Opens automatically when you navigate to the page. Fetches GET /fhir/metadata and renders the CapabilityStatement into five visual components:
Server info cards
Four cards showing Software name and version, FHIR version, server kind, and endpoint address.
Summary stats row
Five counters: Resource Types supported · Total Interactions · Supported Formats · Operations · Search Parameters.
Interaction Coverage donut chart
A proportional donut showing the breakdown of interaction types (read, search-type, create, update, delete, patch) across all resources.
Resource Categories donut chart
Groups all supported resources into Clinical, Patient, Administrative, Financial, and Infrastructure categories with proportional slicing.
Top Search Parameters bar chart
Horizontal bars showing which resources have the most search parameters — useful for understanding query capability.
Interaction Matrix
A table showing the eight key clinical resources (Patient, Condition, MedicationRequest, Observation, AllergyIntolerance, ServiceRequest, Procedure, Encounter) against all six interaction types with ✓ / · indicators and search parameter counts.
All Supported Resources grid
Every resource the server supports rendered as a card showing its type, interaction tags (read, search-type, create, update, delete, patch), and search parameter count. Includes:
The FHIR Server Agent has access to 11 tools that it calls automatically based on your question:
| Tool | What it does |
|---|---|
get_patient_list |
Fetch all patients from IRIS |
get_conditions |
Get conditions for a patient |
get_medications |
Get active medications for a patient |
get_observations |
Get observations and lab results |
get_capability |
Fetch the CapabilityStatement |
query_iris_sql |
Run direct SQL against IRIS via Atelier REST API |
get_fhir_statistics |
Resource counts across the server |
search_guidelines |
RAG search of the clinical knowledge base |
The sidebar Tools Used panel tracks which tools have been called in the current session, with a call counter and a pulsing indicator when a tool is actively running.
Patient and population queries:
One of the platform’s most powerful features is the Agent Builder (/agent-builder) — a no-code interface that lets anyone design, configure, and deploy a custom AI clinical agent without writing a single line of code. Every custom agent integrates directly into the Triage Chat orchestrator and appears in the Agent Network sidebar alongside the built-in agents.
Open Agent Builder → Choose template or start blank → Write system prompt
↓
Configure tools · Set temperature · Enable RAG
↓
Test against live IRIS FHIR data → Save → Available instantly in Triage Chat
The Agent Builder (/agent-builder) is a no-code interface for designing, configuring, and deploying custom AI clinical agents. Every agent created here integrates directly into the Triage Chat orchestrator, appears in the Agent Network sidebar, and is callable from the same conversation interface as the built-in agents — without writing a single line of code.
| Template | Specialty | Key Capabilities |
|---|---|---|
| 🎗️ Oncology Agent | Oncology | Chemotherapy drug interactions, platinum compound contraindications, tumour board referrals, NCCN/ASCO guideline citations |
| 👴 Geriatrics Agent | Geriatrics | Beers Criteria screening, anticholinergic burden, fall risk, polypharmacy review (≥5 drugs flagged) |
| 👶 Pediatrics Agent | Pediatrics | Weight-based dosing (mg/kg), age-appropriate normal ranges, contraindicated medications (aspirin, codeine, fluoroquinolones) |
| ❤️ Cardiology Agent | Cardiology | HFrEF/HFpEF management, digoxin + electrolyte danger detection, GDMT gap identification, AHA/ACC guidelines |
| 🥗 Nutrition Agent | Nutrition | Drug-nutrient interactions, disease-specific dietary guidance (ADA, KDOQI), warfarin + vitamin K counselling |
Step 1 — Open the Agent Builder:
http://localhost:8000/agent-builder
Step 2 — Click the Oncology Agent template. The system prompt auto-fills with a complete clinical prompt covering chemo drug interactions, NCCN guideline citations, and contraindication checks.
Step 3 — Configure:
0.15 — precise and consistent for drug safetysearch_clinical_guidelines + create_service_requestStep 4 — Click Test Agent. The slide-in test panel opens. Type:
My patient ID is demo-022. Can she receive platinum-based chemotherapy?
The agent fetches Susan Lee’s record from IRIS, finds her Platinum compounds allergy (criticality: high), and responds:
⚠ HIGH RISK: Platinum compound allergy documented for this patient.
Carboplatin and Cisplatin are CONTRAINDICATED.
According to NCCN Guidelines (Relevance: 94%) — patients with prior
platinum hypersensitivity should receive alternative regimens.
Recommend: Oncology MDT review for non-platinum alternative.
— ENGLISH HANDOFF SUMMARY —
Patient: Susan Lee (demo-022) | Breast cancer Stage IIB | Platinum allergy HIGH
Assessment: Platinum-based chemo CONTRAINDICATED — allergy on record
Action: ServiceRequest written to IRIS — oncology MDT referral
Step 5 — Save. The Oncology Agent is now available in:
POST /agents/oncology-agent/test| Setting | Guidance |
|---|---|
| Temperature | 0.1 for drug safety and strict protocols · 0.2 for clinical assessments · 0.3 for counselling and dietary advice |
| System prompt | Start with the specialty, list responsibilities, add clinical rules. The platform auto-appends patient ID injection, language detection, and guideline citation rules. |
| Routing description | One sentence telling the orchestrator when to route to this agent. Be specific: “For cancer, chemotherapy, and oncology questions” works better than “For complex patients”. |
| Tools | Enable create_service_request if the agent should write referrals. Enable create_triage_observation if it should record clinical findings. Disable write tools for read-only advisory agents. |
| RAG | Keep enabled for any clinical agent — guideline grounding prevents hallucinated recommendations. |
Once saved, the orchestrator’s router prompt is updated dynamically. If a user types:
‘’’
My patient has breast cancer and is asking about Tamoxifen side effects
‘’’
The zero-temperature router recognises this as an oncology question and routes it to the Oncology Agent rather than the built-in Specialist Agent — without any configuration change.
The Agent Network sidebar in Triage Chat highlights the active agent in real time, showing the custom agent name, icon, colour, and call count alongside the built-in agents.
Every agent recommendation is grounded by 50 clinical guidelines stored as VECTOR(DOUBLE, 1536) embeddings in IRIS — the same instance that holds your FHIR patient data. No external vector database required.
Step 1 — Load a patient and ask a clinical question:
My patient ID is demo-012
Then ask the below:
“My HbA1c is 7.8% and my kidney function has been declining. What should I do?”
The relevance score is the actual VECTOR_COSINE similarity value returned by IRIS — not a hallucinated reference.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Triage Chat |
GET |
/dashboard |
Analytics Dashboard |
GET |
/vitals |
Live Vitals Monitor |
GET |
/fhir-agent |
FHIR Server Agent |
GET |
/agent-builder |
Agent Builder |
GET |
/health |
Service health check |
| Method | Endpoint | Description |
|---|---|---|
POST |
/chat |
Multi-agent clinical chat — routed to built-in or custom agents |
GET |
/session/{id}/new |
Clear session context and memory |
| Method | Endpoint | Description |
|---|---|---|
GET |
/analytics/summary |
FHIR resource counts |
GET |
/analytics/conditions |
Top active conditions across all patients |
GET |
/analytics/observations |
AI-created triage observations |
GET |
/analytics/service-requests |
AI-created service requests |
GET |
/analytics/patients |
Patient roster — used by Patient Picker modal |
| Method | Endpoint | Description |
|---|---|---|
GET |
/vitals/stream/{patient_id} |
SSE real-time vitals stream |
GET |
/vitals/alerts |
AI-triggered critical alert feed |
GET |
/vitals/snapshot/{patient_id} |
Single vitals reading |
| Method | Endpoint | Description |
|---|---|---|
POST |
/fhir-agent/chat |
FHIR Server Agent natural language chat |
GET |
/fhir-agent/status |
IRIS server connectivity check |
GET |
/fhir/metadata |
FHIR CapabilityStatement proxy |
| Method | Endpoint | Description |
|---|---|---|
GET |
/agents |
List all custom agents |
POST |
/agents/create |
Create or update a custom agent |
GET |
/agents/{agent_id} |
Get a single agent config by ID |
DELETE |
/agents/{agent_id} |
Delete a custom agent |
POST |
/agents/{agent_id}/test |
Test a custom agent with a single message against live IRIS |
Thanks