> ## Documentation Index
> Fetch the complete documentation index at: https://cortex-e852fafe-docs-pro-2457-cookbooks-cleanup.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Travel Planner

> Learn how to build an intelligent travel planning platform that understands natural language queries and provides personalized recommendations using HydraDB's AI search and memory capabilities.

> **Note**: All code in this guide uses the official HydraDB TypeScript SDK. Base URL: `https://api.hydradb.com`. Get your API key at [app.hydradb.com](https://app.hydradb.com).

## Prerequisites

**Required knowledge**: TypeScript/JavaScript basics, REST APIs, environment variables\
**Required tools**:

* HydraDB API key
* Node.js 18+ (`node --version`)
* `npm install @hydradb/sdk`

## What You'll Build

By the end of this cookbook, you'll be able to:

* Upload hotel, flight, restaurant, and activity data into HydraDB with correct database scoping
* Answer complex natural language travel queries like "Plan a 5-day romantic trip to Italy for \$3000" using `query` with `mode: "thinking"`
* Store per-user travel preferences and booking history as AI memories for personalized recommendations
* Build family, business, and adventure trip planning flows using semantic search

## The Problem with Traditional Travel Planning

Traditional travel platforms force users to think like search engines:

* **Keyword matching**: “Hotels in Paris” or “Flights to Tokyo”
* **Filter-heavy interfaces**: Complex combinations of dates, prices, and amenities
* **Manual research**: Hours spent comparing options across multiple sites
* **Generic recommendations**: One-size-fits-all suggestions that ignore personal preferences
* **Fragmented experience**: Separate searches for flights, hotels, activities, and restaurants

## The AI-Powered Solution

With HydraDB, travelers can plan naturally and get personalized recommendations:

* **“Plan a 5-day romantic trip to Italy for my anniversary in September with a budget of \$3000”**
* **“Find me a family-friendly resort in Bali with a kids club and water sports activities”**
* **“I want to experience authentic local cuisine in Bangkok: suggest restaurants and food tours”**
* **“Plan a solo backpacking trip through Southeast Asia for 3 weeks, focusing on cultural experiences”**
* **“Find pet-friendly accommodations in San Francisco with easy access to dog parks”**

## Architecture Overview

```mermaid theme={"dark"}
graph TD
    A["Travel Planning Interface<br/>• Natural Language Search<br/>• AI Chat Assistant<br/>• Personalized Recommendations"] 
    B["AI Travel Engine<br/>• Query Understanding<br/>• Preference Matching<br/>• Itinerary Generation"]
    C["HydraDB APIs<br/>• Retrieval Engine<br/>• AI Memories<br/>• Multi-Step Reasoning"]
    
    D["Travel Data Sources<br/>• Hotel databases<br/>• Flight APIs<br/>• Restaurant reviews<br/>• Activity listings<br/>• Travel guides"]
    E["Structured Travel Data<br/>• Pricing information<br/>• Availability calendars<br/>• Location metadata<br/>• Amenity details"]
    F["AI Memory Store<br/>• User preferences<br/>• Travel history<br/>• Booking patterns<br/>• Personalized insights"]
    
    A <--> B
    B <--> C
    B --> D
    C --> E
    C --> F
```

## Step 1: Travel Data Ingestion Strategy

### 1.1 Hotel and Accommodation Data

Start by uploading hotel and accommodation data as app knowledge:

```javascript theme={"dark"}
import { HydraDBClient } from "@hydradb/sdk";

const client = new HydraDBClient({ token: process.env.HYDRA_DB_API_KEY });

const uploadHotelData = async (hotels, database, collection) => {
  const hotelSources = hotels.map(hotel => ({
    id: `hotel_${hotel.id}`,
    database: database,
    collection: collection,
    title: hotel.name,
    type: "accommodation",
    description: hotel.description,
    timestamp: new Date().toISOString(),
    content: {
      text: `${hotel.name} - ${hotel.description}. Located in ${hotel.city}, ${hotel.country}.
             Amenities: ${hotel.amenities.join(', ')}.
             Average rating: ${hotel.rating}/5 from ${hotel.reviewCount} reviews.
             Price range: ${hotel.priceRange}.
             Room types: ${hotel.roomTypes.join(', ')}.`,
    },
    additional_metadata: {
      category: "accommodation",
      location: hotel.coordinates,
      priceRange: hotel.priceRange,
      rating: hotel.rating,
      amenities: hotel.amenities,
      propertyType: hotel.propertyType
    }
  }));

  await client.context.ingest({
    database: database,
    collection: collection,
    appKnowledge: JSON.stringify(hotelSources),
    upsert: "true",
  });
};
```

### 1.2 Flight and Transportation Data

Upload flight schedules, routes, and transportation options:

```javascript theme={"dark"}
const uploadFlightData = async (flights, database, collection) => {
  const flightSources = flights.map(flight => ({
    id: `flight_${flight.id}`,
    database: database,
    collection: collection,
    title: `${flight.airline} ${flight.flightNumber}`,
    type: "transportation",
    description: `Flight from ${flight.origin} to ${flight.destination}`,
    timestamp: new Date().toISOString(),
    content: {
      text: `${flight.airline} flight ${flight.flightNumber} from ${flight.origin} to ${flight.destination}.
             Duration: ${flight.duration}.
             Aircraft: ${flight.aircraft}.
             Departure: ${flight.departureTime}.
             Arrival: ${flight.arrivalTime}.`,
    },
    additional_metadata: {
      category: "transportation",
      origin: flight.origin,
      destination: flight.destination,
      airline: flight.airline,
      duration: flight.duration,
      price: flight.price,
      class: flight.class
    }
  }));

  await client.context.ingest({
    database: database,
    collection: collection,
    appKnowledge: JSON.stringify(flightSources),
    upsert: "true",
  });
};
```

### 1.3 Restaurant and Dining Data

Upload restaurant information with cuisine types and reviews:

```javascript theme={"dark"}
const uploadRestaurantData = async (restaurants, database, collection) => {
  const restaurantSources = restaurants.map(restaurant => ({
    id: `restaurant_${restaurant.id}`,
    database: database,
    collection: collection,
    title: restaurant.name,
    type: "dining",
    description: restaurant.description,
    timestamp: new Date().toISOString(),
    content: {
      text: `${restaurant.name} - ${restaurant.description}.
             Cuisine: ${restaurant.cuisine}.
             Location: ${restaurant.address}.
             Price range: ${restaurant.priceRange}.
             Rating: ${restaurant.rating}/5.
             Specialties: ${restaurant.specialties.join(', ')}.`,
    },
    additional_metadata: {
      category: "dining",
      cuisine: restaurant.cuisine,
      priceRange: restaurant.priceRange,
      rating: restaurant.rating,
      location: restaurant.coordinates,
      dietaryOptions: restaurant.dietaryOptions
    }
  }));

  await client.context.ingest({
    database: database,
    collection: collection,
    appKnowledge: JSON.stringify(restaurantSources),
    upsert: "true",
  });
};
```

### 1.4 Activity and Attraction Data

Upload tourist attractions, activities, and experiences:

```javascript theme={"dark"}
const uploadActivityData = async (activities, database, collection) => {
  const activitySources = activities.map(activity => ({
    id: `activity_${activity.id}`,
    database: database,
    collection: collection,
    title: activity.name,
    type: "activity",
    description: activity.description,
    timestamp: new Date().toISOString(),
    content: {
      text: `${activity.name} - ${activity.description}.
             Category: ${activity.category}.
             Duration: ${activity.duration}.
             Difficulty: ${activity.difficulty}.
             Best time to visit: ${activity.bestSeason}.
             Price: ${activity.price}.`,
    },
    additional_metadata: {
      category: "activity",
      activityType: activity.category,
      duration: activity.duration,
      difficulty: activity.difficulty,
      price: activity.price,
      ageGroup: activity.ageGroup
    }
  }));

  await client.context.ingest({
    database: database,
    collection: collection,
    appKnowledge: JSON.stringify(activitySources),
    upsert: "true",
  });
};
```

## Step 2: Building the AI Travel Assistant

### 2.1 Natural Language Query Processing

Create a travel query handler that understands complex travel requests:

```javascript theme={"dark"}
class TravelAssistant {
  constructor(client) {
    this.client = client;
  }

  async planTrip(query, userProfile) {
    // Use HydraDB's thinking mode for complex travel planning
    const response = await this.client.query({
      query: query,
      database: userProfile.database,
      collection: userProfile.collection,
      mode: "thinking",
      alpha: "auto",
      maxResults: 20
    });

    return this.processResponse(response);
  }

  async processResponse(response) {
    // Return the ranked chunks and graph context; pass them to your LLM to draft the itinerary
    return {
      chunks: response.data?.chunks,
      graphRelations: response.data?.graphContext?.chunkRelations,
      queryPaths: response.data?.graphContext?.queryPaths
    };
  }
}
```

### 2.2 Personalized Recommendation Engine

Implement AI memories to remember user preferences and past travel patterns:

```javascript theme={"dark"}
class PersonalizationEngine {
  constructor(client) {
    this.client = client;
  }

  async generateUserMemory(userInteraction) {
    // Generate memories based on user's travel preferences and booking patterns
    await this.client.context.ingest({
      type: 'memory',
      database: userInteraction.database,
      collection: userInteraction.userId,
      memories: JSON.stringify([{
        // A unique id per interaction, so each one adds a memory instead of replacing the last
        id: `interaction_${userInteraction.userId}_${Date.now()}`,
        text: `User searched for: ${userInteraction.query}.
                   They showed interest in: ${userInteraction.clickedItems.join(', ')}.
                   They booked: ${userInteraction.bookedItems.join(', ')}.`,
        infer: true,
        user_name: userInteraction.userName
      }])
    });
  }

  async getPersonalizedRecommendations(database, collection, destination) {
    // Retrieve user memories to provide personalized recommendations
    const memories = await this.client.query({
      type: "memory",
      database: database,
      collection: collection,
      query: `travel preferences for ${destination}`,
      maxResults: 10
    });

    // memories.chunks contains the user's past preference signals ranked by relevance.
    // Pass these as context to your LLM to generate personalized recommendations.
    return memories.data?.chunks;
  }
}
```

## Step 3: Advanced Search Capabilities

### 3.1 Semantic Search for Travel Experiences

Implement semantic search to understand complex travel desires:

```javascript theme={"dark"}
const searchTravelExperiences = async (query, database, collection, filters = {}) => {
  const searchQuery = `${query} ${filters.destination ? `in ${filters.destination}` : ''}
                       ${filters.budget ? `budget ${filters.budget}` : ''}
                       ${filters.travelStyle ? `${filters.travelStyle} travel` : ''}`;

  const response = await client.query({
    query: searchQuery,
    database: database,
    collection: collection,
    mode: "fast",
    alpha: 1.0,
    maxResults: 20
  });

  return response;
};
```

### 3.2 Multi-Modal Travel Search

Support different types of travel queries:

```javascript theme={"dark"}
const handleTravelQuery = async (query, context) => {
  // HydraDB's semantic search handles all query types without manual classification.
  // Use mode: "thinking" for complex multi-part queries (full itineraries, comparisons).
  // Use mode: "fast" for single-category lookups (hotels only, flights only).
  const isComplex = /itinerary|plan|trip|vacation|week|days/i.test(query);

  const response = await client.query({
    query,
    database: context.database,
    collection: context.collection,
    mode: isComplex ? "thinking" : "fast",
    maxResults: isComplex ? 20 : 10
  });

  return response.data.chunks;
};
```

## Step 4: Real-World Implementation Examples

### 4.1 Family Vacation Planning

**User Query**: *“Plan a 7-day family vacation to Orlando with kids aged 8 and 12, budget \$4000, we love theme parks and want kid-friendly restaurants”*

```javascript theme={"dark"}
const planFamilyVacation = async (query, userProfile) => {
  const response = await client.query({
    query: query,
    database: userProfile.database,
    collection: userProfile.collection,
    mode: "thinking",
    maxResults: 20
  });

  // Group chunks by the `category` each item carries in additional_metadata.
  // response.data.chunks are ranked by relevance, and each group keeps that order.
  const itinerary = {
    accommodation: response.data.chunks.filter(c => c.additionalMetadata?.category === "accommodation"),
    activities:    response.data.chunks.filter(c => c.additionalMetadata?.category === "activity"),
    dining:        response.data.chunks.filter(c => c.additionalMetadata?.category === "dining"),
    transportation: response.data.chunks.filter(c => c.additionalMetadata?.category === "transportation")
  };

  return itinerary;
};
```

### 4.2 Business Travel Optimization

**User Query**: *“I need to travel to London for business next week, find hotels near financial district with good WiFi and meeting rooms”*

```javascript theme={"dark"}
const planBusinessTravel = async (query, userProfile) => {
  const response = await client.query({
    query: query,
    database: userProfile.database,
    collection: userProfile.collection,
    mode: "fast",
    maxResults: 10
  });

  // Return ranked chunks directly. Filter by additionalMetadata.amenities or additionalMetadata.location as needed.
  return response.data.chunks;
};
```

### 4.3 Adventure Travel Planning

**User Query**: *“I want to go trekking in Nepal for 2 weeks, suggest routes for intermediate hikers with cultural experiences”*

```javascript theme={"dark"}
const planAdventureTravel = async (query, userProfile) => {
  const response = await client.query({
    query: query,
    database: userProfile.database,
    collection: userProfile.collection,
    mode: "thinking",
    maxResults: 15
  });

  // Return ranked chunks directly. Sort or filter by additionalMetadata.difficulty for hiking-specific results.
  return response.data.chunks;
};
```

## Step 5: Contextual Recommendations

### 5.1 Weather-Based Suggestions

```javascript theme={"dark"}
const getWeatherBasedRecommendations = async (destination, travelDate, database, collection) => {
  const weatherQuery = `What activities and attractions are best in ${destination} during ${travelDate} considering weather conditions?`;

  const response = await client.query({
    query: weatherQuery,
    database: database,
    collection: collection,
    mode: "fast",
    maxResults: 10
  });

  return response;
};
```

### 5.2 Cultural Event Integration

```javascript theme={"dark"}
const getCulturalEventRecommendations = async (destination, travelDate, database, collection) => {
  const eventQuery = `What cultural events, festivals, or seasonal experiences are happening in ${destination} during ${travelDate}?`;

  const response = await client.query({
    query: eventQuery,
    database: database,
    collection: collection,
    mode: "fast",
    maxResults: 10
  });

  return response;
};
```

## Step 6: Learning from User Behavior

### 6.1 Booking Pattern Analysis

```javascript theme={"dark"}
const analyzeBookingPatterns = async (database, collection, bookingData) => {
  const analysisText = `User has booked: ${bookingData.map(b => b.description).join(', ')}. What patterns can we identify about their travel preferences?`;

  // Generate memory for future personalization
  await client.context.ingest({
    type: 'memory',
    database: database,
    collection: collection,
    upsert: "true",
    memories: JSON.stringify([{
      id: `booking_${collection}`,
      text: analysisText,
      infer: true,
      user_name: bookingData[0].userName
    }])
  });
};
```

### 6.2 Search Refinement

```javascript theme={"dark"}
const refineSearch = async (originalQuery, userFeedback, database, collection) => {
  const refinedQuery = `${originalQuery}. User feedback: ${userFeedback}. Please adjust recommendations accordingly.`;

  const response = await client.query({
    query: refinedQuery,
    database: database,
    collection: collection,
    mode: "thinking",
    maxResults: 10
  });

  return response;
};
```

## Advanced Features

### Multi-Language Support

```javascript theme={"dark"}
const handleMultiLanguageQuery = async (query, language, destination, database, collection) => {
  const localizedQuery = `${query} (query in ${language} for ${destination})`;

  const response = await client.query({
    query: localizedQuery,
    database: database,
    collection: collection,
    mode: "fast",
    maxResults: 10
  });

  return response;
};
```

### Real-Time Price Monitoring

HydraDB does not watch prices. Store the alert rule as a memory so later queries find it, and run the price checks in your own scheduled job.

```javascript theme={"dark"}
const monitorPriceChanges = async (travelPlan) => {
  const priceText = `Monitor price changes for: ${travelPlan.description}. Alert if prices drop by 10% or more.`;

  // Save the alert rule as a memory; your scheduled job does the price checks
  await client.context.ingest({
    type: 'memory',
    database: travelPlan.database,
    collection: travelPlan.userId,
    upsert: "true",
    memories: JSON.stringify([{
      id: `price_${travelPlan.userId}`,
      text: priceText,
      infer: true
    }])
  });
};
```

## Example User Interactions

### Scenario 1: Spontaneous Weekend Trip

**User**: *“I want to go somewhere warm this weekend, budget \$800, flying from New York”*

**AI Response**: Based on your budget and preference for warm weather, I recommend:

* **Miami, Florida**: 3-day weekend package with beachfront hotel and flights for \$750
* **Austin, Texas**: Music and food scene with boutique hotel for \$680
* **Savannah, Georgia**: Historic charm with B\&B accommodation for \$620

### Scenario 2: Anniversary Celebration

**User**: *“Plan a romantic anniversary trip to Paris for 5 days in May, we love art museums and fine dining”*

**AI Response**: For your romantic Paris anniversary:

* **Accommodation**: Hotel des Grands Boulevards in the 2nd arrondissement
* **Day 1**: Louvre Museum morning, Seine river cruise evening
* **Day 2**: Musée d'Orsay, dinner at L'Ambroisie (Michelin 3-star)
* **Day 3**: Montmartre walking tour, Picasso Museum
* **Day 4**: Versailles day trip, romantic dinner at Le Meurice
* **Day 5**: Rodin Museum, farewell lunch at L'Atelier de Joël Robuchon

### Scenario 3: Solo Adventure Planning

**User**: *“I'm planning a solo backpacking trip through Southeast Asia for a month, focusing on cultural immersion and budget-friendly options”*

**AI Response**: Your month-long Southeast Asia adventure:

* **Route**: Thailand to Vietnam to Cambodia to Laos
* **Budget**: \$2,000-2,500 total
* **Accommodation**: Mix of hostels and homestays
* **Cultural experiences**: Cooking classes, temple visits, local festivals
* **Transportation**: Buses and trains for authentic experience

## Integration with Booking Systems

HydraDB returns only what you ingested and does not call booking APIs. Use these queries to find matching listings, then get live availability and prices from your booking provider.

### Real-Time Availability Checking

```javascript theme={"dark"}
const checkAvailability = async (hotelId, checkIn, checkOut, database, collection) => {
  const availabilityQuery = `Check availability for ${hotelId} from ${checkIn} to ${checkOut}`;

  const response = await client.query({
    query: availabilityQuery,
    database: database,
    collection: collection,
    mode: "fast",
    maxResults: 5
  });

  return response;
};
```

### Dynamic Pricing Integration

```javascript theme={"dark"}
const getDynamicPricing = async (searchResults, userProfile) => {
  const pricingQuery = `Get current pricing for these travel options considering user's booking history and preferences`;

  const response = await client.query({
    query: pricingQuery,
    database: userProfile.database,
    collection: userProfile.collection,
    mode: "fast",
    maxResults: 10
  });

  return response;
};
```

## Conclusion

An AI travel planner built on HydraDB turns hours of research into a conversation. With memories, thinking-mode retrieval, and semantic search, your platform can understand what a traveler is asking for and personalize what it returns.

Key benefits of this approach:

* **Natural Language Understanding**: Users can express complex travel desires in natural language
* **Personalized Recommendations**: AI memories ensure recommendations improve over time
* **Contextual Awareness**: Multi-step reasoning considers all aspects of travel planning
* **Booking Integration**: Pair HydraDB results with live availability and prices from your booking provider

The result feels more like talking to a knowledgeable travel advisor than using a search engine.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.