-
-
Qloo's evidence under an idea: favourites, link split, shared tags. Demo data: stand-ins for Qloo and the model; live rows come from Qloo.
-
Saved example: each idea names the favourites behind it. Its taste matches and reasons are stand-ins, not live Qloo or model output.
-
Same AI, favourites only, no Qloo data, asked live. Compared with the saved example's ideas. Partly by design: no favourites as ideas.
-
Same gift as another's, 20 made-up people: Tasteloom 17 of 80; re-run after a fix designed on them: 4 of 80. Models alone: none identical.
-
Checkout: the server sets the price from the saved product cards and refuses a total above the budget. PayPal sandbox, no real money.
-
Friend's page on the live site: three invented favourites typed, then Make my reply link gives a link to send back. No account needed.
Tasteloom in 30 seconds
Try it now: https://tasteloom.kylne700.workers.dev/?images=on (free, no sign-up)
You are buying a gift for someone you know only in fragments: a favourite book, a band, a shop, a place. Tasteloom turns those fragments into gift ideas. Each idea names the favourite behind it (or says "Fits their overall taste" when Qloo links it to none).
- Quick look, about 10 seconds: press Replay the saved example. It plays back a run recorded on Oct 16, 2026 and costs no API calls (10.3 s in our check on Oct 30, 2026); the lookups it lists are recorded, not made now. Its products and prices were live that day; its taste matches and reasons are stand-ins, not live Qloo or model output, and the page says so. It was recorded before the evidence rows described below existed, so it does not show them.
- Live example, 19.3 s in our check on Oct 30, 2026 (one run): press Run a live example, above the form. It fills in five favourites (two books, two artists, one brand) and a budget of $120 picked for this demo, then runs live within the daily limits. The page reported 19.3 s and 20 lookups, and showed 5 ideas: four gifts first, then one experience.
- Your own run: type 3 to 5 things they love and a budget from $10 to $500, then press Find gift ideas. Up to six ideas come back, gifts first, with real products and prices where a shop sells the item.
- Not sure what they love? Ask them, without asking for a gift. A guess can miss, and a wishlist names the gift, so Tasteloom asks for their taste instead. Press Ask them to get one link to send. They open it, name three to five things they love (no account) and press Make my reply link. Their answer travels inside that link, in the part of the address that browsers do not send to a server, so our server does not receive it from them. When you open the reply link here, the form says "Filled from their reply"; only when you press Find gift ideas do those favourites go to our server, like typed ones. Or press Make your own taste link and send it to whoever buys you gifts: they see what you love, not what you will get.
- Each idea shows its evidence (live runs): the favourite Qloo links to it most strongly ("Because they love X"); how Qloo splits its link across the favourites, when two or more of them share it; and the tags Qloo gives to both that favourite and the idea, when there are any (3 of the 5 ideas in our Oct 30 check of the live example). A model-written reason is kept only if it names that favourite and uses one of those shared tags; otherwise the server shows a template sentence built from the same data ("Qloo tags both X and Y as ...", or "Qloo links X to Y." when they share no tag). With no shared tag the model is not asked. If Qloo links the idea to none, the card says "Fits their overall taste" and claims nothing more.
- Pay with test money: PayPal sandbox, as a guest. No real money moves.
- Limits (per UTC day, as deployed on Oct 30, 2026): each visitor can start up to 8 live runs, about 4 of them with shop and web results. The whole demo shares 75 shop searches and 77 web searches; a full run uses 4 to 6 shop and 4 to 5 web searches, so that covers about a dozen full runs. After that, ideas still appear, without buy buttons or place links, and the page says so. Replay the saved example costs no API calls. Compare: same AI, no Qloo (below) is limited to 8 clicks per visitor and 40 in total. Live runs use the hackathon key Qloo gave us, which Qloo's developer guide says stays active through the end of the judging period (Nov 5, 2026, 11:45 pm ET).
The problem
Gifts are a big spend, and a hard one to get right when you know someone only in fragments.
- Spend: the US National Retail Federation's holiday survey (8,247 adults, Oct 1 to 7, 2025, margin of error 1.1 points, run by Prosper Insights & Analytics) forecast $890.49 per person on holiday gifts, food, decorations and other seasonal items, of which $627.93 on gifts for family and friends: a forecast of plans, not a count of purchases. NRF press release, Oct 16, 2025
- Stress (vendor survey): 76% of 2,000 adults said finding the perfect gift is more stressful than asking for a raise or promotion at work (YouGov for the company Mixbook, Oct 8, 2025, margin of error about 3 points). Mixbook report
- Chatbots (vendor survey): 66% of 1,000 US consumers who shopped in the 2025 holiday season said they used an AI chatbot to get gift ideas for a loved one, up from 43% (the year is not stated); Pollfish for the company Talkdesk, Dec 31, 2025. Agile Brand Guide, Jan 12, 2026
The last two are vendor surveys, not independent research.
Why ask the receiver? Gino and Flynn (2011, five studies) found that recipients appreciated gifts they had explicitly asked for more than gifts they had not, while givers assumed both would be appreciated equally and expected unrequested gifts to seem more thoughtful than they did. That is a reason to ask the receiver. They tested requests for specific gifts and wish lists, not taste lists or links; whether asking for taste keeps that benefit and leaves the gift a surprise is what we have not tested.
What it does
- Loves and budget. Add 3 to 5 favourites (an optional type such as book or artist narrows the search) and a budget from $10 to $500.
- Gift ideas. A live list shows what the agent is doing while idea cards arrive, gifts first and experiences after. Each idea names the favourite Qloo links it to; product cards show title, price, shop and link; place ideas come with experience links.
- Pick and pay. Pick up to six items within the budget and pay as a guest in the PayPal sandbox.
- Receipt. After PayPal approves, the server captures the payment once and shows the order.
An AI model drives the work, but the server decides what is allowed. It checks every tool call against its own state, so the model cannot invent an id, a price or a charge, and a model outage does not block a payment. If the model's tool loop stops early, the server fills in what it skipped in a set order; if the model is unavailable, templates keep the page working and the page says so. Prices come from the product cards the server saved (a price sent by the browser is ignored), a total above your budget is refused before PayPal is called, and payment is captured once, only after PayPal says approved.
Copy note. Each idea that names a favourite has a Copy note button. It copies a line such as "I picked this because you love X." (naming the favourites behind the idea) followed by a blank line, and the page then reminds you to add one memory only you can write.
How Tasteloom uses Qloo
Qloo supplies the suggestions and the links between favourites and suggestions. The model chooses among them and writes the words, and the server checks the words.
| Step | Where | What happens |
|---|---|---|
| 1. Search | Qloo /search |
Each typed favourite becomes a Qloo entity (an optional type hint narrows it). |
| 2. Insights with explainability | Qloo /v2/insights |
Up to one call for each gift type (brand, book, artist, place, destination), with all the favourites as input signals and feature.explainability=true. Qloo returns entities the person is likely to like and, for each, which favourites drove it, strongest first, and the tags it gives the entity. Typed favourites are dropped. |
| 3. Popularity cut-off | Server, on Qloo's popularity percentile | Qloo gives each entity a popularity percentile (0 to 1, higher means more popular). Within one list of suggestions, results at 0.999 or above (household names) are dropped, but only if a less popular result with a Qloo link remains; otherwise the list stays whole. |
| 4. Choose | Model, under server rules | The model picks among Qloo's suggestions. The server refuses a pick that would give a third idea of one type, a second place or trip, or ideas all led by the same favourite, unless nothing else is left. |
| 5. Reason and check | Model, then server | The model is asked for a reason only when Qloo gives a tag to both the favourite and the idea. The reason is kept only if it names the favourite Qloo links most strongly and uses one of the shared tags; otherwise a template sentence built from that link replaces it. |
| 6. Buy | Shop and web search | A brand, book or artist becomes a product search at Channel3 (real products, real prices). A place or destination becomes experience links found with Tavily. |
- A live run makes one Qloo search for each favourite and one insights call for each of up to five gift types: at most 10 Qloo calls with five favourites.
- Qloo's share of each link. On a live run, each card shows How Qloo splits its link to this idea (adds up to 100%): the three favourites Qloo links most strongly, rescaled to 100% (a share of that link, not a match percentage), shown when two or more of them share it. A second row, Tags Qloo gives to both the strongest favourite and the idea, lists the tags they share, when there are any. The saved example was recorded before these rows existed and does not have them.
- Qloo's answers are used inside the request and are not stored by the app. (A local-development switch can cache them; the repository's deploy settings do not turn it on.)
npm run contract:qloomakes at most 5 live requests to the real Qloo API and checks the shapes the code expects.
Why not just ask a chatbot?
Same 20 made-up people, three ways: a language model on its own, a bigger model on its own, and Tasteloom (the smaller model inside our app, with Qloo and our rules). The method was written down before the run (Oct 29, 2026); the full table is under Proof.
- The same gift for different people: mixed, not a win. At the cut-off we set in advance (gift and reason text at least 0.85 similar): 0 of 76 for the model on its own, 2 of 80 for the bigger model, 0 of 80 for Tasteloom. On gift text alone, a check we set before any scored data, at least 0.85 similar: 5 of 76 and 9 of 80 for the models on their own, 17 of 80 for Tasteloom. Counted after we saw the data, those 17 are identical text for 8 different things; neither model on its own gave an identical gift to two people. After a change designed after we saw this, one re-run on the same 20 people gave 4 of 80 (see Proof).
- Merch of something they already love: 73 of 76 and 66 of 80 ideas on their own, 3 of 80 in Tasteloom. Partly by design: the app drops anything you typed.
- A reason that names one of their favourites: 80 of 80 in Tasteloom (by construction, whenever Qloo links the idea to a favourite); 39 of 76 and 35 of 80 on their own, where our prompt did not ask for it.
- In the app: under the idea cards, Compare: same AI, no Qloo sends the favourites and the budget to the same Workers AI model, with no Qloo data, and lists the four ideas it writes on its own, marking those that name one of the favourites. It links to the measured comparison. Its answer is not stored on our server.
Proof: the same model on its own and inside Tasteloom
Method (written down before the run, Oct 29, 2026). 20 made-up people, each with 3 well-known favourites and a budget of $25, $50 or $100; 4 gift ideas each; one run per condition, no re-runs. "On its own" is Qwen3-30B-A3B, the model Tasteloom uses, with a plain prompt; "bigger" is gpt-oss-120b, same prompt. "Inside Tasteloom" is Qwen3-30B-A3B inside our idea step (Qloo links, our rules, the server's reason check), run on a local copy of the app with shop and web search paused, so it measures the choice of ideas, not what is on a shelf. One reply from the model on its own was not valid JSON, so it has 76 gifts, not 80.
| What we counted | Model on its own | Bigger model on its own | Inside Tasteloom |
|---|---|---|---|
| Same gift also given to another person (gift and reason text at least 0.85 similar; cut-off set before the run) | 0 of 76 | 2 of 80 (3%) | 0 of 80 |
| Idea is merch of a favourite they already love (partly by design) | 73 of 76 (96%) | 66 of 80 (83%) | 3 of 80 (4%) |
| Reason names one of their favourites (by construction in Tasteloom) | 39 of 76 (51%) | 35 of 80 (44%) | 80 of 80 (100%) |
Other cut-offs for the first row: at 0.80, 11 of 76, 15 of 80 and 4 of 80; at 0.90, none in any column.
Repeats, in plain words. Counted after seeing the data: 17 of Tasteloom's 80 gifts have the same gift text as another person's gift (8 different things; one went to 3 people); neither model on its own gave an identical gift to two people. The first row shows 0 of 80 for Tasteloom because it also reads the first 12 words of the reason, and Tasteloom's reasons name each person's own favourites, which hides repeats; we claim no direction for that row. On gift text alone (a check set before any scored data), at least 0.85 similar is 5 of 76 and 9 of 80 on their own and 17 of 80 inside Tasteloom. So the result is mixed, not a win.
Reading the rows. Merch is partly by design: the app drops anything you typed, our plain prompt did not tell the models to avoid it, and the count matches names, so it can miss works. Reasons are named by construction: the server kept 96 of the 104 reasons the model wrote and swapped 8 for templates. Limits: 20 made-up people, one run, no spread measured; similarity scores are not strictly comparable between Tasteloom's short entity names and the models' longer descriptions.
A second test: change one word. Same 20 people and loves, but the prompt says "my mom" or "my dad"; we also asked the identical question twice for comparison. At 0.85 similar, a gift counts as changed when the other list has no similar gift. In this one run on 20 people, swapping the word changed about 50% of the gifts from the model on its own and 64% from the bigger model, against 36% and 47% when we asked the identical question twice. We ran no interval or significance test, so we do not claim the 14 and 18 point gaps are more than run-to-run noise. (4 of the bigger model's 80 replies could not be read and count as empty, as set in advance; leaving them out makes its gap about 20 points.) This shows that gifts change with the word, not why. Tasteloom asks for no age, gender or relation, so its ideas cannot change with that word; that is a design fact, and we did not run this test on Tasteloom.
After a change. After we saw the repeats we changed the idea step (one commit, five parts, so their effects cannot be told apart): household names yield to less popular suggestions, refusals that are not mistakes no longer count as strikes against the model's own loop, and a run offers at most one trip or place. We re-ran Tasteloom on the same 20 people, once (Oct 30, 2026, same method). Same gift text as another person's gift: 17 of 80 before, 4 of 80 after (2 things, each given to 2 people). Merch of a favourite: 3 of 80 before, 2 of 80 after. Runs finished by the server's own pipeline instead of the model's own loop: 9 of 20 before, 2 of 20 after. It costs more: model compute per person up 42%, median time per person 8.5 s to 9.8 s. We designed the change after seeing the repeats on these same 20 people, so this shows what it does on them, not on other people.
Which build was measured. The measured builds are 75bb9a0 (run 1) and 0aaa605 (run 2). The deployed build adds later changes: evidence rows on the cards, reasons written from shared Qloo tags, gifts listed before experiences, a filter that drops look-alike product cards, a 12-word minimum for a model-written reason, artist ideas titled "Music by ...", fallback picks that prefer a favourite with no idea yet (the fallback ran in 2 of 20 re-run people), and the Compare panel. These later changes were not re-measured.
Where the lists are. Tasteloom's lists contain Qloo-derived names, and Qloo's developer guide asks developers not to store Qloo response data in a public repository, so we publish the method and the counts, not the lists. Method and counts: docs/proof.md in the repository.
Privacy: what is sent where, and what we keep
| Service | What it receives |
|---|---|
| Qloo | the favourites as typed (and the type hint), then Qloo's own entity ids |
| Cloudflare Workers AI | the favourites and budget, the entities Qloo returned and the tags Qloo gives both an entity and the favourite it links most strongly, product titles and prices, and at checkout the ids of the picked items and the order's id, status and total. If you press Compare: same AI, no Qloo: the favourites and the budget only, with no Qloo data |
| Channel3 | product searches built from Qloo's suggestions and the model's wording, with a price ceiling |
| Tavily | searches for an experience idea (a place or destination Qloo suggested) and price checks of a product on its shop's domain |
| PayPal sandbox | the order (items, total) and the return from PayPal's page |
These services keep what they receive under their own terms, which we do not control. Qloo's terms (section 9) let Qloo reuse anonymized input signals sent to its API, including to improve its models.
What Tasteloom keeps. The favourites you type are not stored, and neither are the answers from Qloo and the model, including the Compare answer (a cache for Qloo and model answers exists only in local development; the repository's deploy settings do not turn it on). The server keeps the saved product cards and your budget for 2 hours; sandbox orders for 7 days; shop and web-search answers for 12 hours, under a hash of the search; and daily counters under a hash of the day and your IP address (for IPv6, its /64 network), cleared the next UTC day. There are no accounts, and Tasteloom sets no cookies. Your browser keeps your inputs, the finished run and your picks in sessionStorage (this tab only).
What we do not ask. No age, no gender, no account: only what they love, and your budget. Product photos load from the shops' own servers, which can see your IP address, so they are off by default (the link above turns them on).
Reply links. A reply link is encoded, not encrypted: anyone who has the link can read the answer in it, and the messenger you send it through keeps its own copy, so send it only to the person who asked. A reply holds at most 5 items of at most 80 characters each, and the part of the address after the # is capped at 2048 characters. That part stays in the browser; our server receives the favourites only when the giver presses Find gift ideas. In a browser test (Chromium against a local copy of the app, with Qloo and the model replaced by stand-ins, 2026-10-30), none of 639 requests carried a reply link in its address line, headers or body. We have not run that test against the deployed address.
Design and tests
- Design: plain HTML, CSS and ES modules (no framework, no build step); one warm palette with a single accent; three screens with a step indicator; every state designed (loading, empty, errors, limits, cancelled, failed capture, receipt); visible focus rings and full keyboard use; responsive from 320 px phones to desktop; colours tested for WCAG contrast. A line under the headline says what we do not ask: "No age, no gender, no account: only what they love."
- Tests (logs are in the repository's evidence folder): 237 unit tests, 0 failed (run Oct 30, 2026). A 1125-check browser run in Chromium with stand-ins for Qloo and the model, 0 failed (Oct 30, 2026). Separately, an 816-check browser run in Chromium against the live app on an earlier build (Oct 22, 2026), including a live search and a completed PayPal sandbox order.
- Code: https://github.com/Kylne700/tasteloom (MIT licence).
- Known limits: payments are sandbox only; web price checks rarely confirm a price; the browser tests run in Chromium only. The thin shop catalog and the small model are under Challenges.
Potential Impact
Gifts are a large spend: the National Retail Federation's October 2025 holiday survey (run by Prosper Insights & Analytics) forecast $890.49 per person on holiday gifts, food, decorations and other seasonal items, $627.93 of it on gifts for family and friends (a forecast of plans, not purchases; press release, Oct 16, 2025). Tasteloom is for the buyer who knows the receiver only in fragments. Situations we have in mind (illustrations, not survey data): a work gift exchange with a price limit, a partner's relative you see twice a year, a host you want to thank.
What this entry shows: a finished flow on a live app where the server checks every reason, and a measured comparison with the model on its own, including the result that does not favour us. What it does not show yet: that gifts chosen this way are liked more, or that a shop would pay. We have run no user test.
What we would test. About 10 gift-givers each get ideas twice for the same person and budget, once from a plain chatbot and once from Tasteloom (order varied), and say which ideas they would buy. Then the receiver, who sees no labels, rates both lists. A plan, not a result.
Who could pay. The shop, not the gift-giver: a retailer or gifting marketplace with a gift-finder page could add a reason to each pick. We have not spoken to one and have no price.
Why Qloo matters here. A reason that names a favourite and rests on Qloo's own link is one a shopper can check instead of trust.
Accomplishments we are proud of
- A finished, free flow on a live app: taste in, ideas with reasons, a payment in the PayPal sandbox, a receipt. Daily caps are kept in one Durable Object, so parallel requests cannot pass a cap and the demo stays inside free plans.
- Reasons the server checks, with a visible count: each live run lists "N of M reasons kept" in the agent's lookups.
- 237 unit tests and a 1125-check browser run with stand-ins (both Oct 30, 2026), and a separate 816-check browser run (Oct 22, 2026) that includes a completed PayPal sandbox order (logs in the repository's evidence folder).
- A contract script (
npm run contract:qloo) that re-checks the code's expectations against Qloo's live answers; it caught three answer shapes we had not expected (see Challenges). - A measured comparison that reports the result that does not favour us.
- A reply link that carries a person's answer with no account and no inbox on our side: the answer travels in the part of the address that browsers do not send to a server.
Challenges
- Qloo's live answers had three shapes we had not expected (found Oct 22, 2026, in a live contract run of 5 requests): search hits list their kind in
types, insight entities insubtype, and search answers carry no success flag. The contract script caught them and the parser now reads the real shapes. - A thin shop catalog. Many of Qloo's suggestions return nothing buyable, so a run often shows few product ideas and some experience links.
- A small, free model. On Oct 22, 2026 we tried 7 Workers AI models on the app's real flow (Qloo and catalog faked, real model). We kept the cheapest and quickest of those that completed the tool loop; two others sent invalid tool arguments. With its thinking mode on, the model we kept was slower and used more neurons, so we switch that mode off.
- The same names for different people, and a model loop that ended early. Measuring showed 17 of 80 gifts repeated across people. In 9 of 20 of our test runs (shop and web search paused) the model's own tool loop stopped early and the server's own pipeline finished the run, which still returned ideas. Replaying the earlier code pointed to two likely causes, both refusals that were not mistakes but counted as strikes (three strikes end the model-driven tier): an insights call made in the same turn as the searches it depends on, and several parallel product searches refused as too alike. We could not verify this on the original runs, whose tool answers were not recorded. We changed that rule and the idea step so that household names yield to less popular suggestions; after the changes 4 of 80 gifts repeated and 2 of 20 runs finished on the server's own pipeline (one re-run on the same 20 people).
- PayPal's sandbox page changes layout: a "Pay Now" button with a switch for saving your info, or two buttons, one of them "Pay now as guest". It is PayPal's page, so the checkout screen says which one to press.
What's next
- A user test, as described under Potential Impact.
- A wider product catalog, and group gifts (several people, one receiver).
Sources and dates (read 2026-10-29 unless noted)
- NRF press release, Oct 16, 2025 (forecast of plans, not purchases): https://nrf.com/media-center/press-releases/consumers-to-spend-second-highest-amount-on-record-according-to-nrf-holiday-survey
- Mixbook (vendor survey, YouGov, Oct 8, 2025): https://www.mixbook.com/inspiration/gifting-anxiety-report
- Talkdesk (vendor survey, Pollfish, Dec 31, 2025; reported Jan 12, 2026): https://agilebrandguide.com/ai-saves-shoppers-hours-during-the-2025-holiday-season-but-trust-hinges-on-transparency-and-ethics-new-talkdesk-survey-finds/
- Qloo hackathon developer guide: https://docs.qloo.com/reference/qloo-llm-hackathon-developer-guide ("Keys remain active through the end of the judging period and are deactivated after the hackathon closes."); judging period ends Nov 5, 2026, 11:45 pm ET (rules: https://qloo.devpost.com/rules); Qloo terms of use, section 9, last updated June 15, 2026: https://www.qloo.com/legal/terms
- Gino and Flynn, "Give them what they want: the benefits of explicitness in gift exchange", Journal of Experimental Social Psychology 47(5), 2011, pages 915 to 922; abstract on the Stanford GSB site (read Oct 29, 2026): https://www.gsb.stanford.edu/faculty-research/publications/give-them-what-they-want-benefits-explicitness-gift-exchange. The same paper reports that recipients appreciated money more than a gift they had requested; we make no claim about gifts versus cash.
- Workers AI free allocation of 10,000 neurons a day (Cloudflare pricing page) and 1,000 free credits a month each for Channel3 and Tavily (their docs): read Oct 22, 2026.
- Our own measurements: the comparison and the "mom or dad" test were run on Oct 29, 2026, and the re-run after a change on Oct 30, 2026; other counts are dated where they appear.
How AI was used
Tasteloom was built by AI coding agents (Claude Code) working in stages from written briefs; a person set the goals and owns the accounts the app uses. The tests, the comparison runs and this write-up were also produced by AI agents. At run time a model on Cloudflare Workers AI (Qwen3-30B-A3B) chooses among Qloo's candidates and writes the reasons, and the server checks them. The narration in the video is synthetic speech, not a real person's voice.
Built With
- channel3
- claude-code
- cloudflare-workers
- css
- durable-objects
- hono
- html
- javascript
- paypal
- puppeteer
- qloo
- qwen3
- sqlite
- tavily
- typescript
- workers-ai
- workers-kv
