You cannot prompt your way out of a booking that half-completes. The failures that strand a traveler, or surface a hotel that does not exist, are not model-IQ failures. They are a rate expiring between two API calls, a hold rejected after a ticket already issued, a search storm quietly burning margin. A sharper language model does not undo a charge that was made. So when we built an autonomous travel booking agent, we stopped trying to make the model more careful and moved it out of the control flow entirely. The flow is deterministic Python; the model only parses the request and words the reply. The result is what we call a deterministic booking agent, and you can run every scenario below yourself at https://veriprajna.com/demos/agentic-travel-booking.
The industry is racing in the opposite direction, handing ever-larger models the wheel of the transaction. We think that is the wrong race, and the reason is arithmetic.
The failure mode is arithmetic, not intelligence
A booking is a chain of steps that each has to hold: search, check policy, verify inventory, hold, ticket, book the hotel, commit. Chain enough independently-fallible steps and reliability collapses by multiplication. Ten steps that are each 90% reliable finish end to end at 0.9 to the tenth power, roughly 34%. On TravelPlanner, the multi-day itinerary benchmark from OSU NLP (arXiv 2402.01622), GPT-4 with a ReAct loop completes real itineraries at 0.6%. A model twice as good still loses to the compounding.
And the deployer owns every word the agent says. In Moffatt v. Air Canada (BC Civil Resolution Tribunal, February 2024), the airline was ordered to pay $812.02 after its chatbot invented a bereavement-fare policy, and the tribunal rejected the "it was the AI" defense outright. If your agent tells a traveler they are booked, you are answerable for it whether or not the booking is real.
What happens when the rate expires after the ticket
Here is the case that made us rebuild the architecture. A traveler asks for a flight from Chicago O'Hare to San Francisco next Tuesday, one night downtown. The flight is held and the ticket issues. Then, in the fraction of a second before the hotel commits, the held room rate expires. Two API calls, one infrastructure event between them, and the transaction is now inconsistent: a ticket exists, a room does not.
In our agent, every forward step registers its reverse the moment it runs. Issuing the ticket registered "void ticket, 24-hour window" before anything else happened. So when the hotel commit fails, the engine runs the registered compensations in reverse order (a Saga): it voids the ticket inside the 24-hour window, releases the holds, and only then does the model word the outcome. The traveler is told the truth, that the room could not be confirmed, the flight ticket was voided at no charge, and here are alternatives to confirm now. Terminal state: rolled back, traveler safe.
Same failure, two architectures. The deterministic agent (right) voids the ticket in reverse via the Saga and ends rolled_back; the LLM-in-control baseline (left) still says "All set!" with a confirmation number for a booking that half-failed.
Run the identical scenario through a real ReAct-style agent with the LLM in control, and it does what the left panel shows: the ticket is left issued, nothing compensates, and it cheerfully returns "All set!" with a confirmation number. That is a stranded traveler and an Air Canada precedent waiting to happen.
Every forward step registers its own undo. When the hotel rate expired after the flight was ticketed, the agent voided the ticket inside the 24-hour window and offered honest alternatives, instead of leaving someone with a flight and no room. The Saga rollback is what separates a demo from a product.
The same discipline, one family of failures
The Saga handles partial failure. A verification gate handles the other half, inventory that never existed. When a request names a property the model finds plausible but the reservation system has never heard of, the gate refuses to surface it rather than flagging it after the fact.
A deliberately fabricated hotel, "Tabacon Springs Eco-Lodge," fails the CRS check by property_id. The agent abstains ("I could not confirm that property") rather than inventing a booking. Terminal state: abstained.
The same shape covers policy. Corporate rules are compiled to code, so an out-of-policy fare is physically un-presentable, filtered before it can ever be shown rather than caught afterward, and an unknown fare family fails safe as above-policy instead of slipping through as economy. When nothing in policy is available, the agent escalates to a human queue rather than bluffing. One discipline, applied to partial failure, fabricated inventory, and policy, and none of it lives in the prompt.
Why a better base model does not close the gap
We ran the same 200 synthetic bookings through both architectures, one fixed seed, the same injected infrastructure failures, and scored them.
Same fixed-seed batch (n=200, seed 42), same injected failures, both architectures. By construction the deterministic agent holds 100% consistent terminal states, 0 stranded, 0 fabricated bookings surfaced, at $3.25 average GDS search spend; the baseline's 65% / 40 / 30 / $7.57 emerges from the identical data.
Over this fixed-seed 200-scenario synthetic batch, the deterministic agent held 100% consistent terminal states, 0 stranded travelers, and 0 fabricated bookings surfaced, at an average GDS search spend of $3.25. The real LLM-in-control baseline came in at 65%, 40 stranded, 30 integrity breaches, and $7.57. We state those numbers only as what they are, a by-construction result on a fixed-seed synthetic batch, not an open-world production guarantee. But notice the last column. The margin number, $3.25 versus $7.57, is not about correctness at all. GDS operators charge for searches, not just bookings, around $3 to $3.50 per segment, and Lufthansa raised those fees again on January 1, 2026. A speculative agent that re-searches burns that money; a deterministic flow with a lookup-to-book cache does not. No model upgrade changes that arithmetic.
The failures that strand a traveler are infrastructure events, not model-IQ failures. A better base model does not remove the need for deterministic compensation and a verification gate. That is why this guarantee does not age out as models improve.
Governance an auditor can actually read
Every booking writes an append-only event log, exportable as a single JSON file: the model and version, the typed trip request, every node with its deterministic verdict, every Saga compensation that fired, the terminal state, and an EU AI Act Article 50 disclosure flag. Article 50's transparency obligations start applying on August 2, 2026, and "the agent decided" is not going to be an acceptable answer to a regulator.
The export link under a rolled-back booking; the downloaded JSON carries the model, node verdicts, Saga compensations, terminal state, and the Article 50 disclosure flag. To be clear about scope, the GDS, reservation system, ticketing, and payment are simulated stubs in this demo, not a live Amadeus or Sabre connection.
We want to be precise about what this is. The demo runs over a simulated GDS and reservation system, and the tickets and payments are stubs. It proves a mechanism, not a deployed pipeline, and we would rather say that plainly than imply a live integration we do not have. What is real is the architecture: the control flow is code, the LLM is a typed leaf node, and every step carries its own undo. Agents advise, code decides. You can walk the full flow, trigger the rollback, and export the audit trail at https://veriprajna.com/demos/agentic-travel-booking.
If you are building or buying an agentic booking layer, here is the question worth sitting with. Once your model proposes a trip and the ticket issues, what runs when the very next step fails? Does anything void that ticket inside the void window and tell the traveler the truth, or does the agent report "all set" and let them discover the gap at the airport? We would genuinely like to hear how your stack handles that moment, because the failure is industry-wide and the good answers will be too.