← Choice Health scheduler-use-cases-and-capability-scope.md raw .md

Scheduler Use Cases & Capability Scope — input for Fable 5's design doc

Date: 2026-07-02 Purpose: define the use cases we want the phone/voice scheduler to support, map each to the capability that already exists (or must be built), and give Fable 5 enough to design the tutorial flows + the "offers are quotes" architecture. Companion: scheduler-demo-problem-statement.md (why the current demo is fragile). This doc is the forward-looking "what to build."


0. TL;DR — is there enough to design from?

Yes. The calendar backend (cal-provider, ~/src/cal-provider) already exposes the full CRUD-on-time surface across 3 calendar systems (google, google-oauth, caldav). What's missing is (a) surfacing all of it as caller-facing flow tools, (b) a robust LLM↔tool contract (the #20 "offers are quotes" fix), and (c) tutorial flows + deterministic tests per capability. This doc scopes those.

1. The capability surface that already exists

CalendarProvider (the cal-provider protocol, provider-agnostic across google/caldav) offers:

Method What it does Exposed as a riff flow tool today?
list_calendars list the caller/tenant's calendars only in boot_check (not caller-facing)
get_events list meetings/events in a time window NO — must be built
get_available_slots list free/available slots yes (via check_availability/propose_booking)
create_event schedule/book an appointment yes (via schedule_event)
update_event reschedule/modify an event NO — must be built
cancel_event cancel an event partial (cancel_booking in adapter; no flow)

Calendar systems (CAL_PROVIDER): google | google-oauth | caldav. The riff adapter (riff/providers/cal_provider_adapter/) is the single seam that imports cal_provider; flows/tools are provider-agnostic — a tutorial flow written once runs on any of the three systems by swapping the env var. (Tutorial flows should be designed to this abstraction, not to Google specifics.)

2. The use cases — the full calendar-operation taxonomy

Think broadly: everything a caller (or operator) might want to do with a calendar over voice. Each use case lists the caller intent, the backend capability, and whether it exists as a flow tool today. Bold "NEW" = the backend can do it but it is not surfaced as a caller-facing tool yet.

Design instruction to Fable 5: treat this taxonomy as the menu of capabilities. A v0 need not build all of them, but the design should say which tier each lands in (v0 / v1 / later) and why. Prefer covering the categories broadly over polishing one path.

A. READ — availability & discovery

# Caller intent Capability Status
UC-1 "When are you free Thursday afternoon?" get_available_slots(date, window, duration) exists (read-only entry NEW)
UC-2 "What's on the calendar Thursday?" / "what's blocked?" get_events(range) NEW (list_events)
UC-3 "Are you free at 2 PM Thursday?" availability/events filtered to the slot NEW
UC-4 "What's the next available appointment?" get_available_slots(soonest) exists (scheduling_v1 "soonest")
UC-5 "Any openings this week?" get_available_slots over a range exists (range)
UC-6 "First opening that's at least 90 min, mornings only, not Mondays" constrained availability search (duration + time-of-day + day filters) partial
UC-7 "What's my 2 PM about?" get_events → event detail NEW
UC-8 "How booked am I Friday?" / "how many appointments this week?" get_events → summary/count NEW
UC-9 "When are both Dr. A and Room 2 free?" mutual availability across calendars/resources NEW
UC-10 "What are your hours?" / "are you open Sunday?" business/working-hours query NEW
UC-11 "Read me my upcoming appointments." lookup by caller identity (see §D) → get_events NEW

B. WRITE — booking & mutation

# Caller intent Capability Status
UC-12 "Book an hour at 2 PM Thursday." create_event (after a vetted offer) exists — fragile (the demo bug)
UC-13 "Move my Thursday appointment to Friday at 10." update_event(event_id, new_time) NEW (needs lookup)
UC-14 "Cancel my Thursday appointment." cancel_event(event_id) partial (cancel_booking; no flow)
UC-15 "Hold that slot while I check with my wife." tentative/hold (pending confirm), auto-expire NEW
UC-16 "Book me every Tuesday at 3 for a month." recurring create_event NEW
UC-17 "Add my partner to the appointment." create_event/update_event with attendees/invites NEW
UC-18 "Make my 2 PM 90 minutes instead of 60." update_event (extend/shorten) NEW
UC-19 "Note that it's a leaky faucet." update_event (notes/details/purpose) partial (purpose on create)
UC-20 "Block off Friday morning — I'm out." create_event as a busy/blocked block (not a customer meeting) NEW
UC-21 "Yes, confirm the tentative hold." confirm/accept a held slot partial (confirm_booking)
UC-22 "Book my next cleaning in six months." forward/follow-up booking NEW
UC-23 "Sign me up for the 10 AM class." group/class booking (many attendees → one slot, capacity) NEW

C. POLICY & RULES — constrain every read/write

Not caller "commands" but rules the flow must enforce (design must specify where they live — flow YAML vs cal-provider):

D. IDENTITY & MULTI-TENANT — "whose calendar, which appointment"

E. LIFECYCLE & NOTIFICATIONS

F. CROSS-CUTTING (non-functional — apply to every use case)

3. Proposed tutorial flows (for Fable 5 to design)

One small, focused tutorial flow per capability cluster (mirrors the existing tutorial_* flows), each with a deterministic simulator like the one that caught B-CAL-1/2. Suggested set (Fable 5 picks the v0 subset):

v0 (core reads + a fixed booking):

  1. tutorial_list_availability — UC-1/3/4/5: read-only "when are you free."
  2. tutorial_list_events — UC-2/7/8: "what's on the calendar / what's blocked / how booked am I" (drives the new list_events tool).
  3. tutorial_book_appointment (fix the existing one) — UC-12 via the UC-X2 offer_id model so it stops escalating.

v1 (mutation + identity): 4. tutorial_manage_appointment — UC-13/14/18: reschedule / cancel / resize (drives new update_event / cancel_event tools + the UC-30 lookup). 5. tutorial_hold_and_confirm — UC-15/21: tentative hold → confirm/expire.

later (advanced): 6. tutorial_recurring — UC-16/22: recurring + follow-up booking. 7. tutorial_multi_resource — UC-9/31/33: pick a staff/room, mutual availability, multi-calendar. 8. tutorial_waitlist — UC-36: cancellation backfill / "text me if it opens."

Each tutorial demonstrates one capability cleanly, runs on all three calendar systems, and ships with a SchedulerSim-style deterministic test suite.

Each tutorial flow demonstrates one capability cleanly, runs on all three calendar systems, and ships with a SchedulerSim-style deterministic test suite.

3b. "Several different ways" — the demonstration matrix

The tutorials should not be a single happy-path script; they should show the same use case done several different ways, so an operator/learner sees the range. Four independent axes to demonstrate (a tutorial can hold one axis fixed and vary another):

Axis The "different ways" to show
Calendar system the same flow on google, google-oauth, and caldav — proving provider-agnosticism (swap CAL_PROVIDER, nothing else changes)
Input modality voice (spoken), DTMF/keypad (press 1–3 for a slot), and tap (pick a slot on the companion screen — ties to the remote-control work) — all resolving to the same decision
Offer / selection model deterministic locked_choice offers (robust, testable — the scheduling_v1 style we hardened) vs LLM free-text (flexible but fragile — the book_appointment_v1 style that breaks today); the tutorials should make the trade-off visible and steer toward the offer_id model (#20)
Domain / vertical the same scheduling capability across plumbing / massage / dental / apartment-viewing / generic appointment — showing the flow is a reusable module, not a one-off

Concretely: tutorial_book_appointment should exist in a "voice + LLM-offers" form (today's, fragile), a "voice + locked_choice-offers" form (robust), and a "DTMF/tap" form — each documented so the difference is teachable, plus a note that the same YAML runs on any of the three calendar backends.

3c. Documentation standard (every tutorial must ship with)

Nuance-rich designs get documented extensively — for humans and for the LLMs that read them. Each tutorial flow ships with:

  1. A spec (the design/contract): the use case, the states, the tools it calls, the offer model, and the calendar-systems it's verified on.
  2. A college-readable HTML tutorial (rendered via scripts/render_doc.py): what the caller experiences, an annotated example transcript, and why each design choice was made (e.g., why offers are a locked_choice, why the LLM never formats a time).
  3. Inline flow comments in the YAML explaining each state + guard (the flows are read by both operators and the model).
  4. A deterministic test suite (the SchedulerSim pattern) whose test names read as the capability's behavior spec, listed in the tutorial doc.
  5. A "run it" section: the exact voice.html?flow=... URL, the CAL_PROVIDER env to try each backend, and the pytest command for the deterministic tests.

Target audience for the docs: an operator who has never seen the flow should be able to run it in an afternoon, and Fable 5 (or a future agent) should be able to extend it from the spec alone.

4. What must be BUILT (the design/eng scope)

5. Open design questions for Fable 5

  1. One engine or two? Converge scheduling_v1 (deterministic locked_choice offers, hardened this session) and book_appointment_v1 (LLM offers, live) onto one canonical path — likely the offer_id model for both.
  2. Read-only vs transactional entry points. UC-1/UC-2 are read-only queries; should they be their own top-level intents, or sub-flows of booking?
  3. Event lookup for reschedule/cancel. How does the caller identify their event over the phone (by time? by confirmation? by a code)? — affects UC-7/8.
  4. Multi-calendar / multi-tenant. Does the tutorial assume one calendar, or surface list_calendars?
  5. How much does the LLM touch time at all post-#20 (ideally: never — it only picks an offer_id and reads back).

6. Handoff to Fable 5 — produce a v0 design from this

Next step: Fable 5 thinks through the above and produces a v0 design doc. This document is the input, not the design — it gives the use-case list (UC-1…UC-8), the capability surface that already exists, the "several different ways" demo matrix (§3b), the documentation standard every tutorial must meet (§3c), and the open questions to resolve (§5).

The backend already does the full read/write surface (list events, list free slots, create/update/cancel) across three calendar systems; the v0 design should cover: which capabilities to surface as new caller tools (list_events, reschedule, cancel), the canonical offer model (the #20 offer_id — so the LLM never formats a time), the set of tutorial flows and which "different ways" each demonstrates (§3b), and the documentation deliverables per tutorial (§3c) — each tutorial backed by a SchedulerSim-style deterministic test suite like the one that caught B-CAL-1/2.

A good v0 answers §5's open questions, picks the tutorial-flow set, and specifies the offer_id contract precisely enough that engineering can build the first tutorial_list_availability + fixed tutorial_book_appointment behind it.