This tutorial walks you through building a forecasting workflow that runs entirely inside TagoIO, pointed at your own device data. You pick a variable you want to forecast and a few variables that influence it, train a linear-regression model on your device’s history, run inference in a separate Analysis to predict the hours ahead, and build a dashboard that charts the model’s predictions against the real values alongside accuracy metrics.
No machine-learning background is needed. Every term is introduced the first time it shows up. No local Python install is needed either: the runtime lives in TagoIO.
By the end you will have a dashboard with four stat cards (mean absolute error, root mean squared error, model artifact size, and forecast horizon) above a line chart that plots actual values against the model’s predictions.
The example in this tutorial forecasts an HVAC unit’s power draw from its outside temperature, setpoint, and compressor status, and its numbers (an MAE of 0.353 kW, for instance) reflect that specific data. Yours will be different. The model adapts to whatever device and variables you point it at, and the accuracy depends on your data, so treat the example numbers as the shape of a result, not a target to hit.
Contents
- What you’ll build
- Prerequisites
- Step 1: Choose your target and feature variables
- Step 2: Create the analytics device
- Step 3: Create the access policy
- Step 4: Install and configure the training Analysis
- Step 5: Install and configure the inference Analysis
- Step 6: Build the dashboard
- Step 7: Schedule the Analyses (optional)
- What’s next
- Appendix: the two scripts
If you already know TagoIO and just want the moving parts: variable selection and the case-sensitivity rule are in Step 1, the IAM scopes are in Step 3, the environment-variable tables are under each Analysis in Steps 4 and 5, and the dashboard widget config is in Step 6.
What you’ll build
Two Python Analyses, each with one job:
- Training Analysis. Reads your device’s history, fits a linear regression for the variable you chose, and saves the model as a small JSON file to TagoIO Files. With backtest mode on, it also tests itself against the most recent 10 days and writes out accuracy numbers and an actual-vs-forecast comparison.
- Inference Analysis. Loads that JSON model in a separate run and predicts the next 24 hours.
Both Analyses are variable-agnostic. The defaults forecast HVAC power, but you point them at any numeric variable on any device by changing two environment variables.
Prerequisites
- A TagoIO account with profile-level access (you’ll create one device, install two Analyses, and create an access policy).
- Comfort navigating the TagoIO console. You’ve used the Devices and Analysis modules before.
- A device with at least ~80 days of numeric time-series data. The model needs history to learn from.
- A target variable you want to forecast (for example
power_kw,motor_current,flow_rate). - A few exogenous variables — inputs that influence the target but aren’t the target itself. More on choosing these in Step 1.
- No Python installation. The
python-rt2025runtime runs the code inside TagoIO, and the Analyses ship ready to run. - No machine-learning background. We introduce each term the first time it shows up.
Step 1: Choose your target and feature variables
This decision shapes everything downstream, so spend a minute here.
Your target is the variable you want to forecast. Pick one numeric variable that changes over time in a pattern worth predicting.
Your features are the exogenous variables. Exogenous just means “comes from outside the thing you’re predicting.” They’re inputs that influence the target but aren’t the target itself. For HVAC power, the features are outside temperature, the thermostat setpoint, and whether the compressor is running. All of them push power up or down; none of them is power.
When picking features for your own data:
- Prefer variables with a believable causal link to the target. A motor’s current might be driven by load and ambient temperature; a pump’s flow by pressure and valve position.
- Pick three to six. Too few and the model has little to work with; too many and you need more history to fit them reliably.
Find the exact names. Open your device’s Data tab and look at the Variable column. Variable names are case-sensitive. Copy-paste them from that column rather than typing. The preflight check will catch mismatches, but copying saves the round trip.
A short guide to choosing features:
- Prefer variables with a believable physical or causal link to the target. A feature that correlates by coincidence will help on your training window and then let you down.
- Three to six features is a sensible range. The script needs roughly 10 aggregated rows of history per feature, so more features need more data.
- You do not need a time variable. The script adds time-of-day and day-of-week features for you, so leave the clock out of your feature list.
Once you have your target name and your feature names written down, you are ready to set up the rest.
Step 2: Create the analytics device
You already have the device with your source data. You need one more, to hold the model’s output separately from your raw telemetry.
Create it under Devices → Add Device (blank/custom device).
| Role | Suggested name | Device type | What it holds |
|---|---|---|---|
| Analytics | forecast_analytics |
Mutable | Backtest comparison, forecast, and model metadata |
Mutable is the right type here. The analytics device only ever holds a few hundred records, well under the 50,000-record cap that Mutable devices have. (That cap is worth knowing in general: if you ever build a device that ingests tens of thousands of records, choose Immutable instead, since inserts past the cap on a Mutable device fail silently. It won’t bite you here.)
Copy both device IDs now — your source device and this analytics device. The ID is the 24-character hex string in the device URL. You’ll paste both into the Analysis configuration.
Step 3: Create the access policy
Your Analyses talk to the platform using their own token, which TagoIO provides automatically at runtime. That token only works if the policy attached to the Analysis grants the right permissions.
Open Access Management → Profile Policies and create (or edit) a policy with these scopes:
| Scope | Why it’s needed |
|---|---|
| Device / Access | Access to your source device |
| Device / Get Device Data | Read telemetry from your source device |
| Device / Edit Device Data | Write backtest and forecast records to the analytics device |
| File / Access | List and download the model artifact |
| File / Upload | Save the model artifact |
| Account / Access Profile | The inference Analysis needs the profile ID to build the file download URL |
One detail that trips up people new to TagoIO: you don’t attach a policy by selecting it on the Analysis. It works the other way around. In the policy’s Targets, you list the Analysis by ID or match it by tag. If an Analysis logs Authorization Denied, a missing scope or a missing target is almost always the cause.
Step 4: Install and configure the training Analysis
Install the training Analysis from this template link. Open it in your browser and TagoIO will prompt you to install it into your profile. It arrives with the code in place and the environment variables already defined.
Once it’s installed, open the Analysis and fill in the environment-variable values. Most come prefilled with defaults. The ones you must set are the device IDs and your variable names:
| Key | Value | Notes |
|---|---|---|
TARGET_DEVICE_ID |
(your source device ID) | Required. No default |
ANALYTICS_DEVICE_ID |
(your analytics device ID) | Required. Where backtest output is written |
TARGET_VARIABLE |
(your target, e.g. power_kw) |
Case-sensitive. Must match the Variable column exactly |
FEATURE_VARIABLES |
(comma-separated, e.g. outside_temperature,setpoint,compressor_status) |
Case-sensitive, no spaces around commas |
TRAINING_DAYS |
80 |
Prefilled. Days of history used to fit the model |
BACKTEST_DAYS |
10 |
Prefilled. Holds out the most recent 10 days to test accuracy |
TARGET_VARIABLE and FEATURE_VARIABLES arrive with the HVAC defaults. Change them to your variables unless you’re forecasting HVAC power on a device that uses those exact names. TARGET_DEVICE_ID and ANALYTICS_DEVICE_ID come blank, so set them before your first run.
A couple of terms, introduced as you meet them:
- Linear regression fits a straight-line relationship: it learns a weight for each input and adds them up to predict the output. Simple, fast, and a reasonable fit for steady patterns.
- Backtest means training on older data, then testing on a slice the model never saw. With
BACKTEST_DAYS=10, the Analysis trains on the older history and checks itself against the most recent 10 days. The model never gets to peek at the answers.
Run it. This run takes about 35 seconds. Expect logs like this (with your variable names in place of the HVAC ones):
forecasting-train: starting
config: model=hvac_energy_baseline v1
artifact: ml/model.json
target: 'power_kw'
features: [outside_temperature,setpoint,compressor_status]
training_days: 80
aggregation_min: 60
training_end: 2026-05-31T16:00:00+00:00
backtest_days: 10
preflight: variable names verified against device
train: fetched ... rows in ...ms
train: ... raw points → 1711 aggregated points at 60min
train: saved artifact to Files: /ml/<model>.json (~786 bytes)
backtest: MAE=0.3532, RMSE=0.7455 over 240 hours
backtest: wrote ... records to <analytics-device>
Two preflight checks protect you here. If a variable name doesn’t match your device, the Analysis stops immediately and names the offender. And if your device doesn’t have enough history for the feature set you chose (roughly 10 aggregated rows per feature), it stops with a clear message rather than training a meaningless model.
Two accuracy numbers come out of the backtest. These are the sample HVAC numbers; yours will reflect your own variable:
- MAE (Mean Absolute Error): 0.353 kW. The average size of the model’s miss, in the target’s units. On a baseline that averages around 4 kW, that’s about 9% off.
- RMSE (Root Mean Squared Error): 0.746 kW. Like MAE, but it punishes big misses more.
Confirm the model landed: open Files, find the artifact path from the logs, and you should see a JSON file around 786 bytes.
The model is plain JSON you can open and read: a handful of coefficients, an intercept, and a residual standard deviation. That keeps it portable across Python and library versions, and it loads without executing any code.
Step 5: Install and configure the inference Analysis
Install the inference Analysis from its template link the same way. Open it in your browser, install it into your profile, and it arrives with its code and environment variables ready.
Open the Analysis and fill in the values:
| Key | Value | Notes |
|---|---|---|
TARGET_DEVICE_ID |
(your source device ID) | Required. Reads the most recent feature values from here |
ANALYTICS_DEVICE_ID |
(your analytics device ID) | Required. Writes the forecast here |
MODEL_ARTIFACT_FILE_PATH |
(path from the training logs) | The JSON file to load |
FORECAST_HORIZON_HOURS |
24 |
Prefilled. Hours ahead to predict |
FORECAST_BATCH_SIZE |
100 |
Prefilled. Records per write batch; the default is fine |
Notice what’s not here: no TARGET_VARIABLE, no FEATURE_VARIABLES. The inference Analysis reads those from the model artifact itself. TagoIO Files is the bridge between training and inference. Training writes the JSON model there, and inference reads it back. The two Analyses share nothing else. So when you retrain with a different target, inference follows automatically.
Run it. This run takes about 7 seconds. Expect:
forecasting-inference: starting
config: artifact=/ml/<model>.json horizon_h=24h
inference: loaded artifact from ml/<model>.json (~756 bytes, version=1)
inference: target='power_kw'
exogenous_features=[outside_temperature, setpoint, compressor_status]
inference: using last-observed exogenous values as constants — outside_temperature=19.2380,
setpoint=21.0000, compressor_status=0.0000
inference: wrote ... records to <analytics_device_id> (... API calls, duration=842ms)
forecasting-inference: finished
summary: target=power_kw forecast_count=24 inference_duration_ms=842 records_written=99
api_read_count=3 api_write_count=1 residual_std=0.4031
Verify it ran from the Analysis log. The forecast is written for future timestamps, and TagoIO’s standard surfaces show data up to the current time, so you won’t see these records in the Data tab yet. Instead, confirm the run from the log: look for the predict: 24 hours of forecast_power_kw written to ... line with a non-zero count. That line confirms the inference ran.
Step 6: Build the dashboard
The dashboard visualizes the backtest — actual versus forecast over the last 10 days. The chart shows what the model would have predicted over that window, next to what actually happened. The forward forecast from inference appears here progressively, one hour at a time, as time catches up to each predicted timestamp.
The backtest is what makes the dashboard visible on day one. The forecast fills in over the following hours.
Create a new dashboard and add two widgets pointed at the analytics device.
Line Chart — actual vs forecast (the backtest)
Add a Line Chart with two series. Substitute your own target name for {target}:
- Series 1:
actual_{target}— for HVAC,actual_power_kw - Series 2:
forecast_{target}— for HVAC,forecast_power_kw
Both series share timestamps across the backtest window, so they overlay on the same axis.
Stat Cards — accuracy at a glance
Add four Stat Card (Display) widgets, one variable each:
model_mae— the sample run shows 0.353 kWmodel_rmse— the sample run shows 0.746 kWmodel_artifact_size_bytes— 786 bytesforecast_horizon_hours— 240 hours
When you’re done, it looks like this:
Your numbers will differ — they depend on your variable and how predictable it is.
Step 7: Schedule the Analyses (optional)
In a real deployment, you would schedule both Analyses with Schedule Actions. Schedule training weekly. Schedule inference hourly.
| Analysis | Suggested cadence |
|---|---|
| Training | Weekly |
| Inference | Hourly |
What’s next
You now have an end-to-end forecasting pipeline in TagoIO: a trained and backtested model, scheduled predictions, and a dashboard comparing predictions against actuals. All of it running on the platform.
A note on seeing your forward forecast. The inference Analysis writes records at future timestamps to the analytics device, and TagoIO’s standard surfaces query data up to the current time. Those records become visible as the clock advances past each timestamp. The forecast isn’t lost or hidden; it’s queued for display. To see the full forecast horizon ahead of time, you’d need a custom widget, which is out of scope here.
If you build this, you can share your dashboard in a reply with your target variable and the MAE you landed. It helps the next person following along.
Appendix: the two Analyses
Both Analyses install from the template links below. Open a link in your browser, and TagoIO will prompt you to install the Analysis into your profile, code and environment variables included. To read or edit the code, open the installed Analysis in the Analysis module.
1. Training — fits the model, saves the JSON artifact, and runs the backtest.
2. Inference — loads the artifact and writes the 24-hour forecast.










