Tool description (what the LLM sees)
Tool description (what the LLM sees)
Create and manage a trip: add flight or hotel items, remove items, set traveler details, and select ancillaries.
Operations:
- add_item: Add a flight or hotel to the trip. Pass trip_item_token from flight_search (offer__* tokens) or offer_id from hotel_search (htl_* tokens). Omit trip_id to create a new trip. MULTI-ROOM HOTEL: to book several rooms of the SAME hotel and stay as ONE booking with ONE reference, make ONE add_item call with rooms: [{trip_item_token: "htl_..."}, ...] (2-8 entries, one htl_* rate token per room, mutually exclusive with trip_item_token; HotelBeds-inventory tenants only), do NOT add the same hotel twice as separate items.
- remove_item: Remove an existing item from the trip by item_id (from trip response items[].item_id). Requires an existing trip_id. Can be combined with add_item in a single call to swap an item, remove runs first, then add.
- upsert_travelers: Set traveler details and contact info on an existing trip_id.
- select_ancillaries: Select bags, seats, meals for a quoted trip item. Requires trip_id and item_id.
Returns trip_id for use with the checkout tool. Flights and hotels can coexist in the same trip (single Stripe checkout).
IMPORTANT, TRAVELER DATA:
NEVER invent or fabricate traveler data. Before calling upsert_travelers, you MUST ask the user for the required fields:
- Always: first_name, last_name, passenger_type
- Flights only: date_of_birth (YYYY-MM-DD), gender (male/female), required when the trip contains a flight, optional for hotel-only trips
- Contact: email, phone (with country code)
If a required field is missing, ASK the user. Do not use placeholder or default values.
ANCILLARY FLOW:
After adding an item and setting travelers, check trip response for available_ancillaries on trip items.
If ancillaries are available, offer them to the user before proceeding to checkout.
Use select_ancillaries with the offer_ids from available_ancillaries. Full replacement semantics, send all desired selections.
Flows:
- Flights: flight_calendar → flight_search → trip(add_item) → trip(upsert_travelers) → [trip(select_ancillaries)] → checkout
- Hotels: hotel_search → trip(add_item) → trip(upsert_travelers) → checkout
- Mixed: both in the same trip, one cart, one checkout
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
trip_id | string | No | Existing trip ID. Omit to create a new trip. |
add_item | object | No | Add a flight, hotel or ground item to the trip. For MULTIPLE ROOMS of the same hotel stay, make ONE add_item call with the rooms array (2-8 htl_* tokens), do NOT add the same hotel twice as separate items. |
add_item.trip_item_token | string | No | Token identifying the thing to add. One of: flight_search -> trip_item_token (offer__* format); hotel_search -> offer_id (htl_* format); find_ground -> the connection’s trip_item_token, copied VERBATIM including its trailing ”-<number>” (e.g. “EURS-GBLONLIB-FRPARPGN-2026-09-15T06:01-2026-09-15T09:29-0”). For ground, do NOT pass fares[].offer_id, it is rejected as Bad Request. Mutually exclusive with rooms, provide exactly one of the two. |
add_item.rooms | array<object> | No | MULTI-ROOM HOTEL ONLY: book 2-8 rooms of the SAME hotel and SAME stay as ONE booking with ONE reference. One entry per room, each with its own htl_* rate token from hotel_search (e.g. one rate per occupancy). Mutually exclusive with trip_item_token; for a single room use trip_item_token instead. Currently supported for HotelBeds-inventory tenants only. |
add_item.rooms[].trip_item_token | string | Yes | Hotel rate token (htl_*) from hotel_search for THIS room. All rooms must come from the same hotel and the same stay (same check-in/check-out dates). |
add_item.fare_class | string | No | GROUND ONLY. Which fare of the connection to book. Accepts EITHER the carrier fare name from find_ground results fares[].fare_name (e.g. “PREMIER”) OR the fare class from fares[].fare_class (e.g. “FARE-32”), both identify the same fare, matching is case-insensitive. Omit to book the CHEAPEST fare, the “from” price shown in search. A fare the connection does not offer is rejected and the bookable ones are listed, never silently downgraded. Ignored for flights and hotels. |
remove_item | object | No | Remove an existing item from the trip. Requires an existing trip_id, you cannot remove from a trip that has not been created yet. Can be combined with add_item in a single call to swap an item (remove runs first, then add). |
remove_item.item_id | string | Yes | ID of the trip item to remove. Matches the value returned in the trip response items[].item_id field. |
upsert_travelers | object | No | Set or update travelers and contact info on the trip. Optional per call (you can add_item while building the cart), but travelers and a contact must be present before booking. |
upsert_travelers.travelers | array<object> | Yes | List of travelers (replaces all). Required to complete a booking; the first traveler also supplies the booking contact name. |
upsert_travelers.travelers[].first_name | string | Yes | First name as on travel document |
upsert_travelers.travelers[].last_name | string | Yes | Last name as on travel document |
upsert_travelers.travelers[].date_of_birth | string | No | Date of birth (YYYY-MM-DD). Required for flights; optional for hotel-only trips. |
upsert_travelers.travelers[].gender | enum ("MALE" | "FEMALE") | No | Gender as on travel document. Required for flights; optional for hotel-only trips. |
upsert_travelers.travelers[].passenger_type | enum ("ADULT" | "CHILD" | "INFANT") | Yes | ADULT (12+), CHILD (2-11), INFANT (under 2) |
upsert_travelers.travelers[].nationality | string | No | ISO 3166-1 alpha-2 country code |
upsert_travelers.travelers[].passport_number | string | No | Passport number |
upsert_travelers.travelers[].passport_expiry | string | No | Passport expiry date (YYYY-MM-DD) |
upsert_travelers.travelers[].passport_country | string | No | Passport issuing country (ISO 3166-1 alpha-2) |
upsert_travelers.travelers[].frequent_flyer | object | No | Frequent-flyer / loyalty membership. airline = IATA carrier that issued the membership (e.g. LH); number = membership number. |
upsert_travelers.travelers[].known_traveler_number | string | No | US trusted-traveler Known Traveler Number (TSA PreCheck / Global Entry). Flights only; sent to the airline as Secure Flight data so PreCheck prints on the boarding pass. |
upsert_travelers.travelers[].known_traveler_issuing_country | string | No | ISO 3166-1 alpha-2 country that issued the Known Traveler Number. Defaults to US downstream; ignored without known_traveler_number. |
upsert_travelers.travelers[].redress_number | string | No | DHS redress control number (TRIP program). Flights only. |
upsert_travelers.travelers[].redress_issuing_country | string | No | ISO 3166-1 alpha-2 country that issued the redress number. Defaults to US downstream; ignored without redress_number. |
upsert_travelers.contact | object | Yes | Booking contact (email + phone, both required). Required before the trip can be booked. |
upsert_travelers.contact.email | string | Yes | Contact email for booking confirmation |
upsert_travelers.contact.phone | string | Yes | Contact phone with country code. Required, connectors reject bookings without it. |
upsert_travelers.contact.title | string | No | Title of the person paying (e.g. “mr”, “ms”, “mx”). Required by some rail carriers. |
upsert_travelers.contact.street_and_number | string | No | Billing street and number. Required by some rail/coach carriers. |
upsert_travelers.contact.city | string | No | Billing city. Required by some rail/coach carriers. |
upsert_travelers.contact.zip_code | string | No | Billing postal code. Required by some rail/coach carriers. |
upsert_travelers.contact.country_code | string | No | Billing country as an ISO 3166-1 alpha-2 code (e.g. “FR”). |
upsert_travelers.contact.terms_accepted | boolean | No | Whether the traveller accepted the CARRIER’s terms and conditions, which are separate from Jinko’s. Send true only if they were actually shown and accepted. |
select_ancillaries | object | No | Select ancillaries (bags, seats, meals) for a quoted trip item. Uses full-replacement semantics, send all desired selections. |
select_ancillaries.item_id | string | Yes | ID of the trip item to select ancillaries for. Get from trip response trip_items[].id |
select_ancillaries.selections | array<object> | Yes | Ancillary selections. Full replacement, send all desired selections each time. Get offer_ids from trip_item.available_ancillaries[].offer_id |
select_ancillaries.selections[].offer_id | string | Yes | Ancillary offer_id from available_ancillaries on the trip item |
select_ancillaries.selections[].category | string | No | Ancillary category (BAGGAGE, SEAT, MEAL, etc.) |
select_ancillaries.selections[].pax_ref_id | string | No | Passenger reference ID (for per-pax ancillaries) |
select_ancillaries.selections[].segment_ref_ids | array<string> | No | Segment reference IDs (for segment-scoped ancillaries) |
select_ancillaries.selections[].journey_ref_id | string | No | Journey reference ID (for journey-scoped ancillaries) |
select_ancillaries.selections[].quantity | integer | No | Quantity (defaults to 1) |
user_intent | string | No | The end user’s current request in their own words, e.g. “find a cheap flight to Tokyo in mid-June”. Pass it as-is when short; otherwise condense the goal and constraints into 1-2 sentences. Strip personal identifiers (names, emails, phone numbers, addresses, payment details), replace them with placeholders like “[name]”. Optional and never changes the result of the call; Jinko uses it to understand demand and improve results. |
Examples
Create a new trip (add flight + set travelers in one call):{
"name": "trip",
"arguments": {
"add_item": {
"trip_item_token": "offer_abc123:fare_xyz"
},
"upsert_travelers": {
"travelers": [
{
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1990-01-15",
"gender": "FEMALE",
"passenger_type": "ADULT",
"frequent_flyer": { "airline": "LH", "number": "992100100" }
}
],
"contact": {
"email": "jane@example.com",
"phone": "+33612345678"
}
}
}
}
{
"name": "trip",
"arguments": {
"trip_id": "42",
"add_item": { "trip_item_token": "htl_abc..." }
}
}
{
"name": "trip",
"arguments": {
"trip_id": "42",
"upsert_travelers": {
"travelers": [
{ "first_name": "Jane", "last_name": "Doe", "date_of_birth": "1990-01-15", "gender": "FEMALE", "passenger_type": "ADULT", "frequent_flyer": { "airline": "LH", "number": "992100100" } },
{ "first_name": "John", "last_name": "Doe", "date_of_birth": "2015-05-20", "gender": "MALE", "passenger_type": "CHILD" }
],
"contact": { "email": "jane@example.com", "phone": "+33612345678" }
}
}
}
frequent_flyer object so miles are credited on the booking. airline is the IATA code of the program issuer (e.g. LH for Lufthansa Miles & More), not necessarily the operating carrier, since alliances credit miles on partner flights. Both airline and number are required when the object is present.
{
"name": "trip",
"arguments": {
"trip_id": "42",
"upsert_travelers": {
"travelers": [
{
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1990-01-15",
"gender": "FEMALE",
"passenger_type": "ADULT",
"frequent_flyer": { "airline": "LH", "number": "992100100" }
}
]
}
}
}
Traveler details must match real travel documents, airlines enforce name / DOB matching and reject bookings where they don’t. Never let an agent fabricate these.
trip_id, the current item list, and totals. Use trip_id with checkout when you’re ready to check out.