Capture confirmation and generate record
Most of the time the router will have extracted a choice_index already. But users say things like "the Virgin one" or "the cheapest". For those cases, the confirm node falls back to a second LLM call that maps the freeform reply onto a numbered option.
async def confirm_booking(state: BookingState) -> BookingState:
options = state.get("candidates") or []
if not options:
state["assistant_reply"] = "Let's start over - where would you like to fly from?"
state["stage"] = "collecting"
return state
idx = state.get("_choice_index")
# If the router didn't extract a choice, ask the LLM explicitly.
if not isinstance(idx, int):
system = (
"You interpret which numbered option the user chose. Return JSON: "
'{"choice_index": 1-based int or null, "declined": bool}.'
)
option_list = "\n".join(
f"{i+1}. {o['carrier']} {o['id']} at {o['depart_time']}"
for i, o in enumerate(options)
)
prompt = f"Options:\n{option_list}\nUser reply: {state.get('user_message', '')}"
data = await _llm_json(prompt, system)
if data.get("declined"):
state["assistant_reply"] = "No problem - tell me when you'd like to try again."
state["stage"] = "routing"
state["candidates"] = []
return state
idx = data.get("choice_index")
if not isinstance(idx, int) or idx < 1 or idx > len(options):
state["assistant_reply"] = f"Which option works for you? Reply with 1, 2, or {len(options)}."
state["stage"] = "proposing"
return stateThe confirm node covers the no-candidates case (reset), the missing-index case (ask the LLM to interpret), and the bad-index case (re-prompt). Only after a valid index arrives does the node actually generate the record.
chosen = options[idx - 1]
pax = int(state.get("passengers") or 1)
booking = create_booking(
thread_id=state.get("thread_id", "anonymous"),
flight=chosen,
depart_date=state.get("depart_date") or "",
return_date=state.get("return_date"),
passengers=pax,
)
state["chosen_flight"] = chosen
state["booking_id"] = booking["id"]
state["stage"] = "confirmed"
state["assistant_reply"] = (
f"Booked! Confirmation {booking['id']} - {chosen['carrier']} {chosen['id']} "
f"from {chosen['origin']} to {chosen['destination']} on "
f"{state.get('depart_date')} for {pax} passenger(s). "
f"Total ${booking['total_price_usd']}."
)With a valid choice in hand, the node writes the booking, records the chosen flight and booking id in state, and sets stage to "confirmed" so future turns do not accidentally re-book.
AI prompt: Try it with your own domain
Loading practice…
Quiz: Quiz
Loading practice…