Accommodation Search
The accommodation search system provides hotel and lodging recommendations by integrating with Booking.com and Sabre APIs.
Providers
| Provider | Purpose | Status |
|---|---|---|
| Booking.com | Primary search and booking | ✅ Active |
| Sabre | GDS 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
- User Message → Frontend sends chat message via SSE stream
- Context Agent → Extracts trip requirements, creates
TripStepandTripSearchentities - Conversational Agent → Decides to plan trip, calls
plan_triptool - Trip Planner Agent → Executes
search_accommodationstool with filters - Orchestration →
AccommodationSearchOrchestratorqueries Booking.com and Sabre concurrently - Aggregation → Results from both providers merged and deduplicated
- Feature Extraction — Amenities, ratings, distances extracted for TTV Scoring
- Scoring — Options scored against user preferences and company policies
- Insight Generation — Natural language explanations created via
InsightService - Persistence — Results saved as
TripOptionentities with insights - Recommendations → Trip Planner calls
recommend_optionsto select top 3 - 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:
| Feature | Type | Category |
|---|---|---|
DistanceFeature | float | Location |
StarRatingFeature | float | Quality |
GuestRatingFeature | float | Quality |
PricePerNightFeature | float | Budget |
HasGymFeature | bool | Amenities |
HasWifiFeature | bool | Amenities |
HasBreakfastFeature | bool | Amenities |
IsRefundableFeature | bool | Policies |
Related Documentation
- AI Orchestration — How AI agents coordinate search
- Orchestrator — Business logic coordination
- Sabre Implementation — GDS integration
- Booking.com Integration — Primary search provider
- TTV Scoring — How scoring works