Inspiration

Patients forget 40% to 80% of medical information immediately after leaving a consultation, and nearly half of what they do remember is recalled incorrectly (Journal of the Royal Society of Medicine). Separately, one of the most replicated findings in clinical medicine is that patient history, what the patient actually reports, drives roughly 80% of a diagnosis, more than physical exams or lab tests combined. The input that matters most to a diagnosis is also the input most likely to be lost before a doctor ever hears it.

This is sharper where access to care is limited. Africa averages 2.6 doctors per 10,000 people, and only seven African countries meet the WHO's recommended ratio of 10 per 10,000. In parts of sub-Saharan Africa the ratio drops closer to 2 per 10,000, against 19 in the Americas and 32 in Europe. People already turn to AI chatbots first when something feels wrong, often hours or days before a real appointment is possible. That conversation sits in a chat history, but it carries no weight anywhere it would actually matter, not to a doctor who has no way to verify it, and not to anyone who later needs proof a medical event occurred without being handed a patient's full history to check it.

What it does

A patient opens Handoff and describes symptoms to an AI assistant. Mid-conversation, the AI gives first aid guidance and surfaces a shortlist of matching professionals pulled live from Handoff's network. Once the conversation is complete, it's structured into a summary: symptoms, onset, progression, severity, urgency flag, and committed on Midnight, hashed and timestamped, immediately.

The patient routes that commitment to a professional from the shortlist. The professional opens their dashboard, reads the full intake exactly as reported, and files their own attestation, a short clinical conclusion tied to that specific intake commitment.

From there, the same underlying record serves two audiences differently:

  • The routed professional holds permanent, verifiable access to the full intake they reviewed.
  • Anyone verifying that patient's claim, an insurer processing a reimbursement, a school checking an absence, queries the professional's attestation directly and receives a single fact: confirmed or not, dated, nothing else.

Two commitments, two circuits, two audiences. Neither path crosses into the other.

How it works

Intake. The AI structures the conversation into a fixed schema (symptoms, onset, progression, severity, urgency) and calls commitIntake(hash, timestamp, patientAddress). The structured JSON itself stays client-side; only its hash and metadata are written to the ledger.

Registry-driven matching. Professionals onboard to Handoff by registering an on-chain credential in the professional directory contract. The AI's mid-conversation recommendation queries this same directory, so a suggested doctor is always one who can legitimately receive the intake, not a static list maintained separately from the access-control logic.

Attestation. The routed professional calls commitReport(intakeId, verdict, timestamp). This call only succeeds if the caller's address exists in the professional directory. The resulting report commitment is linked to the intake commitment it was reviewed against, but is a structurally separate record.

Disclosure. Two disclosure circuits exist. One resolves against intake commitments and accepts calls only from the address the patient routed the intake to. The other resolves against report commitments and returns a single boolean plus a date, callable by any verifying party the patient authorizes. There is no circuit that accepts a verifier query and returns intake data, that path was never built, not filtered out.

How we built it

The contracts are written in Compact for Midnight.

  • handoff.compact implements the intake commitment, the report commitment, and the two disclosure circuits.
  • registry.compact implements the professional directory: registration, credential storage, and the eligibility check commitReport depends on.
  • api.ts wraps the Midnight SDK, hashes structured intake summaries client-side before they touch the ledger, and manages wallet-scoped private state per patient session.

The AI layer is a single cloud LLM API call per conversation. It receives the patient's free-text description, returns the structured intake JSON, and, in the same pass, queries the registry contract to generate first aid guidance and professional matches grounded in real, eligible providers. The model has no write access to the ledger and no channel to any party beyond the requesting client.

The frontend is React/Next.js with four surfaces: the intake chat with inline first aid and doctor suggestions, a commit confirmation view showing the on-chain hash and timestamp, a professional dashboard for reviewing routed intakes and filing reports, and a verifier screen that only ever calls the report-disclosure circuit.

Challenges we ran into

Our first pass at the contract used a single commit function and a single disclose function, gated by an authorization-level parameter. It worked in testing, but it meant a verifier and a professional were calling the same code path with different permission flags, one misconfigured flag away from a verifier pulling intake data. We rebuilt this as two independent commitment types with two independent circuits instead of one circuit with branching permissions, so a verifier's call is written against a schema that doesn't include intake fields at all.

Wiring the AI's professional recommendations to the live registry, instead of a fixed list, meant the suggestion step now depends on a contract read completing before the AI can finish its response, which introduced latency we hadn't accounted for in the chat flow. We ended up caching the registry read per session rather than per message, since eligible professionals don't change mid-conversation.

Accomplishments that we're proud of

A disclosure boundary enforced by circuit design rather than permission checks, verifier queries and intake data live in schemas that never intersect. A working path from a natural-language conversation to a committed, tamper-evident record, to a professional's own linked attestation, to a minimal verifiable fact, all traceable back to a single original commitment.

What we learned

A professional and a verifier were never going to need the same data with different amounts of blurring. They needed different data, full stop. Once we stopped trying to build one flexible disclosure function and instead built two narrow ones, the correctness of the system became something the contract guaranteed structurally, not something we had to keep re-checking in application logic.

What's next for Handoff

Open registration for the professional directory, replacing the current curated allowlist with real credential verification. Extending the same commitment pattern to pharmacies, so an attestation can also authorize a checkable prescription. Allowing third-party AI health tools to submit structured intake directly into commitIntake, so the attestation layer isn't limited to conversations that start inside Handoff's own chat.

Built With

Share this project:

Updates