Add Patient Context to a Workflow
This tutorial shows how to pull patient context from the Patient Graph client, normalize the data, and execute a workflow with that context.
Goal
Build a small flow that:
- fetches patient context
- maps it into
WorkflowContext - executes a workflow against that data
Step 1: Create the client
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!,
});Step 2: Load a workflow
import { WorkflowEngine } from '@loop/workflow-engine';
const workflow = WorkflowEngine.load(`
id: patient-context-demo-v1
name: Patient Context Demo
version: 1.0.0
steps:
- id: check-tsh
type: check_biomarker
action:
type: check_value
params:
biomarker: TSH
threshold: 2.5
operator: ">"
- id: check-warfarin
type: check_contraindication
condition: "check-tsh.result === true"
action:
type: check
params:
medication: warfarin
supplement: Selenium
`);Step 3: Fetch patient context
const profileResult = await patientGraph.getPatientContext('user_123');
if (!profileResult.ok) {
throw new Error(profileResult.error.message);
}Step 4: Normalize into workflow data
In practice, the exact shape will depend on your app and repositories. Keep the workflow-facing object shallow and explicit.
const workflowContext = {
patientId: profileResult.data.externalId,
data: {
biomarker: {
TSH: 4.2,
},
medications: ['metformin', 'warfarin'],
age: 38,
genetics: {
MTHFR: 'C677T/C677T',
},
},
};Step 5: Execute the workflow
const result = await workflow.execute(workflowContext);
console.log(result.stepResults);
console.log(result.errors);Example result
{
"success": true,
"workflowId": "patient-context-demo-v1",
"executedSteps": ["check-tsh", "check-warfarin"],
"stepResults": {
"check-tsh": {
"stepId": "check-tsh",
"success": true,
"result": {
"checked": true,
"biomarker": "TSH",
"value": 4.2,
"threshold": 2.5,
"operator": ">",
"result": true
}
},
"check-warfarin": {
"stepId": "check-warfarin",
"success": true,
"result": {
"checked": true,
"medication": "warfarin",
"supplement": "Selenium",
"hasContraindication": true
}
}
},
"recommendations": [],
"errors": []
}Pattern: separate fetch from decisioning
Keep two layers separate:
- context assembly from service clients and repositories
- decisioning inside the workflow engine
That makes your workflows easier to test.
const assembledContext = await loadPatientWorkflowContext(userId);
const result = await workflow.execute(assembledContext);Common mistakes
Passing raw service responses directly into conditions
Avoid making workflow conditions depend on deeply nested transport payloads.
Prefer:
data: {
biomarker: { TSH: 4.2 },
medications: ['warfarin'],
}Instead of:
data: {
patientGraphResponse: profileResult.data,
}Hiding tool allowlists
If your workflow uses run_tool, pass tools explicitly:
const result = await workflow.execute({
patientId: 'user_123',
data,
tools: ['product-search', 'save-note'],
});Next steps
- See Patient Graph Integration
- Read Testing Workflows
- Keep the DSL Reference nearby