Move a patient from result-ready to result-discussed on a tracked clock, so nothing sits in a queue waiting for someone to notice it.
Bring your stack to a call and we will scope it against how your business actually runs.
Book a callA lab result arrives in an inbox. Somebody has to see it, a provider has to review it, a decision has to be made, the patient has to be told, and in many cases something has to happen next: a repeat test, a referral, a medication change, a conversation. Every one of those handoffs is a place where a result can stall, and the stalls are invisible. Nobody sends an alert saying "this result has been sitting unreviewed for nine days." The queue just grows, and the oldest items sink to the bottom where they are least likely to be seen.
Then the patient calls. They had blood drawn eleven days ago and heard nothing, so they call the front desk, who cannot discuss results, so they take a message for the nurse, who checks the inbox and finds the result was reviewed six days ago but nobody told the patient. That call costs staff time at three stations and costs the practice credibility, because from the patient's side the practice simply forgot about them. Practices with a manual process typically cannot answer the basic question of how many results are currently waiting on something, which means they cannot see the backlog they are carrying.
The operational failure is a missing clock and a missing owner. The clinical review itself is not automatable and should not be. A provider reads the result and decides what it means. What is automatable is everything around that: making sure the result is assigned the moment it lands, that the assignment ages visibly, that the patient is told something is ready without the result itself traveling through an insecure channel, that a result requiring a conversation gets a booked conversation rather than a voicemail, and that the loop is only closed when the patient has actually been reached. This build is a tracking and chasing system wrapped around a clinical decision it never makes.
One pipeline, Result Follow-Up, one opportunity per result set rather than per test, so a panel is one record.
Deliberately minimal on clinical content. The platform tracks the state of the follow-up process; the result itself lives in the EHR or lab portal.
This is the build where BO's limits matter most. BO's job is to get the patient to the right human or the right secure channel, and nothing else.
Nine workflows. Two rules apply to every one of them: no workflow ever puts result content into a message, and no workflow fires patient-facing messaging on a record tagged disposition-urgent. Build those as global suppression conditions rather than remembering to add them per workflow.
Trigger: order event received from the EHR, creating an opportunity at Order Placed.
Conditions and branches: branch on whether collection happens in-house today or at an external site later. In-house same-day collection skips straight to workflow 2 on the collection event.
Actions in order:
Stop and exit: specimen_collected_at populated, order canceled, or the provider closes it. Never name the test in any of these messages.
Trigger: specimen_collected_at populated; stage moves to Specimen Collected.
Conditions and branches: branch on consent_sms and portal_enrolled. Patients not enrolled in the portal get a portal invitation in the same message, because enrollment is what makes the rest of the build work.
Actions in order:
Stop and exit: result received, or the record reaches Specimen Problem and the redraw branch takes over.
Trigger: result received event, or a staff member logging receipt.
Conditions and branches:
Actions in order:
Stop and exit: reviewed_at populated.
Trigger: Result Review Disposition form submitted, writing result_disposition.
Conditions and branches: this is the switchboard, and the four branches must be genuinely separate paths rather than variations on one message.
Actions in order:
Stop and exit: immediately after routing. This workflow sends nothing and waits for nothing; it exists to make the routing decision explicit and attributable.
Trigger: tag disposition-routine applied.
Conditions and branches: branch on portal_enrolled. Enrolled patients get the portal notification. Not enrolled: send an enrollment prompt, and if they do not enroll within the window, create a task to mail or call rather than leaving them uninformed. Branch on consent_sms and portal-only for channel selection.
Actions in order:
Stop and exit: result viewed, staff log a conversation, or the ladder exhausts into workflow 9. Maximum two automated reminders.
Trigger: tag disposition-discussion applied, or notification_method_required set to call.
Conditions and branches: branch on whether the practice permits a patient-booked discussion slot for this category, or requires an outbound staff call. Where booking is permitted, run both paths in parallel (a booking link and a call task) because either one closing the loop is a win.
Actions in order:
Stop and exit: discussed_at populated, or escalation. Hard cap on automated patient messages at three across the whole ladder, regardless of attempt count. The rest of the ladder is human calls.
Trigger: action_required true with discussed_at populated.
Conditions and branches: branch on action_type. Repeat test offers Repeat Collection; visit offers Follow-Up Visit; referral creates a referral task rather than a patient booking link, since the practice has to initiate it; medication change creates a task for the provider and suppresses patient booking entirely.
Actions in order:
Stop and exit: action scheduled or completed, or the provider closes it as no longer required.
Trigger: result_disposition set to urgent, or a critical flag received with the result.
Conditions and branches: none. This workflow has one path deliberately, because branching logic in an urgent path is a failure mode. It escalates by time until a human acknowledges.
Actions in order:
Stop and exit: a clinician acknowledges and the patient contact is recorded. No automated patient message is ever sent from this workflow. Its whole job is to make a human pick up a phone quickly.
Trigger: stage moves to Unreachable - Escalated, or a record has been open past the practice's maximum age.
Conditions and branches: branch on the disposition carried in. Urgent and action-required records escalate to a named clinician immediately. Routine records go to a weekly review instead, because the risk profile is different and treating them identically buries the ones that matter.
Actions in order:
Stop and exit: the clinician records a decision and closes the record. A record never closes itself out of this workflow by timing out.
Before launch, test four things specifically: that a non-routine disposition cannot trigger the routine notification branch; that disposition-urgent suppresses every patient-facing send; that an opt-out mid-ladder routes to a staff task rather than ending contact; and that the attempt history exports in a readable form. Also read one of your own notification templates out loud as if it were a voicemail heard by a family member. If it discloses anything, rewrite it.
The backlog becomes visible. Before this build, the honest answer to "how many results are waiting on us right now?" is usually a guess. Afterwards it is a board, split by what each result is waiting on: review, notification, patient contact, or a scheduled action. You cannot work a queue you cannot see, and most practices discover the backlog is larger and older than they assumed.
Review stops being the thing that happens last. An assignment that ages visibly, with a named owner and an escalation at a defined threshold, behaves completely differently from an inbox that nobody is individually accountable for.
The loop closes on contact rather than on sending. This is the single most important shift in the build. "We sent a notification" and "the patient knows" are different facts, and a process that treats them as the same will lose patients quietly. By making discussed_at or patient_viewed_at the closing condition, the workflow keeps chasing until something actually happened.
Patient-initiated calls drop sharply, because the expectation-setting message on day one and the notification on the day of review remove the two moments that generate them. Staff stop fielding "did my results come back?" and the nurse line gets its time back.
And the record becomes defensible. Every result carries who reviewed it, when, what they decided, when and how the patient was contacted, how many attempts it took, and what was scheduled. That is a materially better position than a recollection and a sticky note.
This build touches clinical responsibility more directly than any other in the clinical set, so the decisions below need to be made by clinicians and documented before anything is configured.
This is the highest-sensitivity build in the clinical set. The rules below are not refinements; they are the design.
This section describes operational practice, not legal advice. Result communication requirements, timelines, release rules, and the handling of minors and representatives vary by state and by the practice's own clinical governance, and the rules around automatic result release in particular have been changing. Confirm every specific with the practice's own compliance counsel and clinical leadership before going live, and re-confirm whenever your EHR changes its release behavior. To scope this build for your practice, book a call at bookings.appbo.io.
Every build on this page is something we configure, test and hand over with the SOPs your team needs to run it.
Book a call