← Series contents · Complete reading view
Booking: let the model converse and the system decide
Booking is a good test of whether an agent is connected to a product or merely describing one. A guest can change dates, compare options, ask for more choices and return to an earlier property. Every one of those turns can invalidate an assumption made two messages before.
The client platform moved important booking behaviour into a dedicated flow. The model retained the conversation, but search state, calendar checks, selection and property evidence had explicit application logic.
Search is not availability
A property search finds candidates. A calendar check establishes whether each candidate can satisfy the requested dates, occupancy and booking rules. Returning a search result as “available” without that second step is a semantic error even if the retrieval ranking is excellent.
The booking flow separates candidate discovery from calendar verification. It tracks checked, unavailable and unverified results. It also records whether a scan is complete or truncated. That lets the reply distinguish “no available options were found” from “not every candidate could be checked.”
The distinction matters when a backend is slow. A partial scan may be useful, but the agent should not describe partial evidence as the complete inventory.
Quote the calendar’s total
A listing’s base nightly rate is not a quote for a specific stay. Rates can vary by night, and availability rules can depend on the date range. The flow uses the calendar’s night-by-night information to derive the total for the requested nights.
Consider an illustrative three-night stay at 120, 150 and 150 currency units. The nightly base price of 120 would suggest 360; the actual night total is 420. Fees and taxes may still belong to the checkout calculation. The reply must state what the number includes.
from decimal import Decimal
def nightly_total(rates):
return sum((Decimal(str(rate)) for rate in rates), Decimal("0"))
assert nightly_total([120, 150, 150]) == Decimal("420")
The arithmetic is simple. The difficult part is carrying the correct dates, currency, inclusion rules and provenance through the tool result and into the sentence the guest reads.
Remember what was shown
The system retains search records with their parameters, results and presentation position. The current design supports paging through available properties rather than letting a small first-page cap hide the rest of the inventory.
The phrase “the second one” refers to a presented option, not the second item in whatever search happened most recently. Recording presentation is therefore part of state management. A tool result can contain ten candidates while the model mentions only three; the memory needs to know what the guest actually saw.
A worked conversation makes the requirement clear:
Guest: Four people, 10–13 October, near the harbour.
System: Search and verify; present options 1–3.
Guest: Any others?
System: Continue the same search and preserve its ordinals.
Guest: What if we arrive a day earlier?
System: Create a distinct search with different calendar evidence.
Guest: The second one from the original dates.
System: Resolve the original search, then recheck that property.
This is why a transcript summary is not a complete booking memory. It may preserve the conversation’s topic while dropping the precise mapping needed for an action.
Selection is a new validation point
The selection flow performs a fresh calendar read before returning a checkout link. A property that was available at discovery time may no longer be available when the guest chooses it.
The response should distinguish a valid checkout opportunity from a confirmed reservation. Giving a link does not prove payment, acceptance or booking completion. The confirmation must come from the domain system’s state.
This can be expressed as an evidence ladder:
| Evidence | Safe claim |
|---|---|
| Candidate found | “This property matches the search.” |
| Calendar verified | “It is available for these dates as checked now.” |
| Selection revalidated, checkout link returned | “You can continue through this checkout link.” |
| Confirmed reservation from backend | “The reservation is confirmed.” |
The model should not jump to a higher rung because a more confident sentence sounds reassuring.
Property facts must stay with the property
Parking, accessibility, amenities and house rules are not interchangeable across listings. A generic knowledge search without property scope can produce an answer that is plausible for the portfolio but wrong for the selected stay.
The booking flow retrieves listing details, rules, guest-book information and property-scoped knowledge. Guest-book access is also subject to the appropriate redaction and stay privileges. A prospective guest asking about parking does not need an access code.
The model receives the resulting facts in context, but the flow retains their listing identity and retrieval purpose. That helps answer follow-up questions without treating unrelated property evidence as shared knowledge.
Use bounded parallelism for calendar checks
Calendar verification is a natural fan-out operation: several candidate properties can be checked independently. Give it a concurrency budget based on the calendar service’s capacity. That budget serves a different resource from the outer tool-execution limit or the model-call limiter.
The useful performance calculation is the critical path. If 24 independent calendar reads each take an illustrative 250 ms and the effective concurrency is eight, the idealized service time is roughly three batches, or 750 ms, before overhead and tail latency. It is not 250 ms, and real distributions rarely align into perfect batches.
Track queue wait, timeout rate and backend pressure. Raising concurrency can reduce one guest’s scan time while overwhelming the domain API for everyone else.
Persist facts, not unsupported claims
The booking memory keeps verified results, search parameters and references. It can also record what the reply presented. The guard layer checks for booking claims unsupported by tool results or remembered evidence and can request a bounded repair.
This is useful defence, but it should not become the primary source of correctness. If the tool result already clearly distinguishes unavailable, unverified and bookable states, the model has less ambiguity to repair.
A good result contract is often more valuable than another paragraph of instructions. It gives the model a constrained vocabulary for explaining the outcome.
Test the conversation as a state machine
Single-turn tests miss most booking failures. The evaluation set should include changing dates, asking for more results, selecting an earlier option, duplicate property names, unavailable calendars, incomplete scans and returning to a previous search.
Assertions should inspect the selected listing and search parameters, not only the presence of a checkout URL. A syntactically valid URL for the wrong property is a failed task.
Also test the transition from prospect to existing guest. Once a reservation is confirmed, the authority and data needed for access instructions change. The system should derive that transition from domain state, not from the model’s memory of a congratulatory message.
Why the composite flow helped
The flow reduced the number of mandatory operational steps left to open-ended model planning. Search, verification, pagination, state updates and selection checks became explicit behaviour with unit-testable helpers and inspectable results.
The model still handled the part that benefits from language: understanding preferences, clarifying ambiguity and explaining trade-offs. That division made the assistant more useful while making its critical promises easier to verify.