Skip to main content

Accommodation Search

The accommodation search system provides hotel and lodging recommendations by integrating with Booking.com and Sabre APIs.

Providers

ProviderPurposeStatus
Booking.comPrimary search and booking✅ Active
SabreGDS integration✅ Active

Architecture

┌─────────────────────────────────────────────────────────────┐
│ Frontend (React) │
│ Chat Interface → Results Display │
└──────────────────────────┬──────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ Chat Endpoint (SSE Stream) │
│ ChatOrchestrator │
└──────────────────────────┬──────────────────────────────────┘

┌────────────┴────────────┐
▼ ▼
┌────────────────────────┐ ┌────────────────────────────────┐
│ Context Agent │ │ Conversational Agent │
│ (Trip Requirements) │ │ (User Dialogue) │
└────────────────────────┘ └──────────────┬─────────────────┘


┌────────────────────────────────┐
│ Trip Planner Agent │
│ search_accommodations (PydanticAI)│
└──────────────┬─────────────────┘


┌────────────────────────────────┐
│ AccommodationSearchOrchestrator │
│ Coordinates search & scoring │
└──────────────┬─────────────────┘

┌─────────────┴─────────────┐
▼ ▼
┌────────────────────┐ ┌────────────────────┐
│ Booking.com │ │ Sabre │
│ Service │ │ Service │
└────────────────────┘ └────────────────────┘

AI Agent Tool

The accommodation search is exposed as a tool for the Trip Planner Agent (built with PydanticAI):

class TripPlannerAgentToolset(BaseAgentToolset):
@observe(name=ToolName.SEARCH_ACCOMMODATIONS, as_type="tool")
async def search_accommodations(
self,
ctx: RunContext[TripPlannerAgentDeps],
user_explanation: str,
trip_search_id: UUID,
filters: SearchAccommodationsFilters,
) -> dict[str, int | UUID]:
uow = self._unit_of_work_factory()
async with uow.background_context():
summary = await self._accommodation_search_orchestrator.search_accommodations(
uow, trip_search_id, filters
)
return {
"total_count": summary.total_count,
"booking_count": summary.booking_count,
"sabre_count": summary.sabre_count,
"trip_search_id": summary.trip_search_id,
}

The @observe decorator is from Langfuse for observability tracing.

Search Filters

Available filters for accommodation search:

class SearchAccommodationsFilters(BaseModel):
"""Filters for accommodation search."""

destination: str # City name or coordinates
checkin_date: date
checkout_date: date
guests: int = 1
rooms: int = 1

# Optional filters
min_price: float | None = None
max_price: float | None = None
min_rating: float | None = None
star_rating: list[int] | None = None # [3, 4, 5]
amenities: list[str] | None = None # ["wifi", "parking", "gym"]
property_type: list[str] | None = None # ["hotel", "apartment"]

Data Flow

  1. User Message → Frontend sends chat message via SSE stream
  2. Context Agent → Extracts trip requirements, creates TripStep and TripSearch entities
  3. Conversational Agent → Decides to plan trip, calls plan_trip tool
  4. Trip Planner Agent → Executes search_accommodations tool with filters
  5. OrchestrationAccommodationSearchOrchestrator queries Booking.com and Sabre concurrently
  6. Aggregation → Results from both providers merged and deduplicated
  7. Feature Extraction — Amenities, ratings, distances extracted for TTV Scoring
  8. Scoring — Options scored against user preferences and company policies
  9. Insight Generation — Natural language explanations created via InsightService
  10. Persistence — Results saved as TripOption entities with insights
  11. Recommendations → Trip Planner calls recommend_options to select top 3
  12. Response → Conversational Agent presents ranked options to user

Entity Structure

Accommodation

class Accommodation(BaseEntity):
"""Represents a hotel/property."""

external_id: str # Booking.com property ID
name: str
address: str
city: str
country_code: str
latitude: float
longitude: float
star_rating: float | None
guest_rating: float | None
chain: str | None
distance_km: float | None # From search center

# Relationships
amenities: list[Amenity]
products: list[Product] # Room options

Product (Room)

class Product(BaseEntity):
"""Represents a room/product offering."""

accommodation_id: UUID
name: str
description: str | None
price_per_night: float
currency: str
room_size_sqm: float | None
max_occupancy: int
is_refundable: bool
cancellation_policy: str | None

Scoring Features

Accommodation-specific features for scoring:

FeatureTypeCategory
DistanceFeaturefloatLocation
StarRatingFeaturefloatQuality
GuestRatingFeaturefloatQuality
PricePerNightFeaturefloatBudget
HasGymFeatureboolAmenities
HasWifiFeatureboolAmenities
HasBreakfastFeatureboolAmenities
IsRefundableFeatureboolPolicies