Skip to content

The AI-native operating system for a dental practice — asked work in chat, unprompted work in the inbox, every write on the same governed rails.

HIPAA compliant
vella · ask
Vella looking up demo patient Falcon Dent and proposing the next step

What it is

Canopy is the company. Vella is what staff actually use — a coordinator talks to her in chat, the inbox holds the work she started on her own, and the rest of the practice (schedule, eligibility, claims, remits) sits on the same desk.

Underneath is the OSCAR platform: an event-driven system on Azure where agents and humans write through the exact same door — same risk score, same policy, same hash-chained audit. Autonomy is first-class. A back door is not.

In action

Screens from a synthetic demo practice. No real patients.

Ask Vella

A coordinator types the way they talk — look up a patient, check coverage, draft a claim. Vella answers on a card, and irreversible steps stop on a confirm she will not skip.

vella · ask
Vella chat looking up demo patient Falcon Dent

Coverage before the chair

The eligibility board is the morning list: who is verified, who has no coverage on file, who needs a live check. A 270/271 is one action, and the result stays on the visit.

vella · elig
Eligibility worklist for the demo practice

Claims, acks, money

Once a claim leaves, this is the desk: 999s, 277s, unpaid, rejected. Open a row for the EDI, the ack, and the remit — the same trail Vella reads when someone asks where a claim is.

vella · claims
Submitted claims worklist with clearinghouse acknowledgements

Nothing she can do is hidden

What Vella can do is a live catalogue — playbooks she always follows, skills she looks up, and an honest badge for shipping versus still being built. Read from the system, so it cannot go stale.

vella · know
What Vella can do — live playbook catalogue

More of the desk

Vella
Ask VellaThe empty stateEligibilityClaimsPatientsWhat Vella can do
Ask Vella

What she can do

Patient lookup

Name in, the chart and coverage on a card — no tab-hopping through the roster.

Eligibility & coverage

What is on file, then a live 270/271 when the coordinator needs the payer's word.

Draft and send claims

A clean 837D from the visit, CDT rules before it leaves, confirm-gated transmit.

Rejections & remits

999/277 diagnosis and 835 reconciliation land as cards in the inbox, not email.

Schedule lifecycle

Book, confirm, check in, reschedule, no-show, cancel — every verb is a governed write.

Same rails as a human

Agents never get a back door. Risk score, policy, audit hash-chain — identical path.

Impact

$144K
off a data contract

Beyond the engineering, I independently negotiated $144,000 off the company's data contract.

System architecture

Eight bounded services communicate through an event backbone. State never changes by side effect: writes go through a single governed entry point that commits the change, an audit record, and an outbox event in one atomic transaction. A relay publishes those events to Service Bus, and downstream services react.

Eight bounded services, one governed door
  • Governed-write entry point

    Every state change flows through one door. Each write is an atomic triple-write inside a single transaction — the state mutation, an immutable audit record, and an outbox event — and is scored by a risk engine + policy sidecar before it commits.

  • Agentic reasoning

    Assembles context, reasons with an LLM, and executes tool calls under the same governance rules as humans. Authenticates to Azure OpenAI via managed identity.

  • Real-time risk scoring

    Consumes the operational event stream and computes a live Practice Risk Score across six weighted dimensions. The gateway reads it live to elevate verdicts on risky actions.

  • Practice snapshot

    Maintains a capability-filtered, token-budgeted live view of each practice in Redis, kept fresh by watchers on the event stream — the context layer agents read from.

  • Transactional outbox

    Polls the outbox table and publishes events to Service Bus with exactly-once intent. Dialect-aware row locking lets workers scale concurrently without double-publishing.

  • Real-time fan-out

    Streams events to live clients over WebSockets (Azure Web PubSub) with per-session ordered replay after reconnect.

  • Revenue cycle

    The dental claims pipeline — eligibility, 837D assembly, clearinghouse submission, and remittance ingestion (detailed below).

  • DICOM pipeline

    A DICOMweb store (Orthanc) and a web-based radiograph viewer (OHIF) for dental imaging, wired into the same platform.

Data flow

One write, one rulebook. Every governed change — whether a clinician posts a procedure, an agent submits a claim, or an ERA arrives from a payer — moves through the same path. Nothing bypasses it.

