Real products for Anthropic's Claude commerce agents, with a source receipt behind every fact. No account, no API key.
pip install airshelf-storefront-backend
airshelf-demo-swap ~/code/commerce-agents # their demo, 84 real products instead of 87 invented onesAnthropic's blueprint ships the agent and leaves the catalog to you. StorefrontBackend is an
interface with no implementation, and the retail example runs on 87 fictional products. This is a
real catalog behind that interface, across vendors, with nothing to sign up for.
Every fact the agent states comes back with the page it was read from. The ones with no
receipt are marked (unverified) inline, so the model knows which facts it may assert.
The blueprint's own packages are deliberately unpublished on PyPI, so install them from the repo first, into the same virtualenv:
git clone https://github.com/anthropics/commerce-agents
cd commerce-agents && ./scripts/install.sh
pip install "airshelf-storefront-backend @ git+https://github.com/airshelf/claude-commerce-catalog.git"(pip install airshelf-storefront-backend once the package is on PyPI.)
Two backends, one interface. Pick by whose storefront the agent is.
from airshelf_storefront_backend import AirShelfStorefrontBackend, MerchantStorefrontBackend
backend = AirShelfStorefrontBackend() # the cross-vendor catalog, every brand
backend = MerchantStorefrontBackend(merchant="toshiba") # one merchant's own storefrontAirShelfStorefrontBackend reads the shared catalog: SearchFilters.attributes become spec
constraints the catalog applies itself (a brand attribute becomes the catalog's manufacturer
filter), and get_disclosure returns the receipts box. Policies, orders and delivery return empty, because
the catalog is product truth, not a store.
MerchantStorefrontBackend reads one AirShelf merchant's own data: their product rows on the
per-merchant agent API and their indexed site pages, so search_policies answers "can I return
it" from the merchant's terms page and checkout_handoff sends the shopper to the merchant's
product page tagged ?airshelf_src=agent. It is what the merchant's claimed page at
ax.airshelf.ai/d/<domain>/claimed prints. No public price means quote-only and a
"Request a quote" handoff.
Hand it to the executor wherever the example passes MockRetailBackend. Turn on
ShoppingAgentConfig.enable_disclosures to get the receipts box, which is the point of using
this backend at all.
Check it against production before you trust it:
python smoke.py "600 dpi industrial label printer" # cross-vendor catalog
python smoke.py --merchant toshiba "industrial label printer" # one merchant's storefrontsmoke.py calls the backend the way a test does. run_agent.py calls it the way Anthropic's
agent does, with the MODEL choosing the filters, and prints every tool call and the answer:
COMMERCE_AGENTS_DIR=~/code/commerce-agents python run_agent.py \
"600 dpi industrial label printer for a warehouse" "compare the top two on print width"
python run_agent.py --merchant toshiba "which label printer does 5000 labels a day" "warranty?"It needs a /v1/messages endpoint: ANTHROPIC_API_KEY, or --base-url pointing at any shim
that speaks the Messages API (a LiteLLM proxy onto Azure OpenAI works; add --no-thinking,
Azure's chat/completions refuses tools together with reasoning effort).
Anthropic's retail example ships 87 fictional products, so every demo of a Claude shopping agent runs on a catalog that does not exist. One command replaces them:
airshelf-demo-swap ~/code/commerce-agents
cd ~/code/commerce-agents
python scripts/check.py # their own fixture validator
python scripts/run_demo.py retailTheir storefront now boots on real products, and each PDP marks the specs that carry no source receipt:
{
"product_id": "zebra-zd621",
"title": "Zebra ZD621",
"specs": { "resolution_dpi": "300", "print_width_mm": "104 (unverified)" }
}It rewrites catalog.json and repoints the product ids in orders.json,
merchant_inventory.json and merchant_messages.json, including the variant ids nested
under a family, so order history and the merchant portal keep working. Originals are copied
to *.airshelf-backup first, and --restore puts them back exactly.
Products with no public price are skipped rather than shown at $0.00.
| Their field | What AirShelf puts in it |
|---|---|
Product.product_id |
The AirShelf slug, <manufacturer>-<model> |
Product.title |
canonical_name, the exact string to cite. Do not paraphrase it |
Product.attributes |
Normalized specs, plus unverified_specs naming the ones with no receipt |
Product.labels |
quote-only, unverified-specs, identity-unconfirmed |
ProductDetails.specs |
Each value marked (unverified) unless a claim receipt backs it |
Disclosure |
One row per fact with its trust level, plus the source URLs |
Records are one machine to one row, so nothing is a family and no result carries variants. That
keeps every fenced result well inside max_fenced_chars, where a large variant matrix would not
fit.
The cross-vendor catalog holds product truth, not a store. These return empty instead of inventing an answer (the per-merchant backend answers search_policies from the merchant's own pages; the rest stay empty there too):
| Method | Why |
|---|---|
get_orders, get_order |
AirShelf records no orders |
search_policies |
Returns and warranty text belong to each seller |
get_fulfillment_options |
Delivery and pickup belong to each seller |
get_preferences |
Every session is a guest; there is no shopper profile |
Carts are held in memory for the session, because AirShelf sells nothing itself, and a cart
holds one currency. checkout_handoff returns one link per manufacturer, pointing at its own
product page. The retailer whose price is in the cart is named in the record, but the public
catalog does not expose that retailer's page, so this does not claim to send the shopper there.
Nothing settles here and no payment mandate is held.
A record with no public price is labelled quote-only and refused by the cart, rather than
entering it at a silent 0.00. A priced record whose source named no currency is served under
ISO 4217's XXX and labelled currency-unstated, rather than under a guessed USD; the cart
refuses it too.
SearchFilters.min_rating is ignored. AirShelf carries no ratings, and every product returns
rating unset, so the agent has nothing to misreport.
MIT. Anthropic's blueprint is Apache-2.0 and is not redistributed here.