Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Recommend hotel rooms and complete a real booking end to end — reserve an OpenTravel direct property with a payment link (bank QR, card, or PayPal), check payment status, resend an expired link, or cancel a booking. Falls back to direct Booking.com/Agoda/Traveloka links for OTA-only hotels. Use when booking or reserving a hotel, getting room recommendations, paying for a stay, checking a confirmation code, or cancelling a reservation.
.claude/skills/price-win-pricewin-booking-assistant/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 163% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 5% | 0% |
| case-09 | ✗→✓ | ▲ Improved | -16% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 89% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 414% | 0% |
> Requires the pricewin MCP server. Handles real money: it creates bookings and > payment links. Read the confirmation rules below before use.
MCP server: pricewin. Orchestrates discover → detail → recommend → book → pay → manage.
| Source | Can you book it here? | |---|---| | source: "OPENTRAVEL_DIRECT" (has propertyId) | ✅ Yes — full booking + payment via create_booking | | Booking.com / Agoda / Traveloka | ❌ No — comparison only. Hand the user the OTA url |
Only OpenTravel direct properties yield the propertyId + roomTypeId that create_booking requires. Never imply an OTA hotel can be reserved through this skill.
search_hotels_live(city, checkIn, checkOut, adults, …) → sessionId,then poll poll_search_results(sessionId, nights) every 5s while status is pending/partial (up to 18 polls / 90s)
rating × log(reviewCount + 1) — balances quality against credibility.Strong candidates: rating ≥ 8.0 and reviewCount ≥ 100
get_hotel_detail(propertyId, checkIn, checkOut, adults) for OpenTravelpicks; get_ota_hotel_detail(hotelName, city, checkIn, checkOut, queryText) for a named OTA hotel (~20–60s)
url the tool returnedpricewin-hotel-searchCall get_hotel_detail before booking to obtain roomTypeId, total price, and currency. Do not guess any of the three.
Optionally call get_cancellation_policy(propertyId, ratePlanId, checkInDate) and show the refund terms before taking payment.
In your first request for guest info, ask for all of these together — never split across turns, and always in the user's language:
⚠️ Never auto-fill the email from the account/profile. The guest is often not the account owner. It must come from what the user typed in this chat. If it is missing, ask.
Present the three payment methods as equal choices, no default, no recommended order:
SEPAYPOLARPAYPALIf the user already signalled a preference, infer it and skip re-asking:
| They said | Method | |---|---| | "scan QR", "quét mã", "chuyển khoản", "bank transfer", "VietQR" | SEPAY | | "card", "thẻ", "credit/debit card", "visa", "mastercard" | POLAR | | "PayPal" | PAYPAL |
If anything is still missing after their reply, ask again for just the missing item(s).
Summarise back everything — hotel, room type, check-in/check-out, guests, TOTAL price (full amount, not a deposit), guest name, email address (emphasise it — a typo means the confirmation never arrives), phone, payment method — then explicitly ask the user to confirm it is all correct.
create_bookingRequired: propertyId, roomTypeId, checkIn, checkOut, adults, guestName, guestPhone, guestEmail, paymentMethod, totalAmount, currency. Also pass queryText (user's original text, verbatim).
Returns a payment link and a confirmationCode (e.g. K7X9M2P4) — surface both.
| User says | Tool | |---|---| | "I paid" / "check my booking" | check_booking_status(confirmationCode) | | "the payment link expired" | recreate_payment_link(confirmationCode) | | "cancel my booking" | request_cancel_token → then cancel_booking |
🚨 Never call create_booking twice for the same stay. An expired payment link is fixed with recreate_payment_link — it reuses the same confirmation code. Calling create_booking again creates a duplicate booking and a duplicate confirmation email.
request_cancel_token(confirmationCode, guestEmail) — email must match the booking'sprimary guest. This emails the guest a magic link
cancel_booking(confirmationCode, cancelToken, reason)(reason ≥ 3 chars)
You cannot cancel without the guest fetching that token from their inbox. Tell them to check their email rather than retrying step 1.
### Hotel Name ★★★★☆
- Rating: 8.5/10 (1,234 reviews)
- Best room: Deluxe Double — $85/night
- Free cancellation: until 2026-08-10
- Book: [Reserve now](payment-link) ← OpenTravel direct
- Or compare: [Agoda](url) | [Booking.com](url)Tool inputs and response fields: reference.md.
This skill has real transaction authority and transmits guest PII (name, phone, email) to PriceWin's hosted MCP server https://mcp.price.win/mcp — that is inherent to making a reservation, and it is why booking is a separate skill from search. It ships no code and makes no network calls of its own.
Card numbers, CVV and bank credentials never pass through the skill or the agent — create_booking returns a payment link and the user pays on the provider's own page. Never ask for card details; refuse if offered.
Confirm the full summary and total price with the user before every create_booking. Full disclosure — operator, exact PII fields per tool, payment boundary, cancellation model — in SECURITY.md.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 6,609 | 6,254 | -5% | 1 | 1 | 0% | 402 | 2,013 | +401% | 0 | 0 | — |
case-02 | fail→fail | 9,417 | 7,152 | -24% | 1 | 1 | 0% | 1,651 | 2,240 | +36% | 0 | 0 | — |
case-03 | fail→fail | 9,133 | 4,441 | -51% | 1 | 1 | 0% | 1,467 | 1,945 | +33% | 0 | 0 | — |
case-04 | pass→pass | 8,732 | 4,716 | -46% | 1 | 1 | 0% | 1,499 | 2,476 | +65% | 0 | 0 | — |
case-05 | pass→pass | 7,526 | 4,127 | -45% | 1 | 1 | 0% | 1,529 | 2,458 | +61% | 0 | 0 | — |
case-06 | pass→pass | 6,415 | 4,232 | -34% | 1 | 1 | 0% | 1,149 | 2,350 | +105% | 0 | 0 | — |
case-07 | fail→pass | 4,284 | 2,441 | -43% | 1 | 1 | 0% | 770 | 2,027 | +163% | 0 | 0 | — |
case-08 | fail→pass | 11,109 | 4,616 | -58% | 1 | 1 | 0% | 2,608 | 2,749 | +5% | 0 | 0 | — |
case-09 | fail→pass | 11,334 | 4,057 | -64% | 1 | 1 | 0% | 2,729 | 2,291 | -16% | 0 | 0 | — |
case-10 | fail→fail | 4,455 | 7,318 | +64% | 1 | 1 | 0% | 871 | 2,316 | +166% | 0 | 0 | — |
case-11 | fail→pass | 4,905 | 1,588 | -68% | 1 | 1 | 0% | 1,030 | 1,951 | +89% | 0 | 0 | — |
case-12 | fail→pass | 2,283 | 1,878 | -18% | 1 | 1 | 0% | 382 | 1,963 | +414% | 0 | 0 | — |
case-13 | pass→pass | 5,340 | 1,791 | -66% | 1 | 1 | 0% | 1,015 | 1,960 | +93% | 0 | 0 | — |
case-14 | pass→pass | 2,845 | 2,093 | -26% | 1 | 1 | 0% | 510 | 2,025 | +297% | 0 | 0 | — |
case-15 | fail→fail | 3,568 | 7,776 | +118% | 1 | 1 | 0% | 784 | 2,440 | +211% | 0 | 0 | — |
case-16 | fail→pass | 2,484 | 4,441 | +79% | 1 | 1 | 0% | 405 | 2,415 | +496% | 0 | 0 | — |
case-17 | pass→pass | 6,888 | 5,453 | -21% | 1 | 1 | 0% | 1,209 | 2,611 | +116% | 0 | 0 | — |
case-18 | fail→fail | 5,308 | 3,174 | -40% | 1 | 1 | 0% | 993 | 2,220 | +124% | 0 | 0 | — |
case-19 | fail→pass | 5,508 | 3,567 | -35% | 1 | 1 | 0% | 540 | 2,198 | +307% | 0 | 0 | — |
case-20 | fail→pass | 6,936 | 4,098 | -41% | 1 | 1 | 0% | 1,198 | 2,402 | +101% | 0 | 0 | — |
case-21 | fail→fail | 5,219 | 3,462 | -34% | 1 | 1 | 0% | 893 | 1,822 | +104% | 0 | 0 | — |
case-22 | fail→pass | 10,474 | 3,379 | -68% | 1 | 1 | 0% | 2,238 | 2,278 | +2% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 17 counted toward the lift figure. The other 5 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +41 percentage points is the difference between those two pass rates over the 17 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/3/2026 | +22% |
| gemini-3.6-flash | verified | 8/3/2026 | +14% |
Other measured skills in the registry, with their headline benchmark lift.