Patient Graph Integration
The Patient Graph is the primary source of patient context for the Health AI Platform.
In this repository, the integration has three layers:
- Service routes in
apps/patient-graph - Repository and domain helpers in
packages/patient-graph - Typed HTTP consumption in
packages/patient-graph-client
What Patient Graph provides
The service mounts routes for:
- profiles
- labs
- protocols
- adherence
- events
- treatments
- prescriptions
- conversation history
- check-ins
- notifications
- orders
- affiliates
- attribution
- Rimo webhooks
import { PatientGraphClientImpl } from '@loop/patient-graph-client';
const patientGraph = new PatientGraphClientImpl({
baseUrl: process.env.PATIENT_GRAPH_API_URL!,
getAuthToken: async () => process.env.PATIENT_GRAPH_API_KEY!,
});Fetch patient context
The simplest platform integration is to load a profile and then normalize the fields you need into workflow input.
const profileResult = await patientGraph.getPatientContext('user_123');
if (!profileResult.ok) {
throw new Error(profileResult.error.message);
}
const context = {
patientId: profileResult.data.externalId,
data: {
age: 38,
medications: ['metformin'],
biomarker: { TSH: 4.2 },
},
};Fetch protocol and event context
Many workflows need more than a profile.
const [protocols, timeline] = await Promise.all([
patientGraph.getPatientProtocols('user_123', { status: 'active', limit: 10 }),
patientGraph.getPatientTimeline('user_123', { type: 'protocol_started', limit: 20 }),
]);That pattern works well when you want to derive:
- currently active protocols
- recent adherence events
- treatment milestones
- timeline-based triggers
Example: build workflow context from Patient Graph
import { WorkflowEngine } from '@loop/workflow-engine';
import { PatientGraphClientImpl } from '@loop/patient-graph-client';
const patientGraph = new PatientGraphClientImpl({
baseUrl: process.env.PATIENT_GRAPH_API_URL!,
getAuthToken: async () => process.env.PATIENT_GRAPH_API_KEY!,
});
const workflow = WorkflowEngine.load(`
id: thyroid-follow-up-v1
name: Thyroid Follow-Up
version: 1.0.0
steps:
- id: check-tsh
type: check_biomarker
action:
type: check_value
params:
biomarker: TSH
threshold: 2.5
operator: ">"
- id: notify
type: send_notification
condition: "check-tsh.result === true"
action:
type: notify
params:
channel: email
message: "A thyroid follow-up may be needed."
`);
const profile = await patientGraph.getPatientContext('user_123');
if (profile.ok) {
const result = await workflow.execute({
patientId: profile.data.externalId,
data: {
biomarker: { TSH: 4.2 },
medications: ['metformin'],
},
});
console.log(result.stepResults);
}Route example
The service exposes profile reads through the /profiles/:id route.
curl -X GET "https://patient-graph.loop.health/profiles/user_123" \
-H "Authorization: Bearer $CLERK_JWT"The typed client wraps that behind a safer API:
const profile = await patientGraph.getPatientContext('user_123');Access control and ownership
Patient Graph routes are protected by middleware for:
- authentication
- RBAC access checks
- ownership validation
- rate limiting
- audit logging
That makes Patient Graph the right integration layer for platform logic that needs reviewable access to patient state.
Data-shaping guidance
Keep your workflow context small. Pull from Patient Graph, then reduce to the fields the workflow actually needs.
const workflowContext = {
patientId: 'user_123',
data: {
biomarker: {
TSH: 4.2,
hsCRP: 1.8,
},
medications: ['metformin'],
protocolStatus: 'active',
},
};That makes workflows easier to test and avoids coupling a DSL definition to a full API response shape.
Best practices
- Treat Patient Graph as the system of record for patient runtime context.
- Normalize API responses before passing them into workflows.
- Keep auth and ownership checks in the service layer, not in workflow definitions.
- Use the typed client instead of ad hoc fetch calls where possible.
Next steps
- Read API Reference: Patient Graph
- Follow Add Patient Context to a Workflow
- Review Workflow Engine