Examples and Instructions
Last Updated: June 25, 2026
The sample/ folder contains a complete, runnable example model. It builds on top of the Careflow Broker base image, receives sample data via a callback, and (optionally) writes results to S3.
sample/
├── Dockerfile # builds FROM careflowhealth/careflow-broker:latest
├── main.py # minimal callback example
├── main_test.py # callback example with multi-bucket S3 usage
├── README.txt # integration & build instructions
└── local_dev/
├── config.yaml # set environment: 'local' for local sample-file runs
├── docker-compose.yaml # mounts config + sample data
└── sample_data_payload.jsonSetting up Docker
1. Pull the Careflow Broker base image
docker pull careflowhealth/careflow-broker:latest
2. Build your model image
The sample Dockerfile derives from the base image and copies in your model code:
FROM careflowhealth/careflow-broker:latest
COPY main.py /careflow/main.py
CMD ["python3", "main.py"]Build it (no Azure Artifacts PAT is required; the Careflow dependencies are pre-bundled in the base image):
cd sample/
docker build --tag careflowhealth/test-ai-model:latest .3. Run the container (local development)
Use local_dev/docker-compose.yaml, which mounts config.yaml and the sample data file into /careflow/config/. For local sample-file runs, set environment: 'local' in config.yaml before starting the container:
cd sample/local_dev/
# Update the volume paths in docker-compose.yaml to match your local filesystem first
docker compose upThe config.yaml must be mounted for the container to start – the Careflow library requires it at import time. When deployed via the Careflow Orchestrator, the config.yaml is generated and mounted automatically; you do not provide it yourself.
4. Check the Logs
docker ps
docker logs -f <container_name_or_id>5. Access the Container
docker exec -it <container_name_or_id> /bin/bash6. Verify the Careflow library version inside the container
docker exec -it <container_name_or_id> python3 -c "import careflow; print(careflow.__version__)"Instructions
Minimal local model (main.py)
from careflow import logger, start, config, s3
def test_server_with_callback():
logger.info(config.get())
def callback(data):
logger.info(f"Received data: {data}")
# implement data processing here
# publish results via careflow.send(...) or write to S3 via careflow.s3
start(callback)
if __name__ == '__main__':
test_server_with_callback()In local mode, start(callback) reads the sample data file config/<SUB_TOPIC>.json and feeds it into the callback once every local.TIMER seconds. For the sample, SUB_TOPIC: sample_data_payload, so the file is sample_data_payload.json:
{
"data_payload": "test data payload sent from JSON file for local dev testing"
}Use Case: Local Testing with a Templated Sample Feed
When you need to simulate a stream of varying values (rather than a single static payload), start(callback, sample_parser) supports placeholder substitution in the sample data file. The sample_parser argument supplies the values to substitute on each interval.
The file names below (start.py, FHIR sample, etc.) are illustrative — they are not shipped in the repo. They demonstrate the templating capability of SampleService.
Setup
- Set
environment: 'local'inconfig.yaml. - Set the interval via
local.TIMER(e.g.local.TIMER: 1feeds a new value every second). Setlocal.LOOP: true to repeat the parser list from the start once exhausted. - The sample data file (
config/<SUB_TOPIC>.json) is a JSON template containing placeholders.
Supported placeholders (handled by SampleService):
| Placeholder | Replaced with |
|---|---|
%NOW% | Current UTC timestamp (ISO 8601, e.g. 2024-08-08T11:21:54Z) |
%NOW_SECOND% | Current Unix epoch seconds |
%<KEY>% | The value of the named key from the current sample_parser entry |
%IF(<KEY><op><n>)%...%ENDIF% | The enclosed block, only if the condition is true (operators: < > == <= >= !=) |
If a parser value is a {"min": x, "max": y} dict, a random integer in that range is substituted.
Example (start.py)
import careflow
def callback(data):
careflow.logger.info(f"Received data: {data}")
if len(data) > 0:
spo2 = float(data[0]['valueQuantity']['value'])
pulse = float(data[1]['valueQuantity']['value'])
careflow.send({"data": spo2 + pulse})
# sample_parser is a list of dicts; one entry is consumed per interval
parser = [
{"SPO2": 98, "PULSE": 72},
{"SPO2": 88, "PULSE": 110},
]
careflow.start(callback, parser)In the sample data template, %SPO2% / %PULSE% are replaced from each parser entry, %NOW% is replaced with the timestamp, and an %IF(SPO2<90)%...%ENDIF% block can conditionally inject an “abnormal” interpretation.
Process Overview
- Ensure
environmentandlocal.TIMERare configured. - The
callbackis where the sample data is fed and processed — once per interval. - Use
careflow.send(...)to transmit processed results.
