From intuition to intelligence: Building a hotel pricing agent (Part 3) – Take me to the cloud

At this point, we have a disciplined conversational agent that recommends hotel room prices backed by a machine learning model trained on historical hotel data. No intuition, no heuristics, and no AI hallucinations.

While this setup already delivers strong pricing recommendations, it still runs locally, which limits its usefulness in real business workflows. To turn this into a true decision system — one that can be consumed by dashboards, applications, and automated processes — we need to deploy the pricing intelligence to the cloud.

In this part of the series, we transform the local pricing engine into a cloud-hosted decision API, making it accessible from tools such as Power BI and Power Apps, while preserving determinism, transparency, and control.

The high-level architecture

If you missed Part 1 and Part 2 of this series, the goal of this project is to help a hotel manager in Lagos, Algarve determine optimal room prices that maximize both occupancy and revenue.

The idea is not to replace the manager’s judgment, but to provide a tool — such as Power BI or Power Apps — that allows her to request pricing recommendations in a conversational way, while relying on a deterministic and reproducible pricing engine.

Given the same inputs, the model will always produce the same output. This determinism is essential for trust, auditability, and operational use.

Azure Functions as the execution layer

Since we are using Python and are strong adopters of the Power Platform (and Excel), we deploy the pricing engine safely to Azure using Azure Functions.

The model is not a static script. It dynamically infers results from the input scenario, combining machine-learning demand predictions with a controlled price optimization process. This engine becomes the intelligence layer of the solution and represents valuable intellectual property for the hotel.

By exposing it through a simple HTTP API, we decouple pricing logic from user interfaces and enable reuse across multiple tools and workflows.

Local conversation with the agent

Below is a real interaction with the agent running locally in VS Code:

User: I need a price recommendation for New Year's Eve sea view room.
      Competitors are charging €150 per night.

Agent: For the New Year's Eve sea_view room,
       how many sea_view rooms do you have in your hotel?

User: 20

Agent: To confirm:
       - Is this date a holiday?
       - Is it a weekend?
       - Is there a major event in town?

User: It is a holiday on a Wednesday.
      There’s a festival in Lagos.

[Model loading…]
[Model loaded successfully]

Running optimization:
Testing 25 prices from €75.00 to €225.00…

Agent: I recommend a price of €162.50 per night for your sea_view room,
       approximately 8.3% above the competitor’s price.

       Expected occupancy: 92.8%
       Expected revenue per room: €150.81

       For 20 rooms, total expected revenue ≈ €3,016.

       This premium reflects holiday demand and the local festival.

This interaction illustrates an important shift: the agent does not “think” or guess. It orchestrates a deterministic pricing engine that evaluates multiple price points and recommends the one that maximizes expected revenue under clearly defined assumptions.

Deploying the function to Azure

To deploy the function, we need an Azure subscription, a resource group, and a storage account. The function is then deployed directly from the local repository.


# create the resource group
az group create --name hotel-pricing-rg --location westeurope

# create storage account
az storage account create \
  --name hotelpricingstorage \
  --location westeurope \
  --resource-group hotel-pricing-rg \
  --sku Standard_LRS

# create the function app
az functionapp create \
  --resource-group hotel-pricing-rg \
  --consumption-plan-location westeurope \
  --runtime python \
  --runtime-version 3.11 \
  --functions-version 4 \
  --name hotel-pricing-function \
  --storage-account hotelpricingstorage \
  --os-type Linux

# deploy the function
func azure functionapp publish hotel-pricing-function

# get the function key
az functionapp function keys list \
  --resource-group hotel-pricing-rg \
  --name hotel-pricing-function \
  --function-name PriceRecommendation

Consuming the function from Power Apps

Before adding a conversational layer, we can consume the decision API in a wizard-style Power Apps canvas application. The user manually enters the pricing inputs using dropdowns, numeric inputs, and toggles.

Power Apps pricing input form

Input validation is enforced at the UI level. The action button is enabled only when all required inputs are present and correctly typed.

Calling the Azure Function via Power Automate

The button triggers an instant Power Automate flow. The flow calls the Azure Function using an HTTP action.

Power Automate trigger

The HTTP action is configured as follows:

  • Method: POST
  • Headers: Content-Type: application/json
  • URI: Azure Function endpoint (including function key)

{
  "competitor_price": @{triggerBody()['number']},
  "season": "@{triggerBody()['text']}",
  "room_type": "@{triggerBody()['text_1']}",
  "month": @{triggerBody()['text_2']},
  "rooms_capacity": @{triggerBody()['number_1']},
  "lead_time_avg": @{triggerBody()['number_2']},
  "is_weekend": @{triggerBody()['text_3']},
  "is_holiday": @{triggerBody()['text_4']},
  "event_flag": @{triggerBody()['text_5']}
}

HTTP action configuration

Passing the function key directly in the URL is acceptable for development and demos. In production, the key should be secured (custom connector, environment variable, API Management, or Azure AD authentication).

Parsing and returning the response

The response is parsed using a Parse JSON action:

Parse JSON action


{
  "type": "object",
  "properties": {
    "recommended_price": { "type": "number" },
    "expected_occupancy": { "type": "number" },
    "expected_revenue_per_room": { "type": "number" },
    "note": { "type": "string" }
  }
}

The flow returns the result to Power Apps using a Respond to a Power App or flow action:

Respond to Power Apps

  • recommended_price
  • expected_occupancy
  • expected_revenue_per_room

Calling the flow from Power Apps


Set(varPriceResult, Blank());

Set(
  varPriceResult,
  AzureFunctionHotelPrice.Run(
    Value(TextInputCanvas1.Value),
    Lower(DropdownCanvas1.Selected.Value),
    Lower(DropdownCanvas1_1.Selected.Value),
    DropdownCanvas1_2.Selected.number,
    Value(TextInputCanvas1_5.Value),
    Value(TextInputCanvas1_6.Value),
    If(Toggle1.Checked, 1, 0),
    If(Toggle1_1.Checked, 1, 0),
    If(Toggle1_2.Checked, 1, 0)
  )
);

Power Apps result view

What’s next

In this part, we focused on operationalizing pricing intelligence as a deterministic decision API and integrating it into a Power Apps interface.

In Part 4, we will add a conversational layer on top of this API. The agent will not decide prices — it will only collect missing inputs, call the decision API, and explain the results. This preserves reliability while enabling a ChatGPT-like user experience.

 

Want a tailored pricing strategy for your hotel?
Contact Swell AI Lab to schedule a quick diagnostic.

Share your love
Nuno Nogueira
Nuno Nogueira
Articles: 31

Leave a Reply

Your email address will not be published. Required fields are marked *