Search bookable tours and activities on freetour.com (all types — walking, bike, food, bus, day trips, and more). Filter by `categories` only when the user asks for a specific tour type. Search by city, country, date range, start time, duration, guide language, price range, rating and keywords. Always pass `locale`: en, es, pt, de, fr, or it — the language the user wrote in. Never infer locale from the city. When locale is en (including unsupported user languages), reply in English. UNSUPPORTED USER LANGUAGE (not en/es/pt/de/fr/it): always pass locale: "en". Put only English theme keywords in query (gothic quarter, tapas) — never the user's full sentence or non-English words. Map price, time, duration, category, destination (`city`/`cities`/`country`), and guide-language intent to the matching tool fields — not query. Reply to the user in English; tour cards and widget labels will be in English. START TIME FILTERING (when the user mentions a time or part of day): Use time_from and time_to as integers 0–23 (whole hours only, inclusive). Never put time words in `query` — use time_from/time_to. Exact hour H ('at 10', 'um 10 Uhr', 'a las 10'): time_from: H, time_to: H. Range A–B ('from 10 to 12', 'between 10am and 12pm'): time_from: A, time_to: B. After H ('after 10', 'from 10am'): time_from: H (omit time_to). Until / before H inclusive ('before 10', 'until 10am'): time_to: H (omit time_from). Morning ('morning', 'morgens', 'matin'): time_from: 0, time_to: 11. Afternoon ('afternoon', 'nachmittags', 'tarde'): time_from: 12, time_to: 16. Evening ('evening', 'abends', 'soir'): time_from: 17, time_to: 23. 12 PM → 12, 12 AM → 0, 3 PM → 15. When time_from or time_to is set and no date is given, also pass date_from (today) so the API can match scheduled events. DATE FILTERING: use `date_from` and `date_to` as YYYY-MM-DD. Never put dates in `query`. Single calendar day ('tomorrow', 'завтра', 'mañana', 'demain', 'on July 3'): set BOTH date_from and date_to to that same day. Day after tomorrow ('післязавтра', 'pasado mañana', 'übermorgen'): same day in both fields. Today ('today', 'сьогодні', 'hoy', 'aujourd'hui'): both fields = today. Explicit range ('from July 1 to July 5', '2026-07-01 to 2026-07-05'): date_from = earlier day, date_to = later day. Next week ('next week', 'наступного тижня'): date_from = Monday, date_to = Sunday of next week. This weekend ('this weekend', 'ці вихідні'): date_from = Saturday, date_to = Sunday. Open-ended start ('tours from July 1' with no end): date_from only — server extends date_to by 7 days. Compute relative dates from the user's local today when calling the tool. DURATION FILTERING (when the user mentions tour length): Use duration_from and duration_to as integers in MINUTES (inclusive). Never put duration words in `query`. Exact length L ('1 hour', '90 minutes'): duration_from: L, duration_to: L (1h=60, 1.5h=90, 2h30=150). Range A–B ('2-3 hours', 'von 2 bis 3 Stunden'): duration_from: A*60, duration_to: B*60. At least H ('at least 2h', '2+ hours'): duration_from: H*60. Up to H inclusive ('up to 2 hours', 'max 2h'): duration_to: H*60. Shorter than H ('under 2h'): duration_to: H*60-1. Longer than H ('over 3 hours'): duration_from: H*60+1. Short tour: duration_to: 90. Long tour: duration_from: 180. 1–2 hours: duration_from: 60, duration_to: 120. 2–3 hours: duration_from: 120, duration_to: 180. GUIDE LANGUAGE FILTERING (when the user wants tours conducted in a specific language): Use language_codes as an array of ISO 639-1 codes (e.g. ["ja"] for Japanese, ["es"] for Spanish). Never put language names in `query` — use language_codes. This filters which language the guide speaks; it is NOT the same as `locale` (widget/response language). NEVER set locale to the guide language — locale is only how the USER wrote their message. Example: user writes in English 'find tours in London in Spanish' → locale: "en", city: "London", language_codes: ["es"] (cards in English, Spanish flag on tour). Wrong: locale: "es" for that query — that translates the card UI to Spanish. Example: 'tours in Japanese' → language_codes: ["ja"], locale from prompt language (en if English). Multiple options ('English or Spanish'): language_codes: ["en", "es"]. Supported guide-language codes: en, es, pt, de, fr, it, nl, pl, ru, uk, cs, da, sv, fi, el, hu, ro, hr, tr, ar, he, hi, ja, ko, zh, th, id, fa. Do not confuse with destination country ('tours in Spain' → country: Spain, not language_codes). PRICE FILTERING (mandatory when the user mentions price or budget): Prices are integers in EUR. Never put price words in `query` — use price_from, price_to, free_only, or paid_only. Exact price X ('for X euros', 'por X€'): price_from: X, price_to: X. Free / tip-based ('free', 'gratis', 'kostenlos'): free_only: true (same as price_from: 0, price_to: 0). Range X–Y ('between X and Y', 'von X bis Y'): price_from: X, price_to: Y. From X upward ('from €X', 'ab X€', 'X+'): price_from: X (omit price_to). Up to X inclusive ('up to €X', 'X or less'): price_to: X and price_from: 0. Cheaper than X / less than X ('under X', 'moins de X'): price_to: X-1 and price_from: 0. More expensive than X ('over €X', 'más de X'): price_from: X+1. Paid only ('paid', 'not free'): paid_only: true (same as price_from: 1). If the user mentions ANY price constraint, set the appropriate fields before calling search_tours — never search by city alone. RATING FILTERING (mandatory when the user mentions rating, score, reviews or stars): Ratings are floats 0–10 on the freetour scale, never a 5-star scale. Never put rating words in `query` — use rating_from and rating_to. Named score X ('rating 6', 'rated 8', '8/10'): rating_from: X, rating_to: X.9 — the X.0–X.9 band, so 'rating 6' must not return a 9.5 tour. Decimal score X ('9.8', 'exactly 9.8'): rating_from: X, rating_to: X. At least X ('8+', 'X or more', 'from X'): rating_from: X, rating_to: 10. Range A–B ('between 8 and 10'): rating_from: A, rating_to: B. Up to X inclusive: rating_to: X, rating_from: 0. Below X ('under 7'): rating_to: X-1 (X-0.1 for a decimal), rating_from: 0. Highly rated / top rated / best rated: rating_from: 8, rating_to: 10. Stars are a minimum on the 0–10 scale: 5 stars → rating_from: 9, 4 → 8, 3 → 6, 2 → 4, 1 → 2, each with rating_to: 10. Never map 5 stars to 10. Do not confuse rating with price (needs €/euro), start time (needs am/pm/morning/at H) or duration (needs hours/minutes). If the user mentions ANY rating constraint, set these fields before calling search_tours, and keep every other filter they mentioned. CATEGORY FILTERING: pass `categories` as English API names (never translated). Allowed: Walking Tour, Online Tour, City Ride Tours, Day Trips, Night Life, Food & Drink, Running Tour, Nature & Wildlife, Cruises & Boat, Other, Top Picks. Map user intent even if they wrote another language (e.g. 'tours a pie' → Walking Tour, 'gastronómicos' → Food & Drink, bike → City Ride Tours, boat/cruise → Cruises & Boat). Legacy labels like Bike Tour / Cruises / Nature Tours are normalized server-side to the current API names. Do not default to Walking Tour — omit `categories` to search all types unless the user asks for one. Do not put category type words in `query` when `categories` is set — keep `query` for themes/neighbourhoods only. CITY FILTERING: pass destination cities in English (Barcelona, Berlin, Rome). Put destinations in `city` (one city) or `cities` (array) — not in `query`. For one city use `city` or `cities` with a single element. MULTI-CITY: when the user names several cities (e.g. 'Barcelona and Madrid', 'Paris ou Lyon', 'Berlin und München'), pass cities: ["Barcelona", "Madrid"] in one search_tours call — do not join them into one string. Foreign or local spellings are normalized server-side when possible (Barcelone → Barcelona, Roma → Rome, Praha → Prague, München → Munich). Omit `country` when `city` or `cities` is set. If the city is ambiguous or missing, ask the user to clarify before searching. COUNTRY FILTERING: use `country` when the user wants tours across a whole country without naming a city (e.g. 'tours in Spain', 'find tours in France', 'знайди тури в Іспанії'). Pass the English country name (Spain, France, Germany) — foreign spellings are normalized server-side (España, Spanien, Іспанія → Spain). Put the country in `country`, not in `query` or `language_codes`. 'Tours in Spanish' means guide language → language_codes: ["es"]; 'tours in Spain' means destination → country: "Spain". Omit `country` when `city` or `cities` is set. One country per search — for multiple countries, run separate searches or ask which country. DESCRIPTION FEATURES: use `must_have` / `must_not_have` for hard requirements or exclusions that must appear (or not appear) in the tour description text. Pass short English keywords only (e.g. guide, tapas, wheelchair, bus, crowded). Translate from the user's language to English. Do not use for tour type (use `categories`), price (use price_* / free_only), guide language (use language_codes), or neighbourhood themes (use `query`). Examples: 'with a guide' → must_have: ["guide"]; 'not crowded' → must_not_have: ["crowded"]; 'no bus' → must_not_have: ["bus", "coach"]. Returns tour cards with ratings, prices and direct booking links.
search_tours