← All writing

The machine behind the picks: an agentic system that ran a 39-day tournament

A World Cup is 104 matches over 39 days across three time zones. Each one needs fresh numbers pulled, a pick recomputed, and a scoreline entered before a deadline that doesn't care what else you're doing. Nobody should babysit that by hand, so I built it to run itself — with me pressing only the final button. It's a small, low-stakes system, but it's the clearest example I have of a pattern I keep coming back to at work: automate the grind, keep the judgement human, and be deliberate about which is which.

In my last post I covered the method — pick the scoreline with the highest expected points, every time. This one is about the machine that did it without me watching, and why it's built the way it is.

Five parts, one loop

The system has four moving parts and one human, and each covers a specific weakness in the others:

  • A deterministic Python core — the maths that has to be exactly right, with no AI anywhere near it.
  • An AI agent — the operator that runs the pipeline, recovers when a step breaks, and handles the judgement calls.
  • A Telegram bot — delivers each recommendation and its deadline to my phone, and nags until it's entered.
  • A static site — regenerated from the database after every update, so the current state and the full history are always one build away.
  • Me — I approve the decision and type the scoreline into the app. Accountability stays with a person.

The daily loop is the same six steps every time, most of them untouched by human hands:

1 · Fetch odds market 2 · De-vig fair prob. 3 · EV pick best score 4 · Notify to phone 5 · Enter by hand 6 · Publish static site the one human step
Steps 1–4 and 6 run themselves; step 5 is the human. Blue = data, green = maths, orange = the person.

Deterministic where it has to be exact

The part that computes a pick is plain, boring Python over a local SQLite database — no model, no cleverness, no room for improvisation. It takes the odds, strips the bookmaker's margin to get honest probabilities, walks every possible scoreline, and stores the one with the highest expected points. Same inputs, same answer, every single time. That property matters more than it sounds: when the number that gets entered into a live competition is wrong, it needs to be wrong in a way I can reproduce and trace, not a way that depends on how a model felt that morning.

I stored the work in three layers, the same shape I'd use for any real data pipeline: the raw odds exactly as fetched, the calculation done for that fetch, and the current best pick that the site reads. Nothing is overwritten. If a pick changed between two runs, the system flagged it as drift so I could look before trusting it. This is unglamorous plumbing, and it's the plumbing that makes the output trustworthy — the same reason I care about lineage and versioning in a governed warehouse far more than about any single clever query.

The maths never hallucinates, the agent never sleeps, and the human never misses a deadline. The whole design is just making sure each part only does the job it's actually good at.

The agent for judgement, not arithmetic

The operator was an AI agent — in practice, Claude driving the whole pipeline. Day to day it watched the calendar, refreshed the numbers, recomputed the picks, rebuilt the site, and raised a single alert only when something genuinely needed me. When a fetch failed at 3am because a page had changed or a session had gone stale, it diagnosed and recovered on its own instead of waiting for a human to wake up. That reliability layer is most of what "agentic" buys you in practice — not magic, just a tireless operator that handles the exceptions.

The more interesting work was the judgement it did that isn't arithmetic. The knockout rounds are scored on the result after extra time, which behaves differently from ninety minutes, so the model needed a correction. Rather than hand-wave it, the agent went and researched how extra time actually changes a scoreline across decades of past knockout matches, fitted the adjustment from that data, and folded it into the model — the kind of focused analysis that would have cost me a full day. I kept the accountability: I reviewed the change before it shipped. But the legwork, the part that's real work and not a decision, was done while I did something else.

The division of labour I actually use Deterministic code for the judgement-free work, an agent for the judgement calls and the exception-handling, and a human for the last mile and the accountability. Most failed "AI automation" I see gets this backwards — it lets the model do the arithmetic it can get subtly wrong, and makes a person babysit the loop the machine could run perfectly. Put each where its strengths are and the thing quietly runs itself.

The boring reliability that actually decided it

The design that wins a 39-day competition is mostly about not dropping the ball, and that lives in the unglamorous corners:

  • Getting the data at all. The odds source hard-blocks automated traffic, so the fetch egresses through a residential proxy and banks the right browser cookie, so an ordinary-looking request comes back with clean numbers instead of a block page.
  • Never missing a submission. The single most expensive mistake in a game like this is forgetting to enter a pick. The bot nagging me until a scoreline was in beat any amount of model cleverness.
  • Trust, but verify. A pick isn't done when it's computed — it's done when it's entered and confirmed. Every submission was recorded against a screenshot of the app, so "what the model said" and "what I actually entered" could never silently drift apart.
  • One alert, not a firehose. The bot stayed quiet unless something needed attention, then sent one consolidated message. A monitor that cries wolf gets muted, and a muted monitor is worse than none.

Why this is the same as real data work

I built the football system partly because it's a low-stakes place to practise a discipline I take seriously at work. Strip away the sport and it's the same architecture as a production data platform: a governed source of truth, a deterministic transformation layer you can trust and audit, automation that handles the recurring load, monitoring that speaks up only when it should, and a human accountable for the decisions that matter. The World Cup version just had a hard deadline every few hours and a scoreboard that graded me in public, which is a good forcing function for getting the plumbing right.

It also lands the honest limit of the whole thing. The one ingredient the system didn't produce was the probability estimate itself — that came from the market it read. Everything downstream of that number was mine: the arithmetic, the automation, the reliability, the judgement about extra time. The lesson I keep taking back to real projects is that the durable value usually isn't the model in the middle. It's the boring, trustworthy machinery around it that turns a good estimate into a decision that ships on time, every time.

The system ran all 104 matches and the entry finished first in its pool and inside the global top 0.6%. The finished result — every pick against every actual score — is public at wc26.devapp24.com.

Oleksandr Tverdokhlieb
Oleksandr Tverdokhlieb
Data Analytics Manager · Dubai — building data platforms, automation and applied AI.
More writing → The method behind it Connect on LinkedIn ↗