Front desk
“Is Ada Lovelace booked in this week? If not, find her a slot with Dr Patel on Thursday afternoon.”
“Is Ada Lovelace booked in this week? If not, find her a slot with Dr Patel on Thursday afternoon.”
patient-lookup-tool (find Ada) → appointment-lookup-tool (upcoming) → query_entities on practitioners (which id is Dr Patel) → check_availability (Thursday, visibility=all, that practitioner) → asks you to confirm → appointment-book-tool.The booking is a real staff booking: validated like the calendar, confirmation message sent, and the appointment log records Dana as the person who booked it. If the slot went in the meantime the assistant sees slot_unavailable and offers the next one.Needs: calendar access (access_calendar), and not a read-only-calendar role.“Cancel Mr Byron’s 3 pm today, he called in sick — note it as patient-cancelled.”
“Cancel Mr Byron’s 3 pm today, he called in sick — note it as patient-cancelled.”
patient-lookup-tool → appointment-lookup-tool → write_entity (appointments, update, {"status":"cancelled","cancel_note":"Patient unwell — called in"}).A cancellation follows the practice’s rules: an appointment that has already been checked out (processed) cannot be cancelled and the assistant reports the refusal instead of forcing it. Cancellation messaging goes out as normal.“Who’s on the waiting list… actually, who has an appointment tomorrow morning and hasn’t confirmed?”
“Who’s on the waiting list… actually, who has an appointment tomorrow morning and hasn’t confirmed?”
query_entities on appointments (start between tomorrow 08:00–12:00, status=eq:pending, sort start:asc) then, per patient, patient-info-tool for phone/email.A read-only walk; nothing is changed. Under an own-calendar role the list is silently limited to that person’s own diary.“Add a note to Ada’s file: brought a referral letter, filed in reception.”
“Add a note to Ada’s file: brought a referral letter, filed in reception.”
write_entity on patient_logs (create, patient_id, type, data), optionally files if the letter is scanned.Needs: edit_patient. A role without it gets “Your role does not allow you to write patient_logs (requires edit_patient).” — the assistant relays that rather than working around it.“Take £45 cash from Bob for today’s visit and allocate it to his open invoice.”
“Take £45 cash from Bob for today’s visit and allocate it to his open invoice.”
query_entities on invoices (patient_id, state=eq:unpaid) → write_entity on payments (create, amount "45.00", cash payment_type_id) → write_entity on payment_allocations (create).Card payments cannot be recorded through the API (card_payment_not_allowed) — the assistant will say so and point to the terminal flow in PracticeHub.Needs: view_all_patient_financial_data to see invoices, edit_patient_financials to record the payment, allocate_payments to allocate. Missing any one → a clear refusal naming it.Practitioner
“What does my afternoon look like, and has anyone got an outstanding balance?”
“What does my afternoon look like, and has anyone got an outstanding balance?”
query_entities on appointments (today, practitioner_id = me) → patient-info-tool per patient (balance is on the patient record).Under an own-calendar role the assistant only ever sees this practitioner’s appointments; under own-patients, only patients they are default practitioner for. The balance figure itself is visible (as in the app); the invoices and payments behind it need view_all_patient_financial_data — without it the assistant can say “Bob owes £45” but not list what for.“Move Ada’s 10:00 to 10:30, same day.”
“Move Ada’s 10:00 to 10:30, same day.”
check_availability with rescheduled_appointment_id (so her current slot isn’t counted as busy) → appointment-reschedule-tool.A read-only calendar role can look but not move: “Your role has read-only calendar access.” An own-calendar role can move it within their own diary but not into a colleague’s.“Show me Bob’s last three visits and any notes I left.”
“Show me Bob’s last three visits and any notes I left.”
appointment-lookup-tool (upcoming_only=false) → query_entities on patient_logs.Clinical notes are not on the API or MCP — the assistant can see appointment history and patient-log entries, never the clinical record. That is a platform boundary, not a permission.Owner / manager
“How many new patients did we get last month, and where did they come from?”
“How many new patients did we get last month, and where did they come from?”
query_entities on patients (created between the month bounds — UTC) grouped by referral_source_id, then referral_sources for the names.Account owners hold every permission, so nothing is filtered. For very large sets the assistant pages through (page_size 100) — ask it for a summary rather than a list.“Which appointment types are bookable online, and what do we charge?”
“Which appointment types are bookable online, and what do we charge?”
query_entities on appointment_types (online_booking=eq:1, active=eq:1).Changing one (write_entity update on appointment_types) needs access_settings — an owner has it; a front-desk role usually doesn’t.“Give me every unpaid invoice older than 30 days with the patient’s email.”
“Give me every unpaid invoice older than 30 days with the patient’s email.”
query_entities on invoices (state=eq:unpaid, invoice_date=lt:…, sort invoice_date:asc) → patient-info-tool per patient.Read-only; needs view_all_patient_financial_data. Ask the assistant to draft the reminder emails — sending them is outside the API by design.What every recipe has in common
- The assistant asks before it writes. Good assistants confirm a booking, cancellation or payment before calling a write tool; if yours doesn’t, say “always confirm before booking or cancelling” at the start of the conversation.
- Refusals are the practice’s rules.
409 appointment_rule(already processed, cancelled…),slot_unavailable,group_full,billing_ruleare the same refusals staff get in the app. The assistant should relay the message, not retry. - Permissions are the person’s. A connector never does more than the team member could in PracticeHub: role permissions gate reads/writes/deletes; own-patients / own-calendar roles are ringfenced; account owners see everything. Withdrawing Connect AI apps from the role, or deactivating the user, cuts the connector off on the next call.
- No clinical notes, no card payments, no messaging. Those are outside the API’s scope on purpose (Resources).
Building your own agent
For an unattended agent (a booking bot on your website, a nightly assistant), use an API key on the same MCP endpoint rather than someone’s connector: the agent then acts as the integration, with the key’sread/write abilities, and appears in the audit trail by its integration name. Give it a system prompt that states the clinic timezone (from GET /me), tells it to call check_availability before appointment-book-tool, to always confirm destructive actions, and to relay any refusal verbatim. The tools page is the contract it will read.