Skip to content

feat: add structured product attributes via schema.org PropertyValue#401

Open
sakinaroufid wants to merge 4 commits intoUniversal-Commerce-Protocol:mainfrom
sakinaroufid:feat/product-attributes
Open

feat: add structured product attributes via schema.org PropertyValue#401
sakinaroufid wants to merge 4 commits intoUniversal-Commerce-Protocol:mainfrom
sakinaroufid:feat/product-attributes

Conversation

@sakinaroufid
Copy link
Copy Markdown
Contributor

@sakinaroufid sakinaroufid commented May 1, 2026

Description

Adds an optional attributes array on Product and Variant for measurable facts like battery life, display size, weight, and storage. Shared type at source/schemas/shopping/types/attribute.json, referenced from both schemas. Same shape as schema.org PropertyValue.

Each entry has required name and value plus optional key, numeric_value, and unit. numeric_value lets agents filter without parsing display strings. unit lets them compare across merchants. key gives verticals a stable slot for standardized identifiers without UCP shipping a canonical vocabulary on day one.

Catalog spec doc gains an Attribute section: placement decision tree (attributes vs options vs tags vs metadata), Product/Variant per-name override semantics, SHOULD-list of well-known units, worked example.

Additive. No new endpoints, transports, request shapes, or capability negotiation. Existing producers and consumers are unaffected.

Why

Agents handling queries like "phone with at least 20 hours of battery, under $800" need measurable facts in structured form. The catalog response usually contains the answer but it's stuck in prose: "all-day battery", "lightweight at 1.2 kg".

tags doesn't carry units. metadata accepts anything, so every merchant picks a different shape, which is the same fragmentation problem as parsing prose. options is for variant-defining axes (Color, Size), not measurable facts. None of them is a structured place for "Battery life: 22 hours."

The shape matches schema.org PropertyValue, which is what most catalog teams already publish via JSON-LD on their product pages. For them, adoption is mostly piping existing data into UCP responses.

Design notes

Shared type, not inlined. attributes lives on both Product and Variant, which matches how category.json, media.json, and rating.json are referenced from both. Avoids drift between two parallel definitions. Variant.barcodes stays inlined because barcodes are variant-only.

key in addition to name. Schema.org PropertyValue has both name (human-readable) and propertyID (stable identifier). Using only name makes cross-merchant filtering brittle: "Battery life" vs "battery_life" vs "Battery". The optional key field is the propertyID analog. Producers can populate it now, verticals can standardize values later, consumers that only care about name are unaffected.

Per-name override, not whole-array replace. When the same attribute appears on both Product and Variant, Platforms MUST match by key (if present) or case-insensitive name, override the Product entry with the Variant entry, and inherit any Product entries the Variant doesn't redeclare.

Open vocabulary on unit, with a SHOULD-list. Per the extensibility guidance: no enum. The schema description carries a SHOULD-list of well-known units (SI/UCUM where they exist: kg, mm, Hz; common catalog units otherwise: GB, inches, hours) plus an examples array for codegen affinity. Same pattern as barcodes.type.

Out of scope for v1

  • A UCP-canonical vocabulary of name or key values. Vertical extensions can standardize identifiers later.
  • Server-side filtering on attributes. Filtering happens agent-side over the catalog response.
  • Range expressions. v1 is single values.
  • Localization of attribute names.

Category (Required)

  • Core Protocol: Changes to the base communication layer, global context, or breaking refactors. (Requires Technical Council approval)
  • Governance/Contributing: Updates to GOVERNANCE.md, CONTRIBUTING.md, or CODEOWNERS. (Requires Governance Council approval)
  • Capability: New schemas (Discovery, Cart, etc.) or extensions. (Requires Maintainer approval)
  • Documentation: Updates to README, or documentations regarding schema or capabilities. (Requires Maintainer approval)
  • Infrastructure: CI/CD, Linters, or build scripts. (Requires DevOps Maintainer approval)
  • Maintenance: Version bumps, lockfile updates, or minor bug fixes. (Requires DevOps Maintainer approval)
  • SDK: Language-specific SDK updates and releases. (Requires DevOps Maintainer approval)
  • Samples / Conformance: Maintaining samples and the conformance suite. (Requires Maintainer approval)
  • UCP Schema: Changes to the ucp-schema tool (resolver, linter, validator). (Requires Maintainer approval)
  • Community Health (.github): Updates to templates, workflows, or org-level configs. (Requires DevOps Maintainer approval)

