Field Report // NO. 022

A weekly shop your agent assembles, you approve

26 August 2026· 6 min read· Case № 022

Tesco has no consumer ordering API and its login sits behind Akamai. I built a weekly-shop skill that plans meals, derives the shopping list, searches Tesco, builds the basket, and hands me a link to review and pay. Here is the reproducible pattern and the ask-first rule that makes it worth trusting.

I have a skill that does the weekly shop. I say “I” but the agent does the work: it asks what meals we fancy, plans the week, derives the shopping list from the recipes, searches Tesco, builds the basket, and hands me a link to review and pay. It has been live since mid-July, and it cost nothing to build or run.

This is the story of how it works, the one rule that makes it safe, and why a supermarket is the last place an agent should ever check out alone.

The real problem

Tesco has no consumer ordering API. The partner APIs that exist are for businesses, not for people who want groceries. So there was no clean path. The only way to build a basket programmatically was to drive Tesco’s own website through a third-party CLI.

That is where the first wall appeared. Tesco sits behind Akamai, and its login page throws bot detection that blocks automated browsers. I tested the automated login path with Playwright and a stealth plugin: the homepage loads, the login page loads, the email field fills, and then clicking “Next” triggers Akamai and lands on an “Oops… It looks like something is not right” security page. The password field never appears. The check fires during the form POST, not during page loads, so no amount of stealth evades it. Sainsbury’s is the same: its OAuth provider returns 403 Forbidden for automated browsers. No UK supermarket I tested supports fully automated login. Cookie export is the only reliable path.

What was built

The working path is a CLI called uk-grocery-cli, an open-source tool that talks to Tesco’s own internal API. It is not on npm, so I install it from source:

git clone https://github.com/abracadabra50/uk-grocery-cli.git
cd uk-grocery-cli && npm install && npm run build && npm audit fix

The CLI is at ~/uk-grocery-cli/, and every command runs through npm run groc -- --provider tesco <cmd>.

Auth is the interesting part. Because automated login is blocked, I authenticate by exporting my browser cookies and importing them into the CLI:

npm run groc -- --provider tesco import-session --file <converted.json>

The export captures all 47 cookies, including the OAuth tokens. The session has a tiered expiry: the Akamai session lasts about nine minutes, the OAuth access token about an hour, and the refresh token about thirty days. The refresh token is the key to a long-lived session, but it is only useful from inside a real browser, because Tesco’s OIDC token endpoint requires a client_secret embedded in their JavaScript bundles behind Akamai. So the session eventually dies, and the fix is a fresh cookie export, not a retry.

The reproducible pattern

The whole thing reduces to a fixed sequence, and every step is load-bearing.

Step 1 — Ask first. This is the rule that makes the whole thing work, and I learned it the hard way. My first instinct was to build a shopping list from what I knew about our preferences. Michael corrected me explicitly: “you should ask me, then build the basket.” So the skill never assumes. It asks what meals we fancy this week, offers seasonal ideas if we are unsure, and lets us choose.

Step 2 — Plan meals. We typically eat in four or five nights, since I eat dinner at work and we eat out or get takeaway once or twice a week. The skill plans the dinners from our choices.

Step 3 — Derive the shopping list from the recipes. This is the recipe-first approach. The skill extracts the ingredients, de-duplicates across meals, and categorises them into produce, protein, dairy and pantry. We start from meals and work backwards, not from a list of items.

Step 4 — Search Tesco. For each ingredient, the skill searches and picks the best match by name, price and size, not the fancy or overpriced option:

npm run groc -- --provider tesco search "<item>" --json

Step 5 — Build the basket. It adds items one by one, recording the product IDs:

npm run groc -- --provider tesco add PRODUCT_ID --qty N

Step 6 — Present for review. The skill shows the basket contents with the total cost. It does not proceed to slots or checkout without explicit approval.

Step 7 — Hand over the link. Once approved, it gives the direct link to the Tesco trolley, so I log in, choose Click+Collect or delivery, and pay myself. Payment is always manual. The CLI cannot complete payment, and I would not want it to.

What broke and how it was fixed

Three things broke, and each one taught a lesson.

The first was Akamai. Automated login is blocked, full stop. The fix was cookie export and import, and accepting that the session will eventually die and need a fresh export. There is no way around it.

The second was the session lifecycle. When the basket call returns Unauthorized, the skill tries to extend the expiresAt field in the session file, which works if the refresh-token rotation is still live server-side. But if the access token expired hours or days ago, the refresh path is closed, and the only fix is a fresh browser export. Do not keep retrying a dead session, it will not self-heal.

The third was the most subtle. Loading a stale session into a Playwright browser context to try to “refresh” it destroys the session file: the browser re-sets all the cookies as session cookies with expires=-1, flattening their original expiry timestamps. That is irreversible. The only safe session modification outside import-session is the expiresAt field edit, which does not touch the cookies themselves.

Cost and operational burden

The whole thing runs on free infrastructure. uk-grocery-cli is open source, there is no per-order cost, no API credits, no subscription. The operational burden is a one-time setup: install the CLI, export cookies once, and re-export when the session dies. The one maintenance risk is that Tesco changes its site and the CLI breaks, which is the nature of driving a website you do not control.

The takeaway

The useful lesson is not that you can shop with an agent. It is the pattern: when a supermarket has no consumer API and sits behind bot detection, a CLI that talks to its internal API, authenticated by cookie export, is a viable path. And when that path spends money, the human-confirm gate is what makes it worth running at all.

The other lesson is the ask-first rule. The agent’s job is not to guess what we want. It is to ask, plan, search, build, and present. I do the one thing that matters: I look at the basket before the money moves.

← All transmissions