1. 📌 Overview & Purpose
Goal: Eliminate "tanya simptom semula" di awal konsult. Doktor jimat 2-3 minit/pesakit dgn pre-loaded context + structured briefing card. Pesakit malu/lupa tak masalah — AI dah kumpul + summarise.
Wait-time productivity: Pesakit tunggu giliran tu mengadu kat M1, M2 transform jadi briefing structured. Doctor scan briefing 30 saat — terus masuk topik. Cycle savings: 30 pesakit × 2.5 min = 75 min/hari.
What it is NOT: Bukan diagnosis. Bukan ganti history-taking. Briefing = jump-start, doktor tetap konfirm + clarify face-to-face.
2. 👤 User Stories
Sebagai doktor on-duty, saya nak tengok briefing packet pesakit appointment hari ni — ringkasan simptom + triage + history — supaya saya sedia <30 saat sebelum dia masuk bilik.
Pesakit tambah simptom baru via M1 sambil tunggu giliran — saya nak briefing auto-refresh, tak perlu reload manual.
Saya tap "Acknowledge briefing" → audit log capture saya dah baca · pesakit mobile app reflect doktor dah ready.
Sebagai pesakit, saya nak yakin "doktor dah baca apa saya bagitahu AI" — bila saya masuk bilik dia terus tanya specific, saya tak rasa terbuang masa.
Kalau M1 escalate pesakit MERAH yang dah on-the-way, saya nak briefing dgn HIGH-PRIORITY badge · auto-page sound notification.
Saya guna iPad antara bilik · briefing render mobile-friendly, swipeable cards.
3. ✅ Functional Requirements
appointment.booked from M1 atau manual via M74. ⚙️ Non-Functional Requirements
| Aspect | Target | Notes |
|---|---|---|
| Briefing generation latency | <3s post-trigger | Llama 70B chained · cached patient context |
| Briefing load di doctor UI | <1s | Pre-fetched on appointment book event |
| Real-time refresh latency | <5s | WebSocket push · fallback poll 10s |
| Citation coverage | 100% suggestions | NPRA · MOH CPG · prior encounter source |
| Briefing length | ~300-500 words | Scannable in 30s |
| Token cost / briefing | ~4K tokens avg | Conservative model |
| Concurrent briefing generation | ≥10 simultaneous | Pilot scale |
5. 🗄️ Data Model
| Table | Key fields | Purpose |
|---|---|---|
briefing_packets | id, session_id (M1), encounter_id?, doctor_id, patient_id, packet_json, generated_at, viewed_at, acknowledged_at, version | Per-briefing record |
briefing_revisions | briefing_id, revision_no, change_summary, refreshed_at | FR-2.6 history |
5a. Briefing JSON Schema
{
"briefing_id": "brf_abc123",
"version": 2,
"patient_summary": {
"mrn": "2026-001245",
"age": 45,
"gender": "M",
"preferred_language": "ms"
},
"triage": {
"color": "YELLOW",
"confidence": 0.84,
"reasoning": "Persistent headache 3 days + photophobia",
"red_flags_checked": ["chest_pain", "stroke_signs", "neurological_deficit"],
"red_flags_present": []
},
"chief_complaint": "Sakit kepala 3 hari, sebelah kanan, berdenyut",
"symptom_timeline": [
{ "ts": "2026-05-25T10:00", "symptom": "Onset: throbbing right-side", "source": "patient_pa" },
{ "ts": "2026-05-26T08:00", "symptom": "Photophobia added", "source": "patient_pa" }
],
"history_excerpts": [
{ "encounter_id": "ENC-2025-1115-042", "date": "2025-11-15", "relevant": "Migraine episode · responded to triptan" }
],
"active_meds": [
{ "drug": "Amlodipine 5mg OD", "since": "2024-08" }
],
"allergies": [
{ "substance": "Penicillin", "severity": "MAJOR", "reaction": "rash + urticaria" }
],
"vitals_recent": {
"bp": "138/86 (today)", "hr": 78, "temp": "36.8C", "weight": "78kg"
},
"cdss_hint_top3": [
{ "ddx": "Migraine without aura", "icd10": "G43.0", "confidence": 0.72, "citation": "MOH Headache CPG 2018" },
{ "ddx": "Tension-type headache", "icd10": "G44.2", "confidence": 0.18 },
{ "ddx": "Cluster headache", "icd10": "G44.0", "confidence": 0.10 }
],
"recommended_questions": [
"Tanya: ada aura visual/numbness sebelum sakit?",
"Tanya: keturunan migraine?",
"Tanya: trigger food/stress recent?"
],
"generated_at": "2026-05-26T10:30:00+08:00",
"patient_consent_to_share": true
}
6. 🔌 API + MCP
POST /api/v1/briefings/compose # internal · trigger by event bus
Body: { session_id, encounter_id?, doctor_id }
Response: { briefing_id, ready_at }
GET /api/v1/briefings/{briefing_id} # doctor fetch
Response: full JSON schema
POST /api/v1/briefings/{briefing_id}/acknowledge # doctor ack
→ audit log + patient app status update
GET /api/v1/briefings/{briefing_id}/refresh # force refresh
GET /api/v1/briefings/{briefing_id}/diff # FR-2.15
GET /api/v1/briefings/{briefing_id}/pdf # FR-2.12 export
WebSocket: /ws/doctor/{doctor_id}/briefings # FR-2.6 real-time push
# MCP Tools
briefing_compose Generate briefing from session + history
briefing_refresh Re-compose with new symptom turn
patient_history_fetch Aggregate prior encounters for context
cdss_hint Top-3 DDx from symptom + history
7. 🔁 State Machine
┌──────────────────────┐
│ APPOINTMENT_BOOKED │ trigger from M7 / M1
└──────────┬───────────┘
▼
┌──────────────────────┐
│ COMPOSE_PENDING │ async LangGraph job queued
└──────────┬───────────┘
▼
┌──────────────────────┐
│ AGGREGATE_CONTEXT │ fetch M1 session + 11-section profile + last 3 SOAP + vitals + ADR
└──────────┬───────────┘
▼
┌──────────────────────┐
│ LLM_GENERATE │ Llama 70B compose structured briefing JSON
└──────────┬───────────┘
▼
┌──────────────────────┐
│ VALIDATE │ schema validate · citation enforce · PII strip check
└──────────┬───────────┘
▼
┌──────────────────────┐
│ READY │ persist to DB · push WebSocket to doctor
└──────────┬───────────┘
▼ (M1 update event)
┌──────────────────────┐
│ REFRESH │ regenerate · increment version
└──────────┬───────────┘
▼ (doctor tap acknowledge)
┌──────────────────────┐
│ ACKNOWLEDGED │ audit log · patient app notify
└──────────┬───────────┘
▼ (encounter sign-off)
┌──────────────────────┐
│ ARCHIVED │ TTL 24h post sign-off · audio purge
└──────────────────────┘
8. 🤖 Agent Specification
- Model: Llama 70B Q5 (clinical synthesis quality) · cloud burst gpt-4o
- Memory: Working (Redis · briefing_pending) + Patient long-term (pgvector) + Procedural (CPG)
- Tools: patient_history_fetch · cdss_hint · cpg_lookup · allergy_lookup
System Prompt (template)
You are M2 Pre-Consult Briefing composer dlm MediEco eco.
ROLE:
- Aggregate patient symptom intake (from M1) + medical history + recent vitals
- Compose CONCISE briefing (≤500 words) untuk doctor reading 30 saat
- Output strict JSON per schema
- DO NOT make diagnoses — provide CDSS hint as advisory only
- Highlight RED FLAGS prominently if present
INPUT:
- M1 symptom session full transcript + extractions
- 11-section Patient Profile (allergies · meds · chronic · primary care)
- Last 3 encounter SOAP excerpts (semantic-relevant)
- Recent 3-month vitals
- ADR registry
OUTPUT (strict JSON):
{ chief_complaint, symptom_timeline, triage, history_excerpts,
active_meds, allergies, vitals_recent, cdss_hint_top3,
recommended_questions, citations }
GUARDRAILS:
- PII strip applied (M9 middleware)
- Citation per CDSS suggestion (NPRA/MOH/SOP)
- Confidence score on triage + CDSS
- Recommended questions = open-ended, NOT diagnosis-leading
REMEMBER: Doctor scan 30 saat. Be concise. Highlight unusual/critical.
9. 🎨 UI/UX
- Embedded di M4 Doctor PA encounter detail — top card, default expanded
- Sections: Chief Complaint (heading) · Triage badge (color) · Timeline (visual) · History excerpts · Allergies (alert) · Active meds · Vitals · CDSS hint · Recommended questions
- RED-flag triage = full-width red banner + sound alert
- Citation cards collapsible
- "Acknowledge" button bottom · disabled until 5s minimum read time
- Mobile/tablet swipeable cards (FR-2.8)
- PDF export button untuk offline reference
- Visual diff badge bila refreshed (FR-2.15)
10. ✔️ Acceptance Criteria
- AC-2.1: Briefing generated <3s post appointment booked event
- AC-2.2: Doctor can scan + understand briefing <30s (UAT measured)
- AC-2.3: 100% briefings include citations on CDSS hints
- AC-2.4: RED-flag triage triggers visible alert + audio in <1s
- AC-2.5: Real-time refresh on M1 update arrives within 10s
- AC-2.6: Doctor cycle time savings ≥30% measured pilot vs baseline
- AC-2.7: No PII leak in audit log (M9 enforced)
- AC-2.8: Acknowledge event triggers patient app status update <5s
- AC-2.9: Doc Zam clinical review: 20 sample briefings, ≥18/20 acceptable
11. 🧪 Test Plan
| Tier | Cases | Coverage |
|---|---|---|
| Unit | Briefing schema validate · context aggregator · refresh diff calc · citation enforcer | ≥80% |
| Integration | Event-driven trigger flow · LLM round-trip · WebSocket push · DB persist | 100% paths |
| E2E | 3 scenarios: GREEN routine · YELLOW returning patient · RED escalation | 3/3 pass |
| Clinical | 20 briefing samples by Doc Zam clinical review | ≥18/20 acceptable |
| Load | 10 concurrent briefings · burst 30 in 1 min | p99 <5s |
| Mobile | iPad Safari · Android Chrome · responsive 768/1024px | WCAG AA |
12. 🔗 Dependencies
- Hard: M1 PSPA (input source) · M4 DRPA (UI consumer) · M9 (audit + PII strip) · 11-section Patient model
- Soft: M7 ADPA (manual trigger) · M6 ARXL (allergy registry)
- Event: subscribes to
appointment.booked+patient.symptom.turn
13. 🏃 Sprint Allocation
- Day 1-2: Briefing JSON schema + DB tables
- Day 3-4: LangGraph agent · context aggregator · LLM call
- Day 5: M4 UI integration · embed briefing card
- Day 6: WebSocket real-time refresh
- Day 7: Doc Zam review (20 samples) · final tweak
14. ⚠️ Module-Specific Risks
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Briefing inaccurate (LLM miss key info) | Med | 🟠 Doctor mistrust · revert to old workflow | Doc Zam 20-sample review · iteration · doctor edit feedback loop |
| RED-flag missed in briefing | Low | 🔴 Patient harm | Inherit M1 red-flag classifier · double-check at briefing layer · audit FN rate |
| Briefing overload (too long) | Med | 🟢 Doctor skim · skill decay | Hard cap 500 words · scannable structure · UAT validate |
| Refresh storm (M1 high-frequency turn) | Low | 🟢 Cost / latency | Debounce 30s · diff threshold · only refresh on material change |
| Stale briefing if doctor delay | Med | 🟢 Outdated | Visual "freshness" indicator · auto-refresh on doctor open |