One governed write, end to end
  • 01

    A human action or an agent tool call arrives at one of the bounded services. Both paths converge on the same governed entry point — same writes, same scoring, same audit. There is no back door.

  • 02

    A policy sidecar evaluates the action against versioned policy that defaults to deny, then a deterministic risk engine bands it. The live Practice Risk Score is read here too — and it can only escalate a verdict, never relax one.

  • 03

    The state row, a hash-chained audit row, and an outbox row all commit inside one transaction. If any of the three fails, none of them lands — so the event backbone can never announce a change that didn't actually happen.

  • 04

    A background worker polls the outbox with dialect-aware row locking and publishes the canonical event, keyed so the broker dedupes it. Workers scale concurrently without ever double-publishing.

  • 05

    Subscribers receive the event through topic filters generated from each service's manifest — routing is declared, never hand-wired. In parallel the delivery service streams it to live clients with per-session ordered replay after a reconnect.

  • 06

    The revenue-cycle engine assembles a claim, the practice snapshot refreshes, the risk score re-scores, the UI re-renders. Every subscription is idempotent, so a redelivery changes nothing.

  • 07

    When a reaction leaves the building — a claim to a clearinghouse, a benefit check to a payer — the responses come back in as new governed events through this same path, never as ad-hoc side effects.

Revenue cycle engine

The RCM engine turns clinical work into clean, payer-ready claims and tracks them end to end. The pipeline is deliberately pure — claim assembly does no I/O — so the same logic runs identically from a CLI, an API call, or a batch job, and every output is deterministic and testable against fixtures spanning the full dental code set.

One claim, one full lap — out through the walls and back as three different answers
  • 01

    Real-time benefit checks via X12 270/271 before work begins, so coverage is known up front.

  • 02

    A clean domain model compiles into a deterministic 837D EDI file through a pure builder — no I/O — so the same pipeline runs from CLI, API, or batch.

  • 03

    Per-procedure validation across the full CDT taxonomy (D0100–D9999): allowed teeth, required surfaces, and age gates are enforced before submission.

  • 04

    A canonical receiver/payer table routes each claim to the right clearinghouse and carrier, with hard guards against ID collisions.

  • 05

    Claims are delivered to the Vyne clearinghouse over pinned-key SFTP, with deterministic, collision-proof filenames safe for parallel retries.

  • 06

    Functional acks (999) and claim-status responses (277CA) are ingested, de-duplicated, and traced back to the originating claim.

  • 07

    Electronic remittance advice (835 ERA) is parsed and reconciled — paid amounts, patient responsibility, and per-claim detail preserved for posting.

The risk loop

Every other path on this page has two ends. This one closes. The events a practice generates move its risk score, the score raises the floor on what the gateway will approve without a human, and that floor constrains the very activity that produced the events — so the system gets more cautious exactly where it has been going wrong.

The only closed loop in the platform
  • 25%

    Moves when a claim comes back denied. The heaviest dimension, because a denial is the earliest honest signal that something upstream — coding, coverage, eligibility — was wrong before the claim ever left.

  • 20%

    Moves when a payment fails to reconcile. Money that arrived but can't be matched to what it was paying for. Weighted hard and escalated fast: an unreconciled payment is the one error that compounds silently.

  • 20%

    Moves when an adjustment is posted. Write-offs and adjustments are legitimate, but they're also where revenue quietly leaves. Volume and pattern matter more than any single entry.

  • 20%

    Moves when a patient doesn't show. No-shows and cancellations, which drive both the schedule and the forecast. The one dimension driven by patients rather than by the practice.

  • 10%

    Moves when a compliance gap is detected. Credentialing and compliance gaps that would invalidate work already performed.

  • 5%

    Moves when an order is approved. Supply and vendor commitments. The lightest weight — it moves slowly and rarely surprises anyone.

Infrastructure

The whole estate is Azure-native and declared as code in Bicep — reproducible per environment, with no click-ops. CI/CD runs three sequential gates on every change: lint & tests, manifest and event-filter validation, then idempotent SQL migrations, container build, deploy, and smoke tests.

The estate, and the six-gate pipeline that produces it
  • Every service runs as an independently-scaled container app

  • The entire estate is declared as code, modular and parameterized per environment

  • Entra-only authentication — no SQL passwords anywhere

  • The event backbone; topic filters generated from service manifests

  • Live practice snapshots, risk scores, and session state

  • Real-time WebSocket delivery to clients

  • LLM reasoning for the agent orchestrator, via managed identity

  • Secrets isolated from code and never logged

  • Immutable archive for the audit ledger

  • VNet + private endpoints in front of data services

Built with

PythonFastAPIAzure Container AppsBicepAzure SQL / T-SQLService BusRedisWeb PubSubAzure OpenAIOpen Policy AgentDockerGitHub ActionsX12 EDIDICOM