AI Service API Reference

The AI Service exposes a REST API on port 4003. All endpoints (except /health) require a valid session token issued by the SSO service, passed as Authorization: Bearer <token>.


Request Lifecycle (Sequence Diagram)

The following diagram shows the end-to-end lifecycle of a clinical query through the AI Service, required for IT audit request traceability.

@startuml
actor "Patient" as Patient
participant "Patient Portal" as App
participant "AI Service\n:4003" as API
participant "SEA-LION Guard" as Guard
participant "Orchestrator" as Orch
participant "Agent (A1-A6)" as Agent
participant "LLM\n(med-r1)" as LLM
database "Medplum\n(FHIR R4)" as FHIR
database "Audit Log" as Audit

Patient -> App : Sends message
App -> API : POST /chat\n{patientId, message}

API -> Audit : Log request\n(AuditEvent)

API -> Guard : checkInput(message)
Guard --> API : PASS

API -> Orch : classify(message)
Orch --> API : intent = "medical_query"

API -> Agent : process(input)
Agent -> FHIR : Search Condition,\nMedicationRequest,\nObservation
FHIR --> Agent : FHIR Bundle
Agent -> LLM : Prompt\n(de-identified context)
LLM --> Agent : Raw response

Agent --> API : AgentOutput

API -> Guard : checkOutput(response)
Guard --> API : PASS

API -> Audit : Log response\n(AuditEvent)

API --> App : 200 {reply, agentsUsed,\nguardDecision}
App --> Patient : Display response
@enduml


Base URL

http://localhost:4003

Authentication

Include the SSO token in all requests:

Authorization: Bearer <sso-token>

Health Check

GET /health

Returns service health. No authentication required.

Response 200

{ "status": "ok", "version": "1.0.0" }

Chat (Companion Agent A1)

POST /chat

Send a message to the AI Companion and receive a response.

Request body

{
  "patientId": "patient-123",
  "message": "What are the side effects of metformin?",
  "language": "en",
  "sessionId": "session-abc"
}

Field

Type

Required

Description

patientId

string

Yes

FHIR Patient ID

message

string

Yes

Patient’s message text

language

string

No

en, zh, ms, ta (default: en)

sessionId

string

No

Existing session ID for context continuity

Response 200

{
  "reply": "Metformin commonly causes nausea and diarrhoea, especially when first starting...",
  "sessionId": "session-abc",
  "agentsUsed": ["A1", "A2"],
  "guardDecision": "PASS",
  "language": "en"
}

Nudges (Nudge Agent A3)

GET /nudges/:patientId

Retrieve pending nudges for a patient.

Response 200

{
  "nudges": [
    {
      "id": "nudge-001",
      "type": "medication-reminder",
      "message": "Your morning metformin dose is due.",
      "severity": "info",
      "createdAt": "2026-03-19T08:00:00+08:00"
    }
  ]
}

POST /nudges/:patientId/dismiss

Dismiss a nudge after the patient has acknowledged it.

Request body

{ "nudgeId": "nudge-001" }

Response 200

{ "dismissed": true }

Pre-Visit Summary (Insight Agent A5)

POST /patients/:id/previsit-summary

Generate or retrieve a pre-visit summary for an appointment.

Request body

{
  "appointmentId": "appt-456",
  "lookbackDays": 30
}

Response 200

{
  "compositionId": "Composition/comp-789",
  "sections": [
    { "title": "Medication Adherence", "content": "..." },
    { "title": "Biometric Trends", "content": "..." },
    { "title": "Suggested Discussion Points", "content": "..." }
  ],
  "generatedAt": "2026-03-19T08:00:00+08:00"
}

Adherence Metrics (Measurement Agent A6)

GET /metrics/:patientId/adherence

Retrieve Proportion of Days Covered (PDC) for all active medications.

Response 200

{
  "patientId": "patient-123",
  "period": { "start": "2026-02-17", "end": "2026-03-19" },
  "medications": [
    { "name": "Metformin 500mg", "pdc": 0.85, "status": "on-track" },
    { "name": "Lisinopril 10mg", "pdc": 0.60, "status": "needs-attention" }
  ],
  "overallPdc": 0.72
}

Error Responses

Status

Code

Description

400

INVALID_REQUEST

Missing or malformed request body

401

UNAUTHORIZED

Missing or invalid token

404

NOT_FOUND

Patient or resource not found

422

GUARD_BLOCKED

Request blocked by SEA-LION Guard

500

INTERNAL_ERROR

Unexpected server error

Error envelope

{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "patientId is required"
  }
}