When the user asks whether to buy something, whether a price is good, or whether to wait for a drop, read this before you answer, even when you could answer from memory, because the answer needs a price history and reviews opened this turn. When the user names a product they are about to buy and asks whether it costs less anywhere, read this before you search, because it sets which stores to check and how to report them. Also when the user asks you to buy, order, reorder, or compare a product...
Installs into .claude/skills of the current project.
Are you the author of Shopping?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/danielfebrero-shopping)
---
name: shopping
description: >-
When the user asks whether to buy something, whether a price is good, or
whether to wait for a drop, read this before you answer, even when you could
answer from memory, because the answer needs a price history and reviews
opened this turn. When the user names a product they are about to buy and asks
whether it costs less anywhere, read this before you search, because it sets
which stores to check and how to report them. Also when the user asks you to
buy, order, reorder, or compare a product on Amazon or any other retail site,
asks you to fill a retail cart they will check out themselves, asks which of
two or three products to get or whether one costs less at another store, or
sends a product link to purchase, before you open the store or add anything to
a cart, alongside any store's site playbook. Also when the user asks you to
find, search for, recommend, or shortlist products, such as the latest model
of a phone or accessories for one, before you search or hand the search to a
subagent, so its task asks for the facts the product cards need. Read it as
well as the purchases skill, which covers only how to pay.
---
# Shopping and checkout
You buy products for the user on Amazon and any other retail site. The user picks the product and approves the exact order, in chat or by tapping Pay on an order card, and that approval is what places it. You do the searching, comparing, cart building, and form filling, and you show your work with screenshots at the moments that matter.
## Entry points
- "Order more of the coffee filters I usually get" is a reorder; start from the usual list in memory and the store's order history, as the `orders-and-returns` skill's What the user usually buys says, not a fresh search.
- "Buy a 65-inch TV under $800 with good reviews" is a compare-then-buy with a budget.
- "Find me a good travel stroller" is browsing; the deliverable is a shortlist before anything goes in a cart.
- "Which of these two should I get?" or "Is it cheaper at Target?", about two or three specific products or one product at several stores, is a comparison; the deliverable is the side-by-side view in Comparing offers, and the user picks.
- "I'm about to buy these headphones at Best Buy for $249, is it cheaper anywhere?", or a product link sent with a check before paying, is a price check: a comparison of that product at other stores, with the store and price the user named as the one to beat (see Price check before paying).
- "Should I buy this?" or "Is $600 a good price for it?" asks for advice, not a cart; the deliverable is the verdict in Should I buy it.
- A pasted product link goes straight to that product page.
- A photo or screenshot of a product ("buy this", "find these shoes") is a search: name what you see (brand, model, color) and search for it, then confirm the match with the user before it goes in a cart.
- A list (a packing list, "a phone case, a charger, and a screen protector") is one cart with several items: search each, then review once.
- "Fill my cart, I'll check out" or "I still press buy" is cart only; the deliverable is a filled cart and a handoff, never a payment (see Cart only).
- A message that buys products from your shopping card by name, store, price, and link, and names a saved card and a saved address by Vault id, comes from the app's Checkout sheet, where the user already chose the variant, the store, the card, and the address. Open each link, choose that variant, and go to checkout, one store at a time, without a new search, a shortlist, or a question about which card, which address, or how to pay. The prices it names are the card's, before shipping and tax.
- A message that buys one product from your shopping card by name, store, price, and link, with no Vault ids, comes from that card's Pay now button, where the user already chose the variant and the store. Open the link, choose that variant, and go to checkout without a new search or a shortlist. When you will pay with an order card, ask nothing about which address, which card, or how to pay on the way, since the order card shows those beside Pay. The price it names is the card's, before shipping and tax.
## Before you start
- Resolve what, how many, and any hard constraint (budget, brand, delivery-by date, size). Infer harmless defaults and state them. Ask only when the answer changes what to buy.
- Run SearchPlugins for the retailer the user named. Use a connector when one is installed. Install a missing connector with InstallPlugin without asking; its connect card is the ask. Ask in one widget first only when the user named no service and several plugins fit (Gmail or Outlook, Google or Outlook Calendar), or the plugin has no connector. Say in the user's words why it helps, without saying plugin, MCP, or plugin id, and never paste a connect link. If the search finds nothing, dispatch a `computerUse` subagent with the site's search URL built from the query, for example `https://www.amazon.com/s?k=bread+flour`, so it lands on results instead of clicking through the home page.
- When the user names the store or stores to buy from, or asks whether one sells a product ("is it on Walmart?"), pass their sites, such as `walmart.com`, in `ProductSearch`'s `sites`, so only their offers come back. Leave `sites` out when the user wants the best price wherever it is or asks which store is cheapest, since it hides every other store.
- Read the Memory section for the user's preferred retailer, membership status, default shipping address, sizes, brand rules, whether they always check out themselves (see Cart only), and anything they have said about upsells or delivery speed. Call RecallMemory for a past order they mention.
- If the user has a membership (Prime, Walmart+, a store card), note it, because prices and delivery dates differ from the guest view.
- A compare across three or more stores, or a hunt through many listings, spends much more of the user's plan than a single search. Before you start one, when `CheckSubscriptionUsage` is among your tools, call it. When it reports that most of this cycle's included usage is used and does not say that on-demand usage is enabled, or that the trial ends within a day, send a question widget whose prompt says so in one line and asks whether to run the quick version (one store, its top three matches) or the full hunt. Otherwise start the full hunt without asking.
- When the store's site playbook or an earlier attempt in this conversation shows that it blocks agents or needs a sign-in before it keeps a cart, say so in one line before you start, and name the store you would try next if it does.
## Flow
1. Open the results or the linked product page with the subagent. Only the subagent's final message reaches you, so list in its task every fact you need back for each top candidate: its own product page URL, name, brand, the model number and UPC or EAN when the page shows them, price as shown and any was price, stock state as one of `in_stock`, `out_of_stock`, `preorder`, `backorder`, or `made_to_order`, rating and review count, delivery date and shipping cost, seller, the product image URLs with the main one first, the options it comes in (such as color or size), and up to six key specs as label and value, the same specs for every candidate. For a comparison (see Comparing offers), also list any membership perk the page shows, the return window and who pays return shipping (from the store's return policy page when the product page does not say), and the pack size. Most stores publish these facts as JSON-LD, so on a store with no site playbook have it run this page script on each product page and read the rendered page only for what the script misses: `async (page) => { const o = [], a = (v) => [].concat(v ?? []), u = (i) => i?.url ?? i?.contentUrl ?? i, q = (e) => { if (Object(e) !== e || e.availability == null) return e; const t = String(e.availability).toLowerCase(), availability = /outofstock|soldout|discontinued/.test(t) ? 'out_of_stock' : /preorder|presale/.test(t) ? 'preorder' : /backorder/.test(t) ? 'backorder' : /instock|limitedavailability|onlineonly|instoreonly/.test(t) ? 'in_stock' : e.availability; return { ...e, availability }; }, x = (n) => a(n.offers?.offers ?? n.offers).slice(0, 12).map(q), g = (n) => n.gtin ?? n.gtin13 ?? n.gtin12 ?? n.gtin14 ?? n.gtin8, w = (n) => { if (Object(n) !== n) return; if (Array.isArray(n)) return n.forEach(w); if (a(n['@type']).some((t) => /^(https?:\/\/schema\.org\/)?Product(Group)?$/.test(t))) { const b = a(n.brand)[0], k = a(n.variesBy).map((v) => String(v).split('/').pop()), v = a(n.hasVariant).slice(0, 48), p = [...new Set([...k, ...'color,size'.split(',').filter((name) => v.some((e) => e?.[name] != null))])]; return o.push({ name: n.name, url: n.url, brand: b?.name ?? b, model: n.model?.name ?? n.model, mpn: n.mpn, gtin: g(n), images: a(n.image).slice(0, 5).map(u), rating: n.aggregateRating, offers: x(n), ...(v.length > 0 && { variesBy: k, variants: v.map((e) => ({ name: e.name, url: e.url, image: u(a(e.image)[0]), options: Object.fromEntries(p.flatMap((name) => e[name] == null ? [] : [[name, e[name]]])), mpn: e.mpn, gtin: g(e), offers: x(e) })) }) }); } w(n['@graph']); w(n.mainEntity); w(a(n.itemListElement).map((e) => e?.item ?? e)); }; for (const s of await page.locator('script[type="application/ld+json"]').allTextContents()) { try { w(JSON.parse(s)); } catch {} } return o.slice(0, 12); }`. When a store blocks its product pages, have it take the facts from the search results instead, including each result's thumbnail image URL; the accessibility snapshot carries no image URLs, so it reads them from the result cards' images with a page script. For a compare across stores, check two or three stores the user would buy from in parallel subagents, and note each store that blocked the subagent or had no match. When the user asked about one product or sent its link, also list for it the facts step 6 reads for the product they choose, so its first card is the full entry.
2. Fill the gaps before you present. A shortlist the user can choose from has a photo, a price, a rating, the stock state, and the specs that set the candidates apart for each product; a comparison also needs the extra facts step 1 lists for one. When the report leaves out one of these for a candidate, look first in what you already read, such as a "Page image:" line from an earlier WebFetch of that page, then call WebFetch on the product pages still missing facts, all in parallel; its output starts with a "Page image:" line when the page has a photo. Ask the subagent again only for what WebFetch could not read, and leave out a fact no page showed. Many stores refuse WebFetch, even with a 404, while serving the subagent's browser, so a product page the subagent opened and read in this task is a live link however WebFetch answered.
3. When the site wants a sign-in, a one-time code, or a verify-you-are-human check, follow the Cursor-managed `sign-in` skill in its order, which ends with the Secure Form (`RequestUserForm`) and then handing over the screen with `request_box_help` and one instruction ("Sign in to your <service> account"). Never send a question widget before these; the tool is the ask. After a receipt or a hand-back, dispatch the subagent again; the session persists across turns.
4. Compare. For a visual choice (looks, color, a spec table), take a Screenshot and attach the saved path. Summarize price, rating, delivery date, and the specs the user cares about (see Presenting choices). For a comparison, follow Comparing offers instead.
5. Get the pick. If the user delegated with exact criteria ("order whichever is cheaper delivered") and one product clearly wins, choose it, say why, and still show it before checkout. "Which should I get?" asks for your recommendation, not for you to choose, so the user still picks.
6. Check variants. Size, color, quantity, pack count, and subscription versus one-time purchase change the price. For the product the user is choosing, have the subagent read each option combination its page offers, including combinations that are sold out, with that combination's price, stock, image URL, and page URL; on a store with no site playbook, the page script from step 1 returns them as a product group's variants. For that product only, also have it read each option value's swatch color or image, a short description, the review summary the page shows, the shipping and return policy lines, and links to a size guide, spec sheet, or manual, which fill its full entry (see Presenting choices). Ask with a question widget when the user did not specify and the options are real; otherwise take the default and say so. A saved size (see Sizes and preferences) answers the size question only, so still ask about any other open variant. When more than one variant is open, ask about them together in one short message instead of one question at a time.
7. Add to cart. For several items, repeat the search, compare, and add cycle, then review once.
8. Review the cart from a screenshot, then send the user the cart summary: one line per item with the product as a link, its brand, the variant (size, color, pack count), quantity, unit price, and the seller when it is not the store itself, then the subtotal, shipping, tax, and total as far as the page shows them, with the cart screenshot attached at its saved path. When the cart changes, send a fresh summary so the latest one always matches the cart.
9. Shipping address. Reuse the account's saved address when memory or the page confirms it is the right one. When you will pay with an order card and there is no saved contact to ship to, ask nothing in chat: collect the address with a contact form as the purchases skill says. Otherwise, if the page needs an address typed and the Cursor-managed `vault` skill is in your catalog, follow that skill: use the user's saved contact, and ask in chat for only what it lacks. Without that skill, ask with `RequestUserForm`, with fields targeted at the live checkout page. Confirm the chosen address with the user before you continue, unless they chose it in the app's Checkout sheet or you will pay with an order card, whose Ship to row shows the address beside Pay and lets them pick another saved one.
10. Codes. When the checkout takes promo codes before the final page, gather and enter them on that page, as Codes and offers in the Savings check says, before you go on. When the offer you are buying listed a promo in a `ProductSearch` result, brief the subagent with its exact codes and have it enter every one in the checkout's promo or coupon field before the final page, one at a time, reading the total after each, since the deal price assumes all of them apply. A price drop with no code has nothing to enter; check that the page shows that price. A Pay now or Checkout sheet message names no code, so match its link to that offer in the result, and run `ProductSearch` again for the product when the result is no longer in this conversation.
11. Reach the final review page. Screenshot it. Have the subagent return each line with its amount as the page shows it, then the total, because an order card shows them: each item with its variant, quantity, line total, and https image URL, shipping with its arrival date, tax, each discount as a negative amount, and each fee. Have it also return the checkout page's https link and the name and address the checkout ships to. Your quote is the step 8 cart summary and the shortlist prices, or the prices a Checkout sheet message named, never a promo's deal price. When you entered a promo code, the page must show its discount line or a total that dropped by it; when it shows neither, the code did not apply, so handle it as the Savings check says and name the page's total as the price. Compare each item line on this page with the unit price you quoted for it times its quantity, and compare the unit price itself when the page shows one. Remove any line the user did not ask for, such as a protection plan or an add-on, say that you removed it, then screenshot the page again and read its lines and total again, so the screenshot you attach shows the order as it now stands. Before the order card or the ready-to-buy summary, write one line for each item whose price differs from the quote and for each line the quote did not have (a fee, a protection plan, a subscription, a tip, a donation): the line, what you quoted, what the page shows, and the difference. Then give the change in the total. Shipping and tax that show up for the first time are not price changes, but name their amounts. Shipping or tax that your quote already named and that moved gets its own line the same way, with both amounts. When the page's lines do not add up to its total, do not ask for approval. Report each line and the gap, and stop.
12. Run the savings check on that total (see Savings check). Then get the yes, pay, and place the order (see Paying and confirming).
13. Screenshot the order confirmation. When you paid through an order card, first reply with `purchase` as the purchases skill says, with the delivery estimate in `content`. Then, however you paid, send a shipment card at stage `placed` from the confirmation page in its own `SendToUser`, with the total charged in `content` (see Paying and confirming). When no card goes out, the `purchase` reply is the whole report for an order card; for any other order, report the order number, the total charged, and the delivery estimate. Then, when the purchases skill has an After the order section, create the routine it describes to follow the order until it arrives. Save any size or preference you learned along the way that is not in memory yet (see Sizes and preferences).
## Sizes and preferences
The user should not have to repeat a size or a brand rule they already told you.
- Before you ask for a size, check the Memory section for their size in this brand, then their general size for this kind of item. Use what is saved and say which entry you used ("your usual Aritzia M"). Ask only when nothing is saved or the brand's size chart says this item runs differently.
- Brands size differently, so keep fit per brand and item type ("Levi's 501 jeans: 32x30", "Nike running shoes run small, size up half"), not one size for everything.
- When the user states a size, a fit note, a brand they like or avoid, a default retailer, or a material or ingredient rule, save it with `UpdateMemory`, one fact per entry with the brand and item type. Then name what you saved in one short line of your next message ("Saved: Nike running shoes, 10.5"), even when the rest of the reply is about something else, so they can tell you not to keep it. If they do, remove it.
- A new size replaces the old one for that brand and item type, whether the user simply states it or says the last one did not fit (then wait until they confirm the new size). Before you write it, remove every older entry for that brand and item type in the Memory section, so memory never holds two sizes for the same brand and item.
## Presenting choices
- When `SendToUser` has a `shopping` field, show products in it instead of a text list: every shortlist, and a single product the user asked about or picked. A shortlist entry gets its title, images, one variant with its best offer and that offer's stock state from step 1 as `availability`, its rating, its `specs` with the same labels on every entry, a `keySpec` that is one of those labels and names the spec that sets it apart, a short `note` on what sets it apart, and that strength again as one `good` reason, since some apps show the note on the tile and others the first good reason. Give a `badge` to at most two entries, and only for a comparison the shortlist's data backs up: Top rated, Lowest price, Best value, Biggest discount, Best seller, or Most reviewed. Leave the rest without one, and never badge a material, room, style, or opinion. The product the user asked about or picked gets the full entry: its options with swatches, every variant you found, including ones that are sold out, with its offers and their `policies`, its specs, `about`, `reviewSummary`, and `links`, a `note` on why it fits, and your `reasons` for and against. One item sold in several colors, sizes, or pack counts is one product whose variants are those choices, not one product per color. A product whose `id` came from a product search result gets its options and variants from the card, which fills them from that result's offers and catalog, including sold-out combinations and every size and color the result lists. The product detail shows those options, so write variants only to correct or translate them, or for a product you found another way. Fill the gaps first (step 2), but a rating or spec you still could not get is only left out of that product's entry, never a reason to send a text list. A card needs at least one image, so for a product still without one, run `ProductSearch` for it when you have that tool and use the matching result's id, or else show only that product as an item line. Link each offer to the product's own page that you or the subagent read, and use a search results page only for a product whose own page nobody opened. In `content`, give your pick and the main tradeoff, and name each store that blocked you or had no match. A comparison fills the field as Comparing offers says.
- Without that field, show three to five candidates that differ on something that matters, one per line as `- [Item name](https://item-page-url), $25.60, short note`. The note carries what sets it apart, such as the rating with review count, the delivery date, the seller, or a spec the user asked about.
- Attach a screenshot when the choice is visual or the spec table is dense. A summary alone is enough for a reorder.
- Name the tradeoff plainly ("$40 more for the version with a battery indicator"). Do not pad the list with near-duplicates.
- When a `ProductSearch` offer lists a promo, mention it with that product: its codes, or that it is a price drop with no code, the deal price, the site and age the result gives, and when it ends if the result says, beside the store's price ("$24.00 at Northwind, or $18.00 with code TRAIL20 that a deal site reported yesterday"). It is a deal to try at checkout, not a price, so never lead with the deal price or rank by it. A promo the result says may have expired, or reported at an unknown time, gets a mention only as a long shot. An offer without promos may mean only that the lookup found or returned none, so never say no deals exist.
- Use a question widget for the pick when the shortlist is short and every option is a real product you saw. Otherwise send the summary and let the user reply.
- Show what you collected in the user's language, which is the language they write to you in unless they asked for another or the Memory section names one they prefer. When a page is in another language, translate the words you put in a card or a summary, such as titles, descriptions, specs and their labels, notes, review summaries, policies, delivery and status lines, and option names. Keep brand, store, seller, and venue names, model numbers, order numbers and other codes, prices with their currency, and links as the page shows them. Brief the browser subagent and type into the site in the site's own words, and match a choice the user makes in their language back to those words. A product you send by its product search `id` gets its title, `about`, `specs`, and `reviewSummary` from the search, in the search's language, wherever you leave them blank, so when you translate, write those fields on that product yourself. Its `variants` fill the same way, so when their option names or values would show in another language, write the variants yourself with translated option names and values, and in each put at least one search offer that sells that option, keeping its seller, price, and link. The card fills that offer's stock, delivery, and checkout link from the search and adds the option's other sellers, so write an offer's `delivery` only to translate it. Write `options` only together with the variants, because `options` alone puts every offer in one variant.
## Comparing offers
When the user is choosing between two or three specific products, or the same product at different stores ("which of these two?", "is it cheaper at Target?"), put the offers side by side. Send the side-by-side view and the recommendation, not a shortlist as well.
- Every comparison covers the delivered price (item plus shipping and tax as far as the page shows), the delivery date, the membership perks that apply (Prime, Walmart+, a free shipping threshold), the return window and who pays return shipping, and the seller and its rating, even when the user said which specs matter most. Add the specs the user named after those.
- Read the return window from the product page or the store's return policy page. When neither shows it, write "not shown" rather than a typical value.
- For the same product at several stores, confirm the model number or pack size matches before comparing prices, and say when it does not.
- When `SendToUser` has a `shopping` field, put the comparison there. Give each offer its `delivery`, its shipping and return terms as `policies`, and its perk as `note`. Two or three products get a `compare` with rows for "price", "rating", and the specs every product lists, and the recommendation as its `verdict`. One product at several stores is one product with an offer per store. Without that field, use one column per offer in a compact table, or one line per offer on a channel that shows plain text.
- Name every store you checked and how many there were, including each one that blocked you or had no match, so the user sees what the best price was measured against ("Checked 4 stores: Target, Walmart (out of stock), Best Buy, Amazon (blocked)").
- End with a one-line recommendation and the reason ("Target: $12 less delivered and a 90-day return window, arrives a day later"), then ask which one they want, with a `followUps` reply per offer when you sent the `shopping` field.
### Price check before paying
- Check three to five stores that sell the same product, starting with the brand's own store and the retailers the user would buy from, plus the sellers a `ProductSearch` result lists for it. The store the user named is one of them, at the price you read on its page this turn; when that differs from the price they gave, say so.
- The message text carries the result, also beside a `shopping` card, because the card shows one price and neither the stores you checked nor the differences. Its first sentence is the count line from Comparing offers, marking each store that blocked you, had no match, or had the product out of stock. Its second gives each in-stock offer's difference from the store the user named, cheapest delivered price first: "Checked 4 stores: Target, Walmart (out of stock), Best Buy, Amazon (blocked). Against Target's $89.00 delivered, Best Buy is $6.51 less." When the store they named is already the cheapest, the second sentence says that plainly.
- Work each difference from the two delivered prices, the item plus shipping, exact to the cent: $89.00 against $82.49 is $6.51 less. Never round a difference or write "about".
- A promo code's deal price holds only once a cart shows it, so rank that offer by its price without the code, and give the deal price and its exact difference beside it.
- Offer to put the cheapest offer in a cart and take it to the approval. That is a purchase through the Flow from step 6, and nothing is bought without the user's yes.
- When the user buys at a cheaper store because of this check, record the saving after the order is placed: kind cheaper_store, dated the order date, at the store where they bought, with the link to the product at the store they started from as proof. The amount is the all-in price at the store they started from, less the all-in price they paid. When a code also applied at the cheaper store, use the price before the code, since the code is its own promo_code saving. Save one fact of type "journal" with UpdateMemory for each saving, in exactly this shape: `Saving YYYYMM: YYYY-MM-DD | kind | amount CURRENCY | store | proof link`. YYYYMM is the year and month of that date with no separator. amount CURRENCY is how much less the user paid, with its ISO 4217 code, such as 6.00 USD. Never start any other fact with Saving and a month. Record nothing when they bought at the store they started from, or switched for another reason.
## Should I buy it?
Follow this when the user asks whether to buy something or whether a price is good, or is about to spend a lot on something a cheaper fix might solve. Answer before any talk of checkout, and start the Flow only once they say they want to buy.
- Open a price history page for the item, such as camelcamelcamel or Keepa for Amazon, or the store's own, and say whether today's price is high, normal, or near its low.
- Read the rating and the most common complaint in the reviews you open.
- Name one cheaper option, or a fix for the problem behind the purchase, when one exists.
- Lead with a one-line verdict: Buy, Wait for a drop, Skip, or the cheaper option. Then give the evidence. For Wait for a drop, offer to watch the price as the `orders-and-returns` skill says.
- Take every price, rating, and count from a page you opened this turn, and link that page. If you could not open a source, say so instead of estimating.
- When `SendToUser` has a `shopping` field, send the item there instead of a long reply, with the verdict in `content`, the evidence in the product's `reasons`, and the price history page in its `links`.
## Cart only
Follow this when the user wants a filled cart and will check out themselves, or when memory says they always do. The deliverable is the cart and a handoff, never a payment.
- Build the cart in the user's own store account, signed in the way step 3 says, when they have one. A cart in their account shows on their own phone or computer. A guest cart in your browser does not move to their device.
- Follow the Flow through step 8. Apply a promo code on the cart page when the cart takes one, including one a `ProductSearch` offer listed, and say whether the cart's total dropped.
- Then send the handoff: the step 8 cart summary, the store's cart page link, and one line that the cart is waiting in their account. For a guest cart, or a store without an account cart, send the store's own share-cart or list link when the page offers one. Otherwise send each item as its product link with the variant and quantity.
- In the same message, offer to hand over the screen with `request_box_help` and one instruction ("Check out your cart on <store>"), so they pay in your browser themselves. When that checkout hand-off comes back, read the page. Report an order as step 13 says only when the page is the store's order confirmation. Otherwise say the cart is still waiting.
- Never open a payment form, raise a virtual card, send an `order` card, or click the place-order control in this mode. A later "go ahead and buy it" is a normal purchase through Paying and confirming.
- When the user says they always want to check out themselves, save that as one memory fact and name it, the way Sizes and preferences saves a size.
- When the user hesitates about paying or asks whether it is safe, offer cart only as one plain option in one sentence, without a lecture.
## Savings check
Run this once, on the final review page's total with shipping, tax, and fees, before you ask for the approval; a total from an earlier page can still be missing some of them. When the checkout takes codes only on an earlier page, gather them as Codes and offers below says before you leave that page and enter them there; the rest of the check still runs on the final page. It is one short pass, not a new search.
- Codes and offers. Apply the offers the checkout itself shows, such as a coupon to clip, an automatic cart promotion, or a member price for a membership in the Memory section. When an email connector is installed, search the user's mail for this store's promo codes, such as a welcome, newsletter, or loyalty offer, and keep only codes that have not expired. When the checkout has a promo code field and neither a tool result nor the mail gave a code, ask whether the user has one. Enter only a code the user, a tool result, or the user's mail gave, once each; never guess codes or take them from a list of codes on another site, since stores treat that as abuse. When the store rejects a code, or the total does not drop after it, carry on at the total the page shows with any code that did apply. Tell the user in one message every code you found, where each came from (the email's sender and subject, the tool result, or the user), and which one applied. Cash-back portals and rebate sites are not part of this check; leave them out.
- The merchant's own site. When you are buying through a marketplace seller, a travel site, or another reseller and the total is above 100 USD, or that amount converted to the checkout's currency at today's rate, or above an amount the user set for this check, read the same item, dates, and terms on the merchant's own site (the brand's store, the airline, the hotel). Tell the user both totals. When the merchant's is lower and the user wants it, start the purchase over on the merchant's site from the cart or booking step, so the cart summary, the review, and the approval all come from that site; never carry lines or a total from one site to the other. Keep the reseller when the user chose it for a reason, such as a perk or their account there. When `CheckSubscriptionUsage` reports that most of this cycle's included usage is used and does not say that on-demand usage is enabled, skip this part and say so in one line.
- The card. When you will pay with a card from the user's vault (see Paying and confirming), the user has not already chosen the card, as a message naming it by Vault id does, and `Vault` list shows more than one saved card, pick the one whose `When to use:` line fits this store or this kind of purchase, and give the reason in that line's words. Name only perks a `When to use:` line states, never a reward rate or protection you assume a card has. Without such a line, pick as you otherwise would and give no reason. When the user tells you a card's perk, such as extra points on groceries or a travel credit, offer to add it to that card's hint with `Vault`, and change the hint only when they say yes.
- Then say in one line what the check saved and how ("Saved $6.00 with CAMP6 from the store's welcome email", "Saved €297 by booking direct"), or that the codes you tried did not apply. Say nothing about savings when there was nothing to try.
- After the order is placed, record each saving, since the user paid the lower price: kind promo_code for a code or checkout offer, or direct_booking for buying on the merchant's own site instead of a reseller, with the reseller's total, including any code that applied there, less the merchant's total before any code you entered on the merchant's site, since that code is its own promo_code saving, dated the order date, with the order's https link as proof. Save one fact of type "journal" with UpdateMemory for each saving, in exactly this shape: `Saving YYYYMM: YYYY-MM-DD | kind | amount CURRENCY | store | proof link`. YYYYMM is the year and month of that date with no separator. amount CURRENCY is how much less the user paid, with its ISO 4217 code, such as 6.00 USD. Never start any other fact with Saving and a month. Save nothing when nothing was saved.
## Paying and confirming
- The user must have asked to buy this specific item. Never spend on your own initiative, and never buy to hold a price.
- When the purchases skill has you send an `order` card, as it does to pay with a card saved in the user's vault or a connected wallet, that card is the ready-to-buy summary and the confirmation, so send it in place of the summary and widget below. It carries the items, every charge, the total, where it ships, and how they pay, and its Ship to and Pay with rows let the user change the address and the payment before they tap Pay. So ask nothing about which address, which card, or how to pay before you send it: pick them as the purchases skill says, with X Money only when the user asked for it or chose it as their default. Send no question widget after it either, because a later widget can close the order card. A Checkout sheet message has settled the card and the address: its card's Vault id is the order's `payment.card`, and the saved address its Vault id names is where the order ships, written in `shipTo` as the purchases skill says, never as that address's title or id. Place the order after the user taps Pay, as that skill says.
- Otherwise, before payment, send the ready-to-buy summary: the cart summary from step 8 with each line and the subtotal, shipping, tax, and total read again from the final review page, then the shipping address, the delivery date, and the payment method the page shows, with the review page screenshot attached at its saved path. Then send one question widget whose prompt names the total and the delivery date ("Place the $84.17 order, arriving Tue, Oct 20?"), with options to place it and to edit the order, and allowCustom on so they can name a change. The widget ends your turn. A dismissed widget is a no.
- Give that widget an option for the user to check out themselves. When they pick it, send the handoff in Cart only and place nothing.
- When the site wants payment, a deposit, or a card to hold the booking, work it in this order and stop at the first step that pays. First, a payment method already saved on the site's own account, not a card in the user's vault. Have the subagent select it, and when that account has several, ask which one in the confirmation widget. Next, when the account has none and the `purchases` skill lists a card saved in the user's vault, use that card as its Credit cards section says. When that skill has you send an `order` card, read every line, the total, and the ship-to address from the checkout's review page before you send it, and charge only after the user taps Pay. When neither has one and the site charges an exact total now (tax, fees, tip, and shipping included), Stripe Link is the preferred way to pay: with `RequestVirtualCard` among your tools this turn, raise a one-time card with the site as merchant and type it only into the merchant's checkout; a denial is final. Without that tool, offer Stripe Link once as the `purchases` skill says, when that skill is listed. A card kept on file for a hold or a no-show fee is not charged now, so it never gets a one-time card. Next, and right away whenever the user turns Link down, ignores the offer, or asks to use their own card, send the Secure Form (`RequestUserForm`, reason "checkout", the site's domain) for the card inputs the live checkout shows, such as card number, expiry, CVC, name, and billing ZIP; never tell them you can't take their card, and never predict that the form can't reach card inputs embedded from a payment provider. Last, when the host refuses the form or its receipt says a card field failed, or the user would rather type on the page, hand the box to the user with `request_box_help` and one instruction ("Add your card and confirm the payment on <service>"); the same handoff covers a CVC re-entry and any 2FA, 3DS, or bank prompt. The user finishes the payment inside that handoff, so when the box comes back, skip any later confirm or place-order click and read the confirmation page. When the user already typed their card into chat, use it as given for that checkout instead of sending the form. Card numbers, CVCs, and expiries stay in the merchant's checkout, never in chat or logs.
- Place the order only after the widget's yes, and only the order that widget read back. A change that arrives after the widget went out ("make it two", "the black one") is a no for that order: update the cart, send a fresh summary and widget, and wait for its yes. On the yes, check the page before any payment details go in. Resume the helper that read the review page and give it each line (product, variant, quantity, and unit price) from the ready-to-buy summary sent with the widget the user answered, plus the total and the delivery date that widget named, since a tap can land on an older widget. Tell it to navigate to the review page again, every time, by opening the page's address or going back to the cart and continuing to checkout, because a page loaded before the widget can show prices the store no longer charges. It must not use the browser's reload, which can resubmit a checkout form. It compares that page with them, and when any of them differs, it stops without placing and reports what the page shows. When they all match, take the payment as the payment order says on that same page, without navigating away, since leaving clears typed card fields: a one-time card raised for the total the helper just checked, the Secure Form, or the card the user typed in chat. When the payment goes through a `request_box_help` handoff, the user places the order there, so skip the click and read the confirmation page. Otherwise the helper clicks the place-order control once, dismisses the post-order prompts (a survey, a protection plan, a subscription offer) without accepting them, and reads the confirmation page.
- When the helper stops on a difference, nothing was placed. Send the user what changed and a fresh ready-to-buy summary read from the page as it is now, with a new review page screenshot, then a new widget whose prompt names the new total and the delivery date, and wait for its yes.
- A yes to a ready-to-buy widget sent before the latest one is a no for that order, so do not place it. Say in one line that the widget they answered was for an earlier order, then ask with a widget which they want. One option is the order the latest ready-to-buy summary read back, named by its total. A yes to that option places that order, with the helper checking the page against the latest summary as above. Any other pick needs its own fresh ready-to-buy summary, screenshot, and widget first.
- When `SendToUser` has a `shipment` field, report an order's status as a shipment card in it, one card per order. Take its facts from the store's order or confirmation page, the carrier's tracking page, or the shipping email. The card takes the store's name in plain words and its site URL, its logo image URL when the page shows one, the order number, and each item's title, quantity, and image URL; the accessibility snapshot carries no image URLs, so the subagent reads them from the page's images with a page script. The card needs the store, the order number, and at least one item. Without that field or any of those, report in text instead. Set `stage` from the page's status: `placed` until it ships or a courier picks it up, even when it is due today, `in_transit` once it ships, `arriving_today` when it is on its way and out for delivery or due today, `delivered`, `delayed` when the page says it is late or shows a delivery exception, or `cancelled`. Put the page's own status headline in `status`, translated into the user's language when the page is in another, since a translation still keeps the store's words, and the expected or actual delivery date in `expectedDeliveryDate` as YYYY-MM-DD. For a range, use its last day. Fill `tracking` only with a tracking link a page showed or the URL of the carrier page the subagent opened, and the carrier's name; never build one from a tracking number. Leave out any value no page showed. In `content`, write one sentence on what changed, without the tracking link. The card's message takes no images, links, other cards, or voice memo, so send a screenshot or photo in its own `SendToUser` after the card.
## Pitfalls
- Membership pricing and delivery promises differ from the guest view. Say which one the user is seeing.
- Out of stock, "ships in 3 to 5 weeks", or a delivery date after the user's deadline is a flag before checkout, not after.
- Bundle suggestions, protection plans, and subscribe-and-save upsells are ignored unless the user asked for them.
- Multi-page checkouts hide the real total until the last page. Screenshot the final review page, not the intermediate ones.
- Never present a total you cannot account for line by line.
- A marketplace seller with poor ratings or a long ship time is worth a sentence even when the price is best.
- A page saying the site does not allow AI agents (Amazon shows one) ends that store for this request, so never reload or retry it. Do not stop at the block either. Take the product's brand and model number or UPC from what you already have, such as the user's link text, a search result, or the page's structured data, and check two or three other stores the user would buy from for that exact product in parallel subagents. Match on the model number or UPC, not the title, and call out a near match as one. Then send one message: the blocked store and what its page said, in one line, then each store that has the product with its price, delivery date, and seller, presented as a compare (see Presenting choices), and your pick. When you ask for the store with a question widget, its prompt opens with the blocked store and that it does not allow AI agents, because the options alone never tell the user why the store they named is missing.
- Never invent a price, a rating, a delivery date, a promo code, or an order number. If the page did not show it, say so.
- A deal price is the price only once the checkout shows it. Every approval, in an order card or a widget, names the total the page will charge.
## Site playbooks
Before you dispatch the browser subagent, Read the `site-playbooks-facebook-marketplace`, `site-playbooks-ebay`, `site-playbooks-etsy`, `site-playbooks-craigslist`, `site-playbooks-bestbuy`, `site-playbooks-target`, or `site-playbooks-costco` skill in this catalog, whichever names the site you are about to use, and paste the Dispatch snippet of the job that matches your step (a read-only lookup, or a cart and checkout) into the Task text. It carries the deep link or endpoint that lands on results instead of clicking through the home page, and the stop rules for that site.