RRetailAgentOS

For platform engineers & builders

Implement two contracts. Pick a tier. Everything else is derived.

RetailAgentOS is a reasoning layer on top of UCP (Universal Commerce Protocol). You write a MerchantCatalogAdapter and a BuyerContextResolver; the engine derives your manifest, JSON-LD, product feed, decision pipeline, quotes, and traces. You never re-implement commerce reasoning.

This page renders ADOPTION-GUIDE.md as a product page. That file in the repo is canonical — this is the same content, laid out for reading without cloning anything. See the spec catalog for the exact contracts.

The mental model, 60 seconds

UCP gives commerce its rails: discovery, catalog, cart, checkout handoff. RetailAgentOS adds the layer UCP doesn't carry — the merchant's reasoning: who may see an item, who may buy it, at what price, in what stock, shipped where — moved from checkout-time to catalog-time, as deterministic, machine-readable contracts with a reason code on every decision.

VISIBILITY → ELIGIBILITY → FEASIBILITY → PRICE → FULFILLMENT → QUOTE

Same inputs, byte-identical output, always. No model in the loop, no clock reads inside the engine. One axis to remember: the conformance tier (0–4)describes your store's maturity — a buyer's gold/silver/guest loyalty standing is a separate, orthogonal claim, never a tier.

What you implement: two contracts, nothing else

The engine package is @retailagentos/engine. Zero runtime dependencies; importing it self-registers all evaluators.

import { evaluateOffer, buildManifest, toSchemaOrgProduct } from '@retailagentos/engine';

// 1. Map YOUR catalog to canonical variants
interface MerchantCatalogAdapter<TSource> {
  merchantProfile(): MerchantProfile;      // tier + capabilities[] + endpoints + servesRegions
  toVariants(source: TSource): Variant[];  // one of your products -> 1+ RAOS variants
  listVariants(): Variant[];               // your whole normalized catalog
}

// 2. Resolve who is shopping (region, fulfillment mode, claims)
interface BuyerContextResolver {
  resolve(input: { region?: string; fulfillmentMode?: string }): PartialBuyerContext;
}

Two rules you must not break:

  1. Never call the system clock inside evaluation — read Date.now() once at your server boundary and pass it in as now.
  2. Never fork the reasoning. If a spec doesn't fit your store, raise it as an Open Question on the spec — don't quietly re-implement a decision outside the engine.

Everything else is derived

From the two contracts, the engine derives every agent-facing surface.

You callYou getServe it at
buildManifest(profile)UCP discovery manifestGET /.well-known/ucp
toSchemaOrgProduct(variant)Product + Offer JSON-LDeach product URL (server-rendered)
toProductFeed(variants)Google-format feed rowswherever you publish feeds
evaluateOffer({merchant, variant, quantity, context, now})full DecisionRecord with reasonsyour API / MCP tools
issueQuote(record, now) / validateQuote(...)price-lock tokensquote + checkout handoff
buildDecisionTrace(record) + 3 renderersbuyer / merchant-ops / developer views of any decisionUI, support tooling, logs

The trace renderer (developer / merchant-ops / buyer views) is backed by RAOS-0013.

The adoption ladder — pick your tier, ship in steps