Schema additions to Product and Variant qualify as Core Schema Modifications under the Contributing Guide, so this PR follows the Enhancement Proposal track. The proposal lives at #400.

Related Issues

For #400. Currently in Proposal stage; this PR is the implementation reference and should not merge until the EP reaches Provisional via TC vote.

Checklist

  • I have followed the Contributing Guide.
  • I have updated the documentation (if applicable).
  • My changes pass all local linting and formatting checks.
  • (For Core/Capability) I have included/updated the relevant JSON schemas.
  • I have regenerated Python Pydantic models by running generate_models.sh under python_sdk. The Pydantic regeneration lives in the python_sdk repo and will land there as a follow-up once these schemas merge.

Screenshots / Logs (if applicable)

Local checks against the configs in .github/:

  • ucp-schema lint source/: 80 files checked, all passed.
  • DOCS_MODE=spec uv run mkdocs build --strict: built in 9.66s, no warnings or errors on the new section.
  • markdownlint with .github/linters/.markdownlint.json on the changed doc: 0 issues.
  • cspell with .cspell.json on changed files: 4 files, 0 issues.

Test plan

  • Schema validation, positive: required name/value enforced; each combination of optional fields validates; existing fixtures without attributes validate unchanged.
  • Schema validation, negative: missing name rejected; missing value rejected; numeric_value as string rejected.
  • Conformance fixture: worked example (phone with product- and variant-level attributes).
  • Conformance fixture: display-only case (numeric_value absent, only value populated).
  • Conformance fixture: override case (same key on Product and Variant, assert per-name merge).

Add an optional `attributes` array on Product and Variant for measurable
facts like battery life, display size, weight, and storage. Defined as a
shared type at types/attribute.json with required name/value and optional
key, numeric_value, and unit. Same shape as schema.org PropertyValue.

The catalog spec doc gains an Attribute section with a placement decision
tree (attributes vs options vs tags vs metadata), Product/Variant override
semantics, and a worked example. Marked Working Draft until at least one
merchant prototype lands.

Additive: no new endpoints, transports, request shapes, or capability
negotiation. Backward compatible with existing producers and consumers.
@sakinaroufid sakinaroufid requested review from a team as code owners May 1, 2026 03:59
@sakinaroufid sakinaroufid requested review from jingyli and westeezy May 1, 2026 03:59
@sakinaroufid sakinaroufid marked this pull request as draft May 1, 2026 04:27
@sakinaroufid sakinaroufid marked this pull request as ready for review May 2, 2026 01:06
@BuyWhere
Copy link
Copy Markdown

BuyWhere commented May 5, 2026

This is a welcome addition to the UCP spec. Structured product attributes via schema.org PropertyValue make it much easier for AI agents to do meaningful product comparison across merchants — an agent can filter on “processor generation” or “screen size” directly rather than parsing free-text descriptions.

We are doing something similar on the BuyWhere side — normalizing product data from Shopee, Lazada, and other marketplaces into a structured schema with typed attributes before surfacing it through our MCP server. Having UCP standardize this at the protocol level would save a lot of per-source mapping work.

One question: does this cover nested/complex attributes? For example, a laptop has CPU (with its own properties like cores, clock speed), RAM (type, size), and display (resolution, panel type).

@BuyWhere
Copy link
Copy Markdown

BuyWhere commented May 5, 2026

Great to see progress on structured product attributes. At BuyWhere (buywhere.ai), we have been working on normalized product catalogs across multiple merchants and regions. We use schema.org as a base but extend with commerce-specific properties (pricing tiers, availability windows, multi-currency). Happy to share our category taxonomy if it helps inform the UCP spec.

@sakinaroufid
Copy link
Copy Markdown
Contributor Author

Hi @ptiper - would you mind pls tagging the right reviewers?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants