Source: https://docs.cumuluslabs.io/qualification-booking
Content version: 8c48ac9e

# Qualify a request and book the agreed next step

Build an agent for a requested consultation. It captures the prospect’s needs, routes specialist requests, offers available times and asks for confirmation before booking. It records either the confirmed reservation or the follow-up needed.

The screenshots show synthetic data. You implement the availability, booking and CRM endpoints and determine who may be contacted or booked. Select an image to view it at full size.

## Design the conversation around decisions {#flow}

![A qualification flow spanning interest, need discovery, extraction, routing, booking and CRM follow-up](https://docs.cumuluslabs.io/docs-assets/qualification-map.png)

The main graph handles the conversation and specialist route. A separate booking component handles availability, confirmation, reservation and the failure path. Keeping those steps explicit lets you test a booking change without rewriting the entire qualification conversation.

| Stage | Information you need | Decision |
| --- | --- | --- |
| Introduction | Why the person requested contact; whether now is appropriate | Continue or end respectfully |
| Need discovery | Use case, existing system, scale and timeline | Gather the missing facts rather than guessing |
| Qualification | Structured fields with defined types and choices | Standard booking, specialist follow-up or further information |
| Availability | Slots returned by the calendar service | Offer only currently returned options |
| Confirmation | Selected time, time zone, attendees and requested service | Request the reservation only after explicit agreement |
| Business response | Reservation identifier and final state | Confirm completion or record an exception |
| CRM handoff | Agreed next step and the original run identity | Store an accurate outcome for the human team |

## Define qualification fields {#fields}

![An extraction node for use case, monthly volume, decision timeline and specialist need](https://docs.cumuluslabs.io/docs-assets/qualification-fields.png)

Define fields an operator can use: `use_case` as text, `monthly_volume` as a number, `timeline` as an enum, and `needs_specialist` as a boolean. The field descriptions should say what evidence the conversation needs, including what to do when the caller does not know an answer.

Extraction is model-produced information. Your business system validates it before making a decision or committing a transaction. Do not turn a guessed budget, urgency or title into an authoritative business fact.

![A branch selecting specialist follow-up or the normal booking path](https://docs.cumuluslabs.io/docs-assets/qualification-routing.png)

Use defined variables in the routing conditions and keep a default path. A request outside the standard offering should become a specialist case, not a promise that an unsupported feature is available.

## Separate calendar reads from reservation writes {#actions}

![Availability, booking, follow-up-ticket and CRM actions bound to the agent](https://docs.cumuluslabs.io/docs-assets/booking-action-list.png)

`find_availability` reads your calendar. `book_appointment` requests a reservation. `create_ticket` records a specialist or exception case. `update_crm` records the agreed outcome. Give reads and writes separate contracts and test mocks.

For example, the availability endpoint can return a stable `slot_id`, displayed local time and time zone. The reservation endpoint can accept that slot ID and a known contact ID, then return `{ "state": "confirmed", "appointment_id": "APPT-DEMO-24" }`. Those fields are conventions for your service, not built-in Cumulus calendar APIs.

The reservation service must validate the slot again at commit time: another person can take it after the agent reads availability. It must also honor the idempotency contract so a retry does not create a second appointment.

## Confirm before booking {#confirmation}

![The booking component's confirmation node with the transition for explicit agreement](https://docs.cumuluslabs.io/docs-assets/booking-confirmation.png)

Read back the selected time and time zone. Check the requested service and attendee details. Only the explicit confirmation transition should reach the reservation function.

Test “I need a different time,” “I am not ready to book,” a correction to the attendee and an ambiguous response. A model interpreting a transition condition still needs acceptance tests; a visible edge does not make the interpretation deterministic.

![The booking-result branch distinguishing confirmation from a review path](https://docs.cumuluslabs.io/docs-assets/booking-result-branch.png)

Map the business response into the variable the branch reads. Confirm only a successful reservation response. A stale slot, timeout or unknown result should produce the defined review/reconciliation path; it is not evidence that a calendar entry exists.

## Configure the phone experience {#phone}

![Voicemail detection and the configured message for the consultation example](https://docs.cumuluslabs.io/docs-assets/booking-voicemail.png)

Choose the voicemail behavior deliberately. The message should identify the purpose without leaking unnecessary account information or claiming that an appointment was booked.

![Call behavior settings for interruption, reminders, silence and maximum duration](https://docs.cumuluslabs.io/docs-assets/booking-call-behavior.png)

Set interruption behavior, silence handling and maximum duration for the use case. Test the full audio path as well as text simulations: a scenario that passes in text does not establish natural turn-taking, correct voicemail detection or real number routing.

## Supply the known context at admission {#request}

This example starts a run for a requested consultation. The contact ID is a reference your business already knows; the agent should not invent one from the phone number.

<!-- operation:runs.create -->
```json
{
  "channel": "phone",
  "agent_id": "qualification-booking",
  "to": "+14155550124",
  "from": "+14155550100",
  "dynamic_variables": {
    "business_name": "Acme",
    "contact_id": "LEAD-DEMO-24",
    "service": "technical_consultation",
    "timezone": "America/New_York"
  },
  "metadata": { "lead_reference": "LEAD-DEMO-24", "requested_contact": "true" }
}
```

Use [Start a run](/docs/reference/runs.create) with a retained `Idempotency-Key`. Metadata records your context; it does not independently establish that contact was authorized. For inbound calls, configure the number and published agent as described in [Phone](/docs/phone).

## Test the booking and failure paths {#acceptance}

| Test case | Evidence to inspect |
| --- | --- |
| Person declines to continue | The call ends without a booking write |
| Required qualification field is unknown | The defined information/follow-up route is taken |
| Caller changes the selected time | The confirmed slot matches the final agreement |
| Slot becomes unavailable | No unsupported “you are booked” statement |
| Reservation response is uncertain | Reconciliation or review before another write |
| Specialist required | A case or agreed handoff is recorded with the run reference |

Use node/path assertions for structure, tool assertions for the expected action and a judged criterion for the confirmation conversation. Validate real availability, reservation and CRM contracts separately. Inspect [run-linked action receipts](/docs/investigate-runs#receipts) before treating a meeting as scheduled.

Store the appointment or follow-up identifier with the run ID in your CRM. If the reservation result is unclear, use those identifiers to reconcile it with the calendar service.