Each tier is cumulative and independently valuable. A one-person boutique can stop at Tier 1 and already be agent-safe. You declare a headline tier plus an authoritative capabilities[]list in your manifest; agents negotiate against it and degrade gracefully for anything you don't support — partial adoption is first-class.

  1. 0

    Tier 0 · Discoverable

    an agent can find and correctly read my catalog

    Typical effort: ~1 day once your adapter maps the catalog.

    Implement MerchantCatalogAdapter over your existing product data

    RAOS-0000

    Serve buildManifest() at /.well-known/ucp

    RAOS-0000

    Serve toSchemaOrgProduct() JSON-LD on product pages (prerender or edge function if you’re an SPA)

    RAOS-0000

    Acceptance

    • curl https://yourstore.com/.well-known/ucp returns tier + capabilities
    • curl on a product URL returns valid JSON-LD without JavaScript
  2. 1

    Tier 1 · Qualified

    no dead-end carts

    Only eligible, in-stock items surface, with a reason for everything hidden or blocked.

    Populate eligibilityRules on variants (visibility, region, qualification)

    RAOS-0001

    Populate inventory state (+ freshness TTL, optional soft-hold reservation)

    RAOS-0005

    Implement BuyerContextResolver; call evaluateOffer per product view / cart line

    RAOS-0000 §4

    Acceptance

    • An out-of-region or out-of-stock request returns a ReasonEntry (e.g. REGION_RESTRICTED, OUT_OF_STOCK) with severity and resolution path — not a silent miss or a checkout failure
  3. 2

    Tier 2 · Priced

    the right price per buyer, honored at checkout

    Configure member / bulk pricing (MOQ, increments, tiers, teaser prices, purchase limits)

    RAOS-0002

    Issue and validate quote tokens; declare your honor policy (grace / requote / reject)

    RAOS-0007

    Attach the trust/freshness envelope (simulated signing is fine to start — it’s labeled)

    RAOS-0008

    Acceptance

    • The price an agent shows is bound in a TTL’d QuoteToken
    • A stale or context-changed quote is re-quoted per your declared policy, never silently repriced
  4. 3

    Tier 3 · Member-aware

    specs planned · don't build ahead

    supports member/loyalty-aware pricing and earn preview

    Loyalty earn/burn preview

    RAOS-0009

    Subscriptions & recurring

    RAOS-0010

    Promo stacking

    RAOS-0006

    Catalogued and designed but not yet published or built. Track status on the specs index. Don't build ahead of a published spec — the contracts may still move.

  5. 4

    Tier 4 · Assisted

    specs planned · don't build ahead

    full commerce: fulfillment, handoff, intent, returns

    Fulfillment feasibility

    RAOS-0003

    Cart bridge & checkout handoff

    RAOS-0012

    Intent capture routing (part 2)

    RAOS-0013 pt 2

    Returns & post-purchase policy

    RAOS-0014

    Catalogued and designed but not yet published or built. Track status on the specs index. Don't build ahead of a published spec — the contracts may still move.

How agents actually reach you

Minimum (Tier 0)

Static surfaces — manifest + JSON-LD + feed. Crawlable agents work with zero live endpoints.

Interactive

Expose evaluateOffer and issueQuote as MCP tools on a long-lived server. The MCP layer is a thin adapter: authenticate, inject now, call the engine, return its output unmodified.

Checkout

Hand off to your existing checkout (e.g. Stripe session), carrying quote tokens. RAOS carries reasoning + locked prices; checkout owns payment and tax.

Worked example: TheCustomHub

pilot in progress

A real made-to-order apparel merchant (Vite/React SPA on Firebase, Stripe checkout, ~59-product Shopify-shaped products.json) adopting the ladder as a pilot. This is in-progress integration work, not a completed live deployment — nothing here claims a completed real purchase or a live MCP endpoint.

Ladder stepWhat it looked like there
AdapterCustomHubAdapter: products.json → variants; compareAtPrice → applied offer; inventoryQty → inventory state; null variant rows stripped
Buyer contextregion (US/CA allowlist via checkServesRegion) + fulfillment mode
Tier 0manifest via Cloud Function; JSON-LD via prerender (the SPA is invisible to agents otherwise)
Tier 1–2eligibility + inventory + quote via evaluateOffer/issueQuote behind a Cloud Run MCP server
DifferentiatorcallForPrice: true custom/bulk SKUs route to structured intent capture instead of dead-ending at a contact form

Full detail lives in the repo: specs/reference-implementation/thecustomhub/(discovery → spine design → implementation plan → the self-contained brief you can hand to a coding agent for any new merchant integration).

For platforms

Build it once, every merchant inherits it

A single merchant integrating this ladder gets one agent-ready store. A commerce platform that implements the adapter and resolver once — against its own multi-tenant catalog and buyer-context model — makes every merchant on that platform agent-ready with zero additional work per store. The spec is the leverage: the hard part (deterministic reasoning, reason codes, quote integrity) lives in the engine and the specs, not in each integration.

Ground rules the whole architecture depends on

From RAOS-0000, applying to every tier.

  • Determinism: same (BuyerContext, manifest, catalog, now) → identical output.
  • Most-restrictive default: unknown/missing/untrusted context degrades to guest. Asserted (unsigned) privilege claims are downgraded for transaction-gating stages.
  • Fail-degraded, never crash: a failing safety-critical evaluator blocks; a failing advisory evaluator is omitted.
  • Additive-only evolution: reason codes never change meaning; semver per namespace; deprecation via supersededBy.
  • Namespace: com.os.retailagent.shopping.*, vendor-neutral, written as UCP upstream candidates.
  • v1 seams: USD-only (currency field exists as a seam), single-merchant cart.

Where to go next