> ## Documentation Index
> Fetch the complete documentation index at: https://build.practicehub.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Recipes for AI assistants

> What a connected assistant can actually do for a front desk, a practitioner and an owner — realistic prompts, the tools they use, and where role permissions draw the line

Once a team member connects Claude or ChatGPT to a clinic ([Connectors](/mcp/connectors)), the assistant works through the [tools](/mcp/tools) with that person's PracticeHub role. These recipes show what that looks like in practice: the request as someone would type it, the tools the assistant reaches for, and what happens when the role doesn't allow it. Use them to set expectations with your team — and as a starting point for your own custom agents on an API key.

<Note>
  Everything below is a **conversation**, not code. Assistants decide which tools to call from the tool descriptions, so the same request may take a slightly different route; the outcomes and refusals are what the platform guarantees.
</Note>

## Front desk

<AccordionGroup>
  <Accordion title="“Is Ada Lovelace booked in this week? If not, find her a slot with Dr Patel on Thursday afternoon.”" defaultOpen>
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Cancel Mr Byron’s 3 pm today, he called in sick — note it as patient-cancelled.”">
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Who’s on the waiting list… actually, who has an appointment tomorrow morning and hasn’t confirmed?”">
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Add a note to Ada’s file: brought a referral letter, filed in reception.”">
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Take £45 cash from Bob for today’s visit and allocate it to his open invoice.”">
    **Tools:** `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.
  </Accordion>
</AccordionGroup>

## Practitioner

<AccordionGroup>
  <Accordion title="“What does my afternoon look like, and has anyone got an outstanding balance?”">
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Move Ada’s 10:00 to 10:30, same day.”">
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Show me Bob’s last three visits and any notes I left.”">
    **Tools:** `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.
  </Accordion>
</AccordionGroup>

## Owner / manager

<AccordionGroup>
  <Accordion title="“How many new patients did we get last month, and where did they come from?”">
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Which appointment types are bookable online, and what do we charge?”">
    **Tools:** `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.
  </Accordion>

  <Accordion title="“Give me every unpaid invoice older than 30 days with the patient’s email.”">
    **Tools:** `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.
  </Accordion>
</AccordionGroup>

## 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_rule` are 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](/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's `read`/`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](/mcp/tools) is the contract it will read.
