← Building agentic patient workflows

Part 18 of 18 · 5 min read

Run the lab and ship one workflow

Run the local example, reproduce failures and follow a staged implementation handoff.

Arunank Sharan · Kuzushi Labs ·

In this article

I would begin the next implementation phase with one complete administrative workflow: select a verified patient, prepare a slot, review it, book it once and open the resulting appointment. Then attach a separately observable communication step. A small complete path exposes more engineering truth than a large agent catalogue.

The downloadable reference lab was written for this expanded series. It uses Python's standard library and SQLite, runs locally and contains synthetic identifiers. It does not call a model, EHR, messaging service or patient system. Its purpose is to make the action boundary and failure cases executable.

Run it before reading every chapter

Download and unzip the implementation kit, then enter its reference-lab directory:

python3 --version
python3 prm_lab.py
python3 -m unittest discover -s tests -v

Use Python 3.10 or later with an IANA time-zone database available to zoneinfo. The demo creates a temporary database and removes it when finished. You should see one appointment, one outbox event and one provider receipt. UUIDs will differ across runs.

Run the offline lab, repair the source adapters, connect the UI, validate a vendor sandbox and begin a supervised pilot.

Understand the files and boundaries

ArtifactWhat it demonstratesWhat it does not claim
prm_lab.pyProposals, revisions, idempotency, booking transaction, outbox leasesA production web service
tests/test_workflows.pyRaces, rollback, expiry, authorization, callbacks, time zonesLive connector compatibility
benchmark/scenarios.jsonl24 starter scenario cards across 12 familiesA completed model benchmark
benchmark/README.mdProposed 300-case evaluation and reporting contractClinical validation
connectors/Example protocol and resource contractsDeployed MCP, A2A or EHR servers
frontend/A typed destination and latest-response helperA replacement dashboard

The article snippets marked as SQL sketches or interface pseudocode require adaptation. The kit identifies those separately from the runnable Python example. That keeps “copy and run” distinct from “use this contract while integrating.”

Reproduce the approval edit bug class

The first experiment is to prepare one slot, edit the proposal and try confirming the old revision:

proposal = lab.propose(actor, "p-001", "s-001", now=100)
revised = lab.revise(
    actor, proposal["proposal_id"],
    expected_revision=1, slot="s-002", now=105,
)

# This must raise Conflict("stale_approval"):
lab.confirm(
    actor, proposal["proposal_id"], 1,
    proposal["plan_hash"], "old-click", now=110,
)

After catching that expected error, confirm revised with its new revision and hash. The appointment must use s-002. The test suite automates both cases. This directly addresses the original implementation seam where edited action parameters and saved execution steps can differ.

Reproduce a lost response

Run a successful confirmation, discard its returned value and call it again with the same idempotency key. The result should identify the same appointment, and the appointment count should stay at one.

Then repeat with a different proposal under the same key. That must fail. An idempotency record is not a generic permission to reuse a cached success; it binds a request fingerprint to a result.

For delivery, the fake provider can accept a message and then raise a timeout. Repeating the request with its stable event ID returns the same fake receipt. This connector intentionally supports idempotency. A real provider needs its own documented facility or a reconciliation path; the fake is not evidence that every provider is safe to retry.

Give the developer a sequence of deliverables

I would implement the integration in five bounded stages. The durations below are planning windows for a small experienced team, not promises about an unfamiliar EHR procurement or security review.

StageDeliverableExit evidence
Days 1–3: source contractsRepair patient and appointment tool adapters; normalize resultsService contract tests pass without a model
Days 4–7: one UI pathBackend interpretation, editable proposal, confirmation, typed routeBrowser test reaches one persisted appointment
Days 8–12: durabilityVersioned proposals, idempotency, outbox, restart recoveryCrash and duplicate-event tests pass
Days 13–17: one connectorVendor sandbox booking or one messaging channel, receipts and reconciliationContract fixtures and recorded sandbox outcomes
Days 18–20: supervised pilot gateReviewed scenarios, telemetry, rollback and staff handoffAgreed release gates and named incident owner

If the connector contract is unresolved, keep progressing on synthetic fixtures but do not label the integration complete. A vendor's authentication, supported resource profile or booking semantics can change the implementation effort substantially.

Map the work back to the original project

The backend adapter work belongs around the existing orchestrator registry and domain services. The confirmation changes belong in pending-action storage and execution reconstruction. The frontend work replaces the command-bar simulation with the backend contract and connects result cards to allowed routes.

Journey transitions need durable event creation and worker recovery. Provider integration needs one verified path from a communication record to a real receipt. Session context needs explicit use in the agent execution path, and dashboard updates need an actual authenticated subscription rather than a declared provider with its connection disabled.

I would track each of those as an acceptance story with a before/after trace. “Added MCP” or “enabled memory” is too broad to tell a reviewer what became dependable.

Run the release drill with the team

Before the pilot, have one person act as coordinator, one as patient-role simulator and one as operator. Prepare a booking, change the date, deny an old approval, confirm the new proposal, interrupt the worker and recover the result. Then revoke the coordinator's permission and verify that a replay does not disclose or execute the operation.

Finally, create an unresolved connector outcome and hand it to the designated operator. The operator should be able to find the request, determine what remains unknown and reconcile it without reading an entire chat transcript. If that requires developer guesswork, the recovery surface is not finished.

The point of this implementation path is a narrow, demonstrable result. Once one workflow survives corrections, retries, restarts and handoffs, extending the platform becomes a matter of adding well-defined operations to a working foundation.