Put the chart behind a port
Voice tools — find, book, confirm, cancel, eligibility — call a small adapter interface, never the chart directly. A local mock mirrors the real field names, so every flow runs end to end with no third-party keys.
Going live swaps one implementation: the same calls hit the real practice-management API. Routes, prompts, and the dashboard never change, because they never knew which side of the port they were on.
Swap the voice without touching routes
A tiny provider interface sits between the app and telephony: place calls and send texts through it, and keep a mock that writes scripted transcripts to the database. Without carrier keys the whole product still demos — every call, text, and booking lands in the store.
A demo safety rule is enforced in code, not in a runbook: real calls and texts only ever go to a verified demo number. Every other patient stays simulated, with a transcript written so the dashboard still looks alive.
// Pattern: Narrow ports around the chart and the voice
interface PMSAdapter {
readonly findPatient: '(name, phone) => chart record';
readonly slots: '(provider, day) => bookable times';
readonly book: '(patient, slot) => appointment with audit entry';
}
interface VoiceProvider {
readonly placeCall: '(to: VerifiedNumberOnly) => call handle';
readonly simulate: '(scenario: string) => scripted transcript in DB';
}Stream every write to the ops room
Each booking, verification, and message emits an event through an in-process bus, persisted to an events table and streamed to the dashboard over server-sent events. KPIs move while the call is still happening.
That is the healthcare-data discipline applied to voice operations: ingestion, access, and audit designed around the data’s sensitivity.
Have a similar architectural challenge?
Talk with our engineering team about trade-offs, cutovers, and sizing for your system.
