Agent-Ready Commerce, Part 2: From Product Pages to Commercial A developer argues that AI agents require a different interface than traditional ecommerce product pages, which are designed for human interpretation and can tolerate ambiguity. The platform must expose a source-backed, freshness-aware, and action-supporting view of products to enable safe agent actions like recommendation, comparison, and checkout. The article focuses on the 'facts' part of the agent-ready commerce chain, emphasizing the need for operational truth over presentation. A product page is not a contract. It is a presentation surface. That distinction matters more once AI agents start interacting with commerce systems. Traditional ecommerce platforms can rely on human interpretation. A human can read a product title, inspect images, compare delivery notes, scan a return policy, notice uncertainty, and decide whether to continue. A product page can be visually useful even when the underlying commercial state is incomplete, stale, or spread across several systems. An AI agent needs a different interface. It should not need to scrape a product page, infer policy meaning from free text, guess whether inventory is fresh, or decide whether a price is reliable enough to quote. If the platform expects agents to recommend products, compare alternatives, prepare checkout, or act within delegated authority, then the platform needs to expose more than product presentation. It needs to expose commercial truth. This is the second article in the Agent-Ready Commerce series. Part 1 introduced the broader model: Facts → Eligibility → Authority → State transition → Evidence → Audit This article focuses on the first part of that chain: facts . The central argument is simple: a raw product record is not enough for agent-ready commerce. The platform needs a source-backed, freshness-aware, action-supporting view of the product before agents can safely act on it. A normal product page compresses many different concerns into one human-readable surface: Product identity Price Inventory Images Description Badges Variants Delivery estimate Return policy snippet Warranty information Promotional copy Reviews Cross-sell modules Checkout call to action That compression is useful for presentation, but it is lossy from a systems perspective. The page may show “In stock,” but the inventory value may be several hours old. It may show a price, but the pricing source may have changed since the last feed publication. It may show a return-policy sentence, but the policy may not apply to every category, region, or customer type. It may show marketing claims that are approved for humans to read, but not precise enough for agents to quote. A human can tolerate some of this ambiguity. An agent should not be forced to. A product page answers a presentation question: How should this item be shown to a buyer? An agent-facing product contract has to answer operational questions: What is currently known about this item? Where did that knowledge come from? How fresh is it? Is it complete enough for discovery? Is it complete enough for comparison? Is it complete enough for checkout? Is it safe for an agent to quote? Those are different questions. Treating the product page as the source of truth mixes them together. Consider a product in a catalog: Product: Travel Backpack SKU: BAG-TRAVEL-42 Price: €129 Catalog status: active Inventory status: in stock Category: Travel Bags A simple storefront can render this product. It has a title, a price, an image, a category, and an inventory flag. A basic product model might look like this: type Product = { id: string; sku: string; title: string; description: string; price: { amount: number; currency: string; }; inventory: { status: "in stock" | "low stock" | "out of stock"; quantity?: number; }; categoryId: string; imageUrls: string ; active: boolean; }; This is enough to display a product card. It is not enough to decide whether an AI agent can safely act on the product. Suppose the real platform state looks like this: Price: fresh, verified 5 minutes ago Inventory: stale, last synced 18 hours ago Return policy: missing for Travel Bags Warranty policy: known Shipping policy: known for EU, unknown for US Generated description: pending review Feed publication: last published yesterday A human-facing storefront may still show the product. The commercial system, however, has several unresolved questions. Can an agent discover this product? Probably yes. Can an agent compare it with another backpack? Maybe yes, if comparison only needs identity, price, category, and basic attributes. Can an agent quote the return policy? No, because return-policy coverage is missing for the category. Can an agent prepare checkout? No, because inventory is stale. Can an agent trigger delegated payment? Definitely not, because checkout is not even valid yet. A single field like active: true cannot represent these distinctions. This is the gap commercial truth is meant to fill. Product data describes the item. Commercial truth describes what the platform is currently willing to rely on about the item. Those are related, but not identical. A catalog record may say: js const product = { id: "bag travel 42", title: "Travel Backpack", price: { amount: 129, currency: "EUR" }, inventory: { status: "in stock" }, active: true }; A commercial truth summary might say: type ProductTruthSummary = { productId: string; truthVersion: string; facts: { identity: FactStatus; price: FactStatus; inventory: FactStatus; policyCoverage: FactStatus; media: FactStatus; generatedClaims: FactStatus; }; overallStatus: "verified" | "incomplete" | "stale" | "conflicting"; }; type FactStatus = { status: "known" | "missing" | "stale" | "conflicting" | "unknown"; sourceRefs: string ; lastVerifiedAt?: string; }; For the backpack example, the truth summary could look like this: js const truth: ProductTruthSummary = { productId: "bag travel 42", truthVersion: "truth 2025 10 18 001", facts: { identity: { status: "known", sourceRefs: "catalog import 2025 10 18" , lastVerifiedAt: "2025-10-18T09:00:00Z" }, price: { status: "known", sourceRefs: "pricing sync 2025 10 18 0905" , lastVerifiedAt: "2025-10-18T09:05:00Z" }, inventory: { status: "stale", sourceRefs: "warehouse sync 2025 10 17 1500" , lastVerifiedAt: "2025-10-17T15:00:00Z" }, policyCoverage: { status: "missing", sourceRefs: }, media: { status: "known", sourceRefs: "media library 2025 10 15" }, generatedClaims: { status: "unknown", sourceRefs: "ai description draft 778" } }, overallStatus: "incomplete" }; The commercial truth object does not replace the product. It qualifies it. The product says what the item is. The truth summary says how much confidence the platform has in the facts required to use that item in commerce workflows. Source references are not metadata decoration. They are part of the reliability model. A price from a pricing service, an inventory value from a warehouse sync, a warranty statement from a policy document, and a description generated by an AI workflow should not be treated as equally authoritative. A source reference can be modeled simply: type SourceReference = { sourceId: string; sourceType: | "catalog import" | "merchant admin" | "pricing system" | "inventory system" | "policy document" | "media library" | "generated content"; sourceVersion?: string; sourceHash?: string; observedAt: string; }; The important point is that commercial facts should be traceable. Without source references, the platform cannot easily answer basic operational questions: Where did this price come from? Was this inventory value synced or manually edited? Was this policy claim approved or generated? Did the source change after the feed was published? Which source should be revalidated before checkout? For human-facing commerce, missing traceability may create debugging pain. For agent-facing commerce, it also creates trust problems. If an agent quotes a return policy or prepares checkout based on stale inventory, the platform needs to know which fact led to the decision and which source produced that fact. This is why commercial truth should be evidence-aware from the beginning. Freshness is often modeled too broadly. A product is marked fresh or stale. That is not precise enough. Different facts have different risk profiles. Stale inventory is more dangerous than a stale product image. Stale price may block checkout but not discovery. Missing warranty information may block policy quotation but not product comparison. A generated description pending review may block agent quotation but not internal merchandising. A better model tracks freshness by fact group: type ProductTruthFreshness = { identity: "fresh" | "stale" | "unknown"; price: "fresh" | "stale" | "unknown"; inventory: "fresh" | "stale" | "unknown"; policyCoverage: "fresh" | "stale" | "unknown"; media: "fresh" | "stale" | "unknown"; generatedClaims: "fresh" | "stale" | "unknown"; }; For the backpack example: js const freshness: ProductTruthFreshness = { identity: "fresh", price: "fresh", inventory: "stale", policyCoverage: "unknown", media: "fresh", generatedClaims: "unknown" }; This allows the platform to make more useful decisions: Discovery: allowed Comparison: allowed Policy quotation: blocked Checkout preparation: blocked Delegated payment: blocked A single productIsFresh value would hide the reason. Fact-level freshness gives the platform a way to degrade gracefully instead of treating the product as either fully usable or fully unusable. A commercial truth layer should describe what is known. It should not become responsible for every business decision. This boundary is important. Commercial truth answers: What facts exist? Where did they come from? How fresh are they? Are they complete? Are they conflicting? Eligibility answers: Given those facts, which actions are allowed? Those two layers should remain separate. For example: type TruthReadiness = { productId: string; facts: { price: "fresh"; inventory: "stale"; policyCoverage: "missing"; }; }; The truth layer can produce that result without deciding what the agent may do. The eligibility layer can then apply action-specific rules: type AgentCommerceAction = | "discover" | "compare" | "quote policy" | "add to cart" | "prepare checkout" | "delegate payment"; type EligibilityDecision = { productId: string; action: AgentCommerceAction; allowed: boolean; blockers: string ; }; A simplified eligibility function might look like this: function evaluateCheckoutReadiness truth: TruthReadiness : EligibilityDecision { const blockers: string = ; if truth.facts.price == "fresh" { blockers.push "Price must be revalidated before checkout." ; } if truth.facts.inventory == "fresh" { blockers.push "Inventory must be revalidated before checkout." ; } if truth.facts.policyCoverage === "missing" { blockers.push "Required policy coverage is missing." ; } return { productId: truth.productId, action: "prepare checkout", allowed: blockers.length === 0, blockers }; } This separation prevents the truth layer from becoming a hidden monolith. If a business later decides that stale inventory should still allow cart insertion but block checkout, that change belongs in eligibility rules, not in the definition of inventory truth. A useful boundary is: Truth describes the commercial facts. Eligibility decides what those facts allow. Not every action requires the same quality of truth. Discovery may require only identity, visibility, media, and basic category information. Comparison may require price and comparable attributes. Policy quotation requires policy coverage and source references. Checkout preparation requires fresh price, fresh inventory, and applicable policies. Delegated payment requires even more: checkout validity, cart integrity, payment authority, and possibly human confirmation. The same product can therefore have different readiness levels for different actions. type ActionTruthRequirement = { action: AgentCommerceAction; requiredFacts: Array< | "identity" | "price" | "inventory" | "policyCoverage" | "media" | "generatedClaims" ; }; Example requirements: js const requirements: ActionTruthRequirement = { action: "discover", requiredFacts: "identity", "media" }, { action: "compare", requiredFacts: "identity", "price" }, { action: "quote policy", requiredFacts: "policyCoverage" }, { action: "prepare checkout", requiredFacts: "price", "inventory", "policyCoverage" } ; For the backpack example, the resulting matrix might be: discover allowed compare allowed quote policy blocked: return policy missing prepare checkout blocked: inventory stale, return policy missing delegate payment blocked: checkout not valid This is more useful than marking the product as generally available or unavailable. Agent-facing systems need to know what kind of action is safe. Operators need to know which missing facts block which commercial capabilities. Some product facts are direct values. Others are derived. Direct fact: Price is €129. Derived fact: Product is visible to agents. The second statement depends on rules. It might depend on catalog status, product category, merchant settings, policy completeness, feed publication status, generated claim review, and regional restrictions. Derived facts should include provenance. type DerivedFact