One AI agent, ten public datasets: what it found

Worked examples on public, open datasets. No client or private data. This is the shareable version of the kind of analysis I run privately on real business data.

I’ve been building a data agent that does the boring-but-hard part of analysis on its own: it loads a table, profiles every column, tests which relationships are real, models the outcome you care about, and then, the part that actually matters, turns all of that into a few sentences a decision-maker can act on. One question in, one clear answer out.

The short version

  • One pipeline, ten datasets, no tuning. Load → profile → test → model → explain, run unchanged on restaurants, shipwrecks, houses, diamonds, penguins, wine, cars, biopsies, air quality and the US economy.
  • The honest answer is usually simpler than the expected one. Check size decides the tip. Location and income decide the house price. Carat decides the diamond.
  • Knowing when to stop is a feature. On a 32-row table the agent refuses to ship a predictive model rather than reporting a flattering score (§7).
  • Every dataset below is public and linked, so you can re-run any of it yourself.

To show what that looks like, I ran the same pipeline, unchanged across ten well-known public datasets: restaurants, real estate, cars, wine, biology, the economy. Each section below has two parts: the business read (what it means and what to do about it) and, folded underneath, the technical report (every algorithm it ran, the tests it chose, and the scores) for anyone who wants to check its work. The point is not any single finding. It is that the same machine gets to a usable answer on wildly different data.

1. Restaurant tipping: what actually decides the tip

The size of the check decides the tip, and almost nothing else does. Party size nudges it slightly; day of week, shift, smoking and the diner’s gender make no practical difference. To grow tips, grow the check.

Dataset: tips (seaborn, from Bryant & Smith, 1995, 244 checks.

Automated analysis · restaurant tipping

What actually decides how much a table tips

244 dinner & lunch checks · one table · analysed end-to-end by the agent

Bottom line: The size of the check explains the tip almost entirely. Party size nudges it a little; the day of week, the shift, whether guests smoked, and the diner's gender make almost no practical difference. If you want tips to grow, grow the check, not the schedule.
What moves the tip
Check size86%
Party size6%
Day of week5%
Smoker at table2%
Guest gender<1%
Lunch vs dinner~0%
The numbers behind it
$19.79
Average check
$3.00
Average tip
~15%
Effective tip rate
±$0.73
Tip predictable from the bill within this
What this means for the floor
  • Sell the check, not the shift. Tables above ~$34 tip about $5; tables under ~$11 tip under $2. A single upsell, a starter, a second round or dessert, is worth more to tip income than any night of the week.
  • Don't chase "good tables." The instinct that certain guests tip better (by gender, by shift, by smoker status) does not hold up in the data. Those signals are real but tiny. Coaching servers on them wastes attention.
  • Bigger parties help mostly because they spend more. Party size matters, but largely as a proxy for check size, so it is not a separate lever.
Produced automatically by an AI data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset; no private data.
See the technical report: every algorithm, test and score
Technical report · Restaurant tipping

How the agent analysed tips

244 rows · 8 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 7 columns over 244 rows
  2. Association matrix: association_matrix: Pairwise association across 7 columns
  3. Model evaluation: regression_metrics: R²=0.523, RMSE=0.957
  4. Feature importance: permutation_importance: Top feature: total_bill
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'tip': 'total_bill' (tree R²=0.46)
Association tests (dtype-routed)
ColumnsTest chosenResult
tip~total_billspearmanstrong positive correlation (r=0.679, p=2.5e-34)
tip~sizekruskal_wallissignificant difference in tip across size (6 groups, epsilon_squared=0.231, p=8.04e-11)
tip~daykruskal_wallissignificant difference in tip across day (4 groups, epsilon_squared=0.035, p=0.0357)
Model performance

Task: regression · backend: gbt · held-out test rows: 61

0.523
RMSE0.957
MAE0.729
Feature importance: permutation_importance
FeatureScoreShare
total_bill0.85886%
size0.0646%
day0.0515%
smoker0.0152%
sex0.004270%
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

The folklore of the “good table” mostly evaporates: the lever is check size, not the night or the shift.


2. Titanic: what decided who survived

Sex decided who survived the Titanic, and ticket class decided the rest. Being female moved the odds more than any other variable; travelling first class helped on top of that. Age barely mattered once those two were known.

Dataset: Titanic passenger list (OpenML, 891 passengers.

Automated analysis · Titanic survival

Who survived the Titanic, and what actually decided it

1,309 passengers · one table · classified end-to-end by the agent

Bottom line: Survival wasn't random. Two things decided it: sex first, then the class of ticket. Being female moved the odds more than anything else; travelling first class helped on top of that. Age barely mattered once those two were known.
What decided survival
Sex68%
Passenger class27%
Age5%
The numbers behind it
77%
Survival correctly predicted from 3 facts
Sex
Strongest single factor
0.81
Model's ability to rank risk (AUC, 1.0 = perfect)
3
Factors that mattered
What to do with it
  • The headline generalises: when a crisis is governed by a rule (“women and children first”), the data recovers that rule cleanly, with no need for the backstory.
  • Class was a real, separate advantage, not just a proxy for sex. First-class passengers fared better within each group.
  • Age added almost nothing once sex and class were known, a reminder that more columns are not more insight.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · Titanic survival

How the agent analysed titanic

1309 rows · 7 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 4 columns over 1309 rows
  2. Association matrix: association_matrix: Pairwise association across 4 columns
  3. Model evaluation: classification_metrics: accuracy=0.771, f1=0.761
  4. Feature importance: permutation_importance: Top feature: sex
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'survived': 'sex' (tree accuracy=0.79)
Association tests (dtype-routed)
ColumnsTest chosenResult
survived~sexchi_squaresignificant association between survived and sex (Cramér's V=0.527, p=4.59e-81)
survived~passengerClasschi_squaresignificant association between survived and passengerClass (Cramér's V=0.313, p=1.72e-28)
Model performance

Task: classification · backend: gbt · held-out test rows: 328

Accuracy0.771
Precision0.773
Recall0.771
F10.761
ROC-AUC0.812

Confusion matrix (rows = actual, cols = predicted)

18419
5669
Feature importance: permutation_importance
FeatureScoreShare
sex0.16266%
passengerClass0.07631%
age0.007933%
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

A crisis governed by a rule leaves a clean signature in the data; you don’t need the story to recover “women and children first.”


3. California housing: what sets a home’s price

Where a California home sits and how wealthy its neighbourhood is set almost the whole price. Latitude, longitude and median income together explain the vast majority of the variation. The age of the house barely registers.

Dataset: California Housing (scikit-learn, 1990 US Census, 20,640 block groups.

Automated analysis · California housing

What really sets a California home's price

20,640 neighbourhood blocks · one table · modelled end-to-end by the agent

Bottom line: Two forces set the price: where the home is (latitude + longitude) and how wealthy the neighbourhood is. Together they explain the vast majority of the variation. How old the house is barely registers.
What sets the price
Location (lat/long)66%
Neighbourhood income23%
Crowding / occupancy7%
Rooms & house age4%
The numbers behind it
83%
Of price variation explained
Location
Biggest lever, combined
Income
Strongest single factor
~0%
Effect of house age
What to do with it
  • Location and income are the whole game. For pricing, valuation, or where-to-build decisions, these two beat every property-level detail combined.
  • Stop over-weighting house features. Age, room counts, and bedroom ratios move price only at the margin, useful for fine-tuning and useless as headline drivers.
  • The model is trustworthy here (it explains 83% of prices on data it never saw), so it's a fair basis for automated valuation.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · California housing

How the agent analysed california_housing

20640 rows · 7 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 9 columns over 20640 rows
  2. Association matrix: association_matrix: Pairwise association across 9 columns
  3. Model evaluation: regression_metrics: R²=0.835, RMSE=0.467
  4. Feature importance: permutation_importance: Top feature: Latitude
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'MedHouseVal': 'MedInc' (tree R²=0.53)
Association tests (dtype-routed)
ColumnsTest chosenResult
MedHouseVal~MedIncspearmanstrong positive correlation (r=0.677, p=0)
MedHouseVal~HouseAgespearmannegligible positive correlation (r=0.075, p=4.84e-27)
Model performance

Task: regression · backend: gbt · held-out test rows: 5160

0.835
RMSE0.467
MAE0.313
Feature importance: permutation_importance
FeatureScoreShare
Latitude0.83237%
Longitude0.6629%
MedInc0.5323%
AveOccup0.157%
AveRooms0.0452%
HouseAge0.042%
Population0.008860%
AveBedrms0.006580%
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

Location and neighbourhood income are the whole game; property details move price only at the margin.


4. Diamonds: what a price is made of

A diamond’s price is mostly its size. Carat weight and physical dimensions carry it; clarity and colour fine-tune it; cut grade barely moves it at all. The agent predicts price to within a few hundred dollars.

Dataset: diamonds (ggplot2, 53,940 stones.

Automated analysis · Diamond pricing

What a diamond's price is really made of

53,940 diamonds · one table · modelled end-to-end by the agent

Bottom line: Price is almost entirely about size: carat weight and physical dimensions. Clarity and colour fine-tune it; cut grade barely moves the price at all. The agent predicts price within a few hundred dollars.
What makes the price
Size (carat & dimensions)75%
Clarity11%
Colour6%
Cut grade<1%
The numbers behind it
98%
Of price variation explained
±$287
Typical prediction error
Carat
Dominant driver
Cut
Almost no price effect
What to do with it
  • Price by weight first. For inventory, appraisal, or buy/sell decisions, size is the anchor and everything else is a modest adjustment.
  • Cut is oversold as a price driver. It matters for beauty, but the market barely pays for it, which is worth knowing when negotiating.
  • Automated pricing is viable: the agent explains 98% of price on unseen stones, tight enough to flag mispriced listings.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · Diamond pricing

How the agent analysed diamonds

53940 rows · 8 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 10 columns over 53940 rows
  2. Association matrix: association_matrix: Pairwise association across 10 columns
  3. Model evaluation: regression_metrics: R²=0.980, RMSE=560
  4. Feature importance: permutation_importance: Top feature: carat
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'price': 'carat' (tree R²=0.88)
Association tests (dtype-routed)
ColumnsTest chosenResult
price~caratspearmanvery strong positive correlation (r=0.963, p=0)
price~cutkruskal_wallissignificant difference in price across cut (5 groups, epsilon_squared=0.018, p=1.53e-210)
price~claritykruskal_wallissignificant difference in price across clarity (8 groups, epsilon_squared=0.050, p=0)
Model performance

Task: regression · backend: gbt · held-out test rows: 13485

0.98
RMSE560.208
MAE287.4
Feature importance: permutation_importance
FeatureScoreShare
carat0.64747%
y0.46834%
clarity0.15611%
color0.0876%
z0.0171%
x0.005570%
cut0.002480%
depth0.001190%
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

Size dominates; clarity and colour fine-tune; cut grade, the thing shoppers obsess over, barely moves the price.


5. Penguins: identifying species from a ruler

A handful of ruler measurements and the island a bird was seen on identify three penguin species almost perfectly. The agent labels them correctly 98% of the time.

Dataset: palmerpenguins (Horst, Hill & Gorman, 344 birds.

Automated analysis · Penguin species

Telling three penguin species apart from a few measurements

344 penguins · one table · classified end-to-end by the agent

Bottom line: Three species can be identified almost perfectly from a handful of body measurements plus which island a bird was seen on. The agent labels species correctly 98% of the time.
What identifies the species
Which island45%
Bill length35%
Flipper length11%
Bill depth8%
The numbers behind it
98%
Correctly identified
3
Species separated
2–3
Measurements needed
2
Natural groups found unsupervised
What to do with it
  • Cheap measurements beat expensive ones. A ruler and a location note classify a bird as well as any lab work, the practical lesson for any “which type is this?” problem.
  • Location carries real signal. Where something is observed is a feature, not just metadata.
  • The pattern is genuine, not imposed: left to find groups on its own, the agent recovered clean clusters that track the species.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · Penguin species

How the agent analysed penguins

344 rows · 7 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 8 columns over 344 rows
  2. Association matrix: association_matrix: Pairwise association across 8 columns
  3. Model evaluation: classification_metrics: accuracy=0.977, f1=0.977
  4. Feature importance: permutation_importance: Top feature: island
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'species': 'flipper_length_mm' (tree accuracy=0.95)
  6. Clustering: kmeans: 2 clusters, silhouette=0.417
  7. Cluster profiling: profile_clusters: Characterised 2 clusters
Model performance

Task: classification · backend: gbt · held-out test rows: 86

Accuracy0.977
Precision0.978
Recall0.977
F10.977
ROC-AUC1

Confusion matrix (rows = actual, cols = predicted)

3800
1160
1030
Feature importance: permutation_importance
FeatureScoreShare
island0.22145%
bill_length_mm0.17235%
flipper_length_mm0.05311%
bill_depth_mm0.0418%
Unsupervised clustering

2 clusters, silhouette=0.417, method kmeans. k chosen automatically by silhouette score.

Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

Cheap measurements beat expensive ones: a few body measures and a location note classify a bird 98% of the time.


6. Wine: separating varieties by chemistry

Three grape varieties separate perfectly on chemistry alone, with zero misclassifications. A handful of compounds (flavanoids, proline, colour intensity) do all the work.

Dataset: Wine recognition (scikit-learn, UCI, 178 wines.

Automated analysis · Wine cultivars

Separating three wine varieties by chemistry alone

178 wines · one table · classified end-to-end by the agent

Bottom line: Three grape varieties are perfectly separable from their chemistry, with zero mistakes. A few compounds (flavanoids, proline, colour intensity) do all the work.
What tells the varieties apart
Flavanoids39%
Proline29%
Colour intensity22%
Alcohol & hue7%
The numbers behind it
100%
Correctly classified
0
Errors on unseen wines
3
Markers carry the signal
3
Natural groups found unsupervised
What to do with it
  • A short test panel is enough. You do not need to measure everything. Three compounds authenticate variety with no errors.
  • Strong fit for QA and authenticity checks: a fast chemical signature that flags a mislabelled or off-spec batch.
  • The chemistry is genuinely distinct: unsupervised clustering found the same three groups without being told they exist.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · Wine cultivars

How the agent analysed wine

178 rows · 7 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 14 columns over 178 rows
  2. Association matrix: association_matrix: Pairwise association across 14 columns
  3. Model evaluation: classification_metrics: accuracy=1.000, f1=1.000
  4. Feature importance: permutation_importance: Top feature: flavanoids
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'wine_class': 'proline' (tree accuracy=0.93)
  6. Clustering: kmeans: 3 clusters, silhouette=0.311
  7. Cluster profiling: profile_clusters: Characterised 3 clusters
Model performance

Task: classification · backend: gbt · held-out test rows: 45

Accuracy1
Precision1
Recall1
F11
ROC-AUC1

Confusion matrix (rows = actual, cols = predicted)

1500
0180
0012
Feature importance: permutation_importance
FeatureScoreShare
flavanoids0.26239%
proline0.19829%
color_intensity0.15122%
alcohol0.0244%
hue0.023%
malic_acid0.0112%
magnesium0.0112%
Unsupervised clustering

3 clusters, silhouette=0.311, method kmeans. k chosen automatically by silhouette score.

Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

Three compounds tell three grape varieties apart with zero errors, so a short test panel is enough.


7. Cars, and knowing when NOT to trust a model

Weight and engine power drive fuel economy, and 32 cars is too little data to predict it. The relationships are strong and clear. The agent says so, then refuses to ship a model it cannot stand behind.

Dataset: mtcars (R datasets, Motor Trend 1974, 32 cars.

Automated analysis · Car fuel economy

What drives fuel economy, and why the agent won't overclaim on 32 cars

32 cars · one table · analysed end-to-end by the agent

Bottom line: Weight and engine power drive fuel economy: heavier, more powerful cars burn more. The relationships are strong and clear. But with only 32 cars, the agent flags that there's too little data to build a trustworthy predictive model rather than pretending otherwise.
What relates to MPG (correlation strength)
Engine power (hp)very strong
Weightvery strong
Cylindersstrong
Rear-axle ratiomoderate
The numbers behind it
32
Cars, a small sample
Weight + power
The real levers
Honest
Model flagged as unreliable
r ≈ 0.9
Strength of the top relationships
What to do with it
  • The levers are real: to improve fuel economy, cut weight and power. The data is unambiguous on direction.
  • The restraint is the point. Most tools would still hand you a confident prediction; this one tells you 32 rows can't support one. Knowing when not to trust a model is worth more than a false number.
  • Next step if it mattered: gather more vehicles before relying on a predictive model. The relationships suggest it would pay off.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · Car fuel economy

How the agent analysed mtcars

32 rows · 8 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 11 columns over 32 rows
  2. Association matrix: association_matrix: Pairwise association across 11 columns
  3. Model evaluation: regression_metrics: R²=-0.619, RMSE=5.83
  4. Feature importance: permutation_importance: Top feature: disp
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'mpg': 'wt' (tree R²=0.96)
Association tests (dtype-routed)
ColumnsTest chosenResult
mpg~wtpearsonvery strong negative correlation (r=-0.868, p=1.29e-10)
mpg~hpspearmanvery strong negative correlation (r=-0.895, p=5.09e-12)
mpg~cylkruskal_wallissignificant difference in mpg across cyl (3 groups, epsilon_squared=0.831, p=2.57e-06)
Model performance

Task: regression · backend: gbt · held-out test rows: 8

-0.619
RMSE5.83
MAE5.308
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

The levers (weight, power) are obvious, but the agent refuses to build a confident model on 32 rows. The restraint is the feature.


8. Breast-cancer biopsies: flagging malignancy

Cell size and shape separate malignant from benign biopsies with about 98% accuracy. The strongest signals are the worst-case irregularities in a sample: the most abnormal cells give it away.

Dataset: Breast Cancer Wisconsin (Diagnostic) (scikit-learn, UCI, 569 biopsies.

Automated analysis · Breast-cancer diagnosis

Flagging malignant tumours from cell-shape measurements

569 biopsies · one table · classified end-to-end by the agent

Bottom line: From measurements of cell size and shape, the agent separates malignant from benign tumours with about 98% accuracy. The strongest signals are the worst-case irregularities in a sample. The most abnormal cells give it away.
What flags a malignant tumour
Worst concave points17%
Worst texture14%
Worst perimeter14%
Size variation (area error)9%
The numbers behind it
98%
Overall accuracy
51 / 53
Malignant cases caught
1
False alarm out of 90 benign
0.99
Risk-ranking quality (AUC)
What to do with it
  • Strong decision-support, not a replacement. Catching 51 of 53 malignant cases makes this a serious triage aid, and the 2 misses are why a clinician stays in the loop.
  • Irregularity is the tell. The “worst” (most extreme) measurements in a sample carry more signal than the averages, so focus attention there.
  • Consistent and auditable: the same sample always yields the same call, with the reasoning inspectable, which matters in a clinical setting.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · Breast-cancer diagnosis

How the agent analysed breast_cancer

569 rows · 5 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 31 columns over 569 rows
  2. Association matrix: association_matrix: Pairwise association across 31 columns
  3. Model evaluation: classification_metrics: accuracy=0.979, f1=0.979
  4. Feature importance: permutation_importance: Top feature: worst concave points
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'diagnosis': 'worst radius' (tree accuracy=0.94)
Model performance

Task: classification · backend: gbt · held-out test rows: 143

Accuracy0.979
Precision0.979
Recall0.979
F10.979
ROC-AUC0.993

Confusion matrix (rows = actual, cols = predicted)

891
251
Feature importance: permutation_importance
FeatureScoreShare
worst concave points0.03317%
worst texture0.02714%
worst perimeter0.02714%
area error0.0189%
worst area0.0179%
mean texture0.0126%
mean concave points0.0126%
mean area0.008394%
worst concavity0.007694%
symmetry error0.006994%
worst smoothness0.005593%
perimeter error0.00493%
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

About 98% accuracy from cell-shape measurements: strong decision-support, with the misses that keep a clinician in the loop.


9. Air quality: seeing bad-air days coming

Ground-level ozone is a weather story: it climbs with heat and sunlight and falls with wind. Temperature is the single biggest driver, and the agent predicts ozone from weather alone with about 79% accuracy.

Dataset: airquality (R datasets, New York, May–Sep 1973, 153 days.

Automated analysis · Urban air quality

What drives ground-level ozone, and how to see bad-air days coming

153 days · one table · modelled end-to-end by the agent

Bottom line: Ground-level ozone is mostly a weather story: it climbs with heat and sunlight and falls when it's windy. Temperature is the single biggest driver. The agent predicts ozone from the weather with about 79% accuracy.
What drives ozone
Temperature54%
Wind26%
Sunlight (solar)11%
Time of month9%
The numbers behind it
79%
Of ozone variation explained
Heat
Biggest driver
Wind
Biggest reliever
Hot + still + sunny
The high-ozone recipe
What to do with it
  • Bad-air days are forecastable. Hot, calm, sunny conditions are the recipe, a simple early-warning trigger for public-health alerts.
  • Wind is the natural cleaner. Still air is when ozone accumulates; factor that into when to schedule sensitive activity.
  • Weather explains most of it (79%). The rest points to sources worth investigating beyond the weather.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · Urban air quality

How the agent analysed airquality

153 rows · 8 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 6 columns over 153 rows
  2. Association matrix: association_matrix: Pairwise association across 6 columns
  3. Model evaluation: regression_metrics: R²=0.794, RMSE=14.7
  4. Feature importance: permutation_importance: Top feature: Temp
  5. Key-driver tree: decision_tree_key_drivers: Top driver of 'Ozone': 'Temp' (tree R²=0.73)
Association tests (dtype-routed)
ColumnsTest chosenResult
Ozone~Tempspearmanvery strong positive correlation (r=0.774, p=2.25e-24)
Ozone~Windspearmanstrong negative correlation (r=-0.590, p=3.13e-12)
Ozone~Solar.Rspearmanmoderate positive correlation (r=0.348, p=0.000181)
Model performance

Task: regression · backend: gbt · held-out test rows: 29

0.794
RMSE14.67
MAE10.878
Feature importance: permutation_importance
FeatureScoreShare
Temp0.57754%
Wind0.27826%
Solar.R0.11511%
Day0.0697%
Month0.0232%
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

Ground-level ozone is mostly a weather story: hot, still and sunny is the high-ozone recipe.


10. The US economy: 48 years of unemployment

US unemployment moves in regimes, not a smooth drift. Across 48 years the agent found 11 sharp structural breaks. They land on the known recessions: 1975, 1982, 1990, 2001, 2008. The series rose 34% across the span, and the near-term forecast points down.

Dataset: economics (ggplot2, from FRED UNRATE, 574 monthly readings, 1967–2015.

Automated analysis · US economy

48 years of US unemployment: the shifts that actually matter

574 monthly readings, 1967–2015 · one table · time-series analysis by the agent

Bottom line: Over five decades, unemployment did not drift smoothly. It moved in regimes, with 11 sharp structural breaks that line up with known recessions (1975, 1982, 1990, 2001, 2008…). Across the span it rose about 34%, and the near-term forecast points modestly down.
What the series shows
Long-run rise across the period+34%
Structural breaks detected11
Seasonal swing within each yearyearly
Near-term directiondown
The numbers behind it
+34%
Rise across the period
11
Structural breaks (regime shifts)
2008
Largest recent break
Down
Direction of the 12-month forecast
What to do with it
  • Plan around regimes, not averages. A single long-run average hides the breaks; the useful unit is the period between shocks, and the agent finds those boundaries automatically.
  • The breaks aren't noise. They map onto real recessions, which is a good sanity check that the method is finding structure, not artefacts.
  • Forecasts come with honest error bands. The near-term call is a modest decline, but the widening range is the point: it says how much to trust it.
Produced automatically by the data agent: the table was loaded, profiled, tested for associations, and modelled, then the drivers were ranked and translated into plain language. The same pipeline ran unchanged on every dataset. Public open dataset.
See the technical report: every algorithm, test and score
Technical report · US economy

How the agent analysed economics

574 rows · 6 operations run · deterministic pipeline

Pipeline executed
  1. Profile: profile: Profiled 6 columns over 574 rows
  2. Association matrix: association_matrix: Pairwise association across 5 columns
  3. Seasonal decomposition: seasonal_decompose: Decomposed unemploy (additive, period=12)
  4. Forecast: arima: 12-step forecast of unemploy (ARIMA(1, 1, 1))
  5. Change-point detection: ruptures_pelt_rbf: 11 changepoint(s) in unemploy; first at 1970-06-01T00:00:00
  6. Period comparison: two_window_comparison: unemploy up +33.9% across the split (significant, p=1.77e-21)
Every step above is chosen by transparent rules (statistical test picked from column dtypes; k picked by silhouette; model held out a proper test split). Re-running on the same table yields the same output. Public open dataset.

The series moves in regimes, not a smooth drift; the agent finds the 11 breaks, and they line up with real recessions.


That’s the through-line across all ten: the honest answer is usually simpler than the one people expect, it points at a decision you can act on, and when the data cannot support a claim the agent says so instead of inventing one. The value is not a cleverer model. It is getting to that one sentence fast, on any table you hand it.

Sources and further reading

Every dataset above is public, and each section links its source. The tooling underneath:

PieceWhat it doesSource
scikit-learnModels, held-out splits, scoringscikit-learn.org
statsmodelsStatistical tests, ARIMA, seasonal decompositionstatsmodels.org
rupturesChange-point (structural break) detectioncentre-borelli.github.io/ruptures-docs
Model Context ProtocolHow the agent reaches the analysis toolsmodelcontextprotocol.io

Anthropic’s Building effective agents draws the line I use. A workflow orchestrates tools through predefined code paths; an agent directs its own. The pipeline above is deliberately the first kind. When someone is going to act on the answer, reproducible beats clever.

I’m a data scientist. If you’ve got a pile of data and a decision hiding in it, get in touch.

← All posts