<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Artemii Karkusha</title>
    <description>The latest articles on DEV Community by Artemii Karkusha (@integration-maestro).</description>
    <link>https://dev.to/integration-maestro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3865759%2F8184c618-63be-45d4-9583-040d74524d2a.jpeg</url>
      <title>DEV Community: Artemii Karkusha</title>
      <link>https://dev.to/integration-maestro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/integration-maestro"/>
    <language>en</language>
    <item>
      <title>UCP April 2026: Cart, Catalog, and Signals Change Everything</title>
      <dc:creator>Artemii Karkusha</dc:creator>
      <pubDate>Fri, 10 Apr 2026 16:51:20 +0000</pubDate>
      <link>https://dev.to/integration-maestro/ucp-april-2026-cart-catalog-and-signals-change-everything-chl</link>
      <guid>https://dev.to/integration-maestro/ucp-april-2026-cart-catalog-and-signals-change-everything-chl</guid>
      <description>&lt;p&gt;On April 8, 2026, the &lt;a href="https://ucp.dev" rel="noopener noreferrer"&gt;Universal Commerce Protocol&lt;/a&gt; shipped its most significant release since launch. Eighty-nine commits from twenty-plus contributors over eleven weeks. Twenty-seven new schemas. Five breaking changes. And three entirely new capabilities that transform UCP from a checkout protocol into a full commerce lifecycle specification.&lt;/p&gt;

&lt;p&gt;After &lt;a href="https://dev.to/articles/visa-vic-vs-ucp-agentic-commerce-architecture"&gt;analyzing UCP's architecture against Visa's VIC reference agent&lt;/a&gt;, I've been tracking this spec closely. This release answers the question I raised in that analysis: &lt;em&gt;can an open protocol cover the entire pre-purchase journey — discovery, browsing, cart building — without losing the schema rigor that makes it production-ready?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer is yes. Here's what changed, what broke, and what it means for integration teams building on top of UCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pre-Purchase Story Gets a Protocol
&lt;/h2&gt;

&lt;p&gt;The headline feature of this release is three new top-level capabilities that cover everything &lt;em&gt;before&lt;/em&gt; checkout.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdblnls33us5692qb1qym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdblnls33us5692qb1qym.png" alt="UCP commerce lifecycle pipeline: Catalog Search, Cart, Checkout, and Order connected left-to-right, each with its capability endpoint label. Search and Cart marked NEW. Signals flow through every stage via the signals framework." width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cart: Browsing Without Commitment
&lt;/h3&gt;

&lt;p&gt;UCP now has a formal Cart capability (&lt;code&gt;dev.ucp.shopping.cart&lt;/code&gt;) — and the design reveals how carefully they thought about the distinction between "exploring" and "buying."&lt;/p&gt;

&lt;p&gt;A cart is not a checkout. This sounds obvious, but most commerce platforms blur this line. Shopify's cart &lt;em&gt;is&lt;/em&gt; a pre-checkout. Magento's quote &lt;em&gt;becomes&lt;/em&gt; an order. The boundaries are fuzzy, and that fuzziness creates integration nightmares when you need to sync cart state across systems.&lt;/p&gt;

&lt;p&gt;UCP's cart has a deliberately simple lifecycle:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Aspect&lt;/th&gt;
      &lt;th&gt;Cart&lt;/th&gt;
      &lt;th&gt;Checkout&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;State model&lt;/td&gt;
      &lt;td&gt;Binary — exists or 404&lt;/td&gt;
      &lt;td&gt;Lifecycle — pending → active → complete&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pricing&lt;/td&gt;
      &lt;td&gt;Estimated totals&lt;/td&gt;
      &lt;td&gt;Final, committed pricing&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;Required for completion&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Sharing&lt;/td&gt;
      &lt;td&gt;
&lt;code&gt;continue_url&lt;/code&gt; for handoff&lt;/td&gt;
      &lt;td&gt;Session-bound&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Conversion&lt;/td&gt;
      &lt;td&gt;Converts to checkout via &lt;code&gt;cart_id&lt;/code&gt;
&lt;/td&gt;
      &lt;td&gt;Converts to order on completion&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The conversion mechanism is idempotent — passing the same &lt;code&gt;cart_id&lt;/code&gt; always returns the same &lt;code&gt;checkout_id&lt;/code&gt;. This follows the &lt;a href="https://dev.to/rules#idempotency-mandate"&gt;Idempotency Mandate&lt;/a&gt; at the protocol level, preventing duplicate checkouts when network retries happen during cart-to-checkout conversion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-World Example:&lt;/strong&gt;&lt;br&gt;
  &lt;span&gt;In a multi-platform integration where an AI agent builds a cart across Shopify and Magento storefronts, UCP's cart-checkout separation means the agent can accumulate items from different merchants into separate carts, then convert each to a checkout independently. The cart's &lt;code&gt;continue_url&lt;/code&gt; enables handoff between agents — one agent discovers products, another completes the purchase. This is the kind of workflow that falls apart when cart and checkout are the same object.&lt;/span&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Catalog Search and Lookup: Discovery Gets Structured
&lt;/h3&gt;

&lt;p&gt;Two new capabilities handle product discovery — and they're designed to be adopted independently, which is the right architectural call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Catalog Search&lt;/strong&gt; (&lt;code&gt;dev.ucp.shopping.catalog.search&lt;/code&gt;) provides free-text search with structured filters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// UCP Catalog Search — semantic query with filters&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CatalogSearchRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Optional — enables filter-only browsing&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// OR semantics&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Minor units (cents)&lt;/span&gt;
      &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// BCP 47&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ISO 4217&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Buyer purpose signal&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;pagination&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 10, business sets upper bound&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two design decisions stand out here. First, &lt;code&gt;query&lt;/code&gt; is optional — meaning you can do filter-only browsing, image search, or any other discovery modality via extensions. Second, &lt;code&gt;category&lt;/code&gt; uses an array with OR semantics and supports multiple taxonomies (Google Product Category, Shopify, merchant-custom). This avoids the taxonomy lock-in problem that plagues catalog integrations between PIM systems and commerce platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Catalog Lookup&lt;/strong&gt; (&lt;code&gt;dev.ucp.shopping.catalog.lookup&lt;/code&gt;) handles targeted retrieval when you already know what you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Batch lookup with correlation tracking&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CatalogLookupRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Product IDs, variant IDs, SKUs&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;SearchFilters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Optional post-resolution filtering&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Response variants carry input correlation&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;VariantWithCorrelation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;featured&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// How this was resolved&lt;/span&gt;
  &lt;span class="p"&gt;}[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;inputs&lt;/code&gt; correlation on the response is particularly well-designed. When you batch-lookup 10 product IDs and get back 15 variants, each variant tells you which input IDs resolved to it and whether the match was &lt;code&gt;exact&lt;/code&gt; (variant-level) or &lt;code&gt;featured&lt;/code&gt; (product-level, server-selected). This eliminates the guesswork that happens in every catalog integration where you request items by ID and get back a flat list with no context about &lt;em&gt;which request&lt;/em&gt; each result satisfies.&lt;/p&gt;


&lt;p&gt;Production Pattern&lt;/p&gt;
&lt;br&gt;
  &lt;p&gt;The search/lookup split mirrors how mature PIM systems already work internally. Akeneo PIM separates search (Elasticsearch-backed, fuzzy, ranked) from retrieval (MySQL-backed, exact, complete). UCP formalizing this at the protocol level means your integration layer can route each operation to the right backend without the commerce platform needing to support both in a single endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signals: Authorization Without Friction
&lt;/h2&gt;

&lt;p&gt;The most architecturally significant change in this release isn't a new capability — it's the &lt;code&gt;signals&lt;/code&gt; field added across checkout, cart, catalog search, and catalog lookup.&lt;/p&gt;

&lt;p&gt;Signals are platform attestations about the buyer context — things the platform has directly observed or verified through third parties. They use reverse-domain naming (&lt;code&gt;dev.ucp.buyer_ip&lt;/code&gt;, &lt;code&gt;dev.ucp.user_agent&lt;/code&gt;, &lt;code&gt;com.example.risk_score&lt;/code&gt;) and flow from platform to merchant on every request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Signals on a checkout request&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CheckoutWithSignals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;signals&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev.ucp.buyer_ip&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev.ucp.user_agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This replaces the deprecated &lt;code&gt;risk_signals&lt;/code&gt; field and represents a fundamental shift in how UCP handles trust. Instead of checkout-only risk data, signals flow through the &lt;em&gt;entire&lt;/em&gt; commerce lifecycle — from product search through purchase. A merchant can adjust search results, cart pricing, and checkout approval based on the same signal data.&lt;/p&gt;

&lt;p&gt;The reverse-domain naming is enforced via JSON Schema &lt;code&gt;propertyNames&lt;/code&gt;, meaning custom signal providers can extend the namespace without collision. Shopify can define &lt;code&gt;com.shopify.buyer_authenticated&lt;/code&gt;, Stripe can define &lt;code&gt;com.stripe.risk_level&lt;/code&gt;, and they'll never conflict.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-World Example:&lt;/strong&gt;&lt;br&gt;
  &lt;span&gt;In a SAP Commerce Cloud integration, fraud signals today come from the payment gateway at checkout time — too late to prevent catalog abuse. With UCP signals flowing through search and lookup, a merchant can throttle high-velocity product lookups from suspicious IPs before they even hit the cart. This is defense-in-depth at the protocol level, not bolted on as a payment-gateway afterthought.&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Changes That Actually Matter
&lt;/h2&gt;

&lt;p&gt;Five commits carry the &lt;code&gt;!&lt;/code&gt; breaking marker. Here's what requires migration work versus what you can absorb passively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Must Migrate: Signed Amounts on Totals
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;total.json&lt;/code&gt; now uses &lt;code&gt;signed_amount.json&lt;/code&gt; instead of unsigned &lt;code&gt;amount.json&lt;/code&gt;. This fixes a real schema bug — discounts needed to be both &lt;code&gt;&amp;gt;= 0&lt;/code&gt; (from &lt;code&gt;amount.json&lt;/code&gt;) and &lt;code&gt;&amp;lt; 0&lt;/code&gt; (from discount semantics), which was unsatisfiable.&lt;/p&gt;

&lt;p&gt;The fix consolidates sign constraints into &lt;code&gt;total.json&lt;/code&gt; as the single source of truth:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Total type&lt;/th&gt;
      &lt;th&gt;Sign constraint&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
&lt;code&gt;subtotal&lt;/code&gt;, &lt;code&gt;tax&lt;/code&gt;, &lt;code&gt;fee&lt;/code&gt;
&lt;/td&gt;
      &lt;td&gt;Must be &amp;gt;= 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;
&lt;code&gt;discount&lt;/code&gt;, &lt;code&gt;items_discount&lt;/code&gt;
&lt;/td&gt;
      &lt;td&gt;Must be &amp;lt; 0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Migration&lt;/strong&gt;: Update your Zod schemas and type definitions. If you were manually working around the unsigned amount constraint for discounts, you can now remove that workaround.&lt;/p&gt;

&lt;h3&gt;
  
  
  Must Migrate: Order Schema Overhaul
&lt;/h3&gt;

&lt;p&gt;Orders now have a 1:N relationship with checkouts (one order can span multiple checkouts), &lt;code&gt;currency&lt;/code&gt; is required, and adjustments use &lt;code&gt;totals&lt;/code&gt; instead of &lt;code&gt;amount&lt;/code&gt;. The &lt;code&gt;quantity.original&lt;/code&gt; field tracks pre-adjustment quantities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Migration&lt;/strong&gt;: Update your order processing pipeline. The &lt;code&gt;amount&lt;/code&gt; → &lt;code&gt;totals&lt;/code&gt; rename on adjustments will break deserializers. The &lt;code&gt;currency&lt;/code&gt; requirement may need a default value in your mapping layer if your upstream system doesn't always provide it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Must Migrate: Embedded Protocol Error Alignment
&lt;/h3&gt;

&lt;p&gt;Delegation error responses moved from JSON-RPC &lt;code&gt;error&lt;/code&gt; to &lt;code&gt;result&lt;/code&gt; using the standard &lt;code&gt;error_response&lt;/code&gt; envelope. This is a wire-format change that will break embedded checkout implementations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Migration&lt;/strong&gt;: Update your ECP (Embedded Checkout Protocol) error handling. Errors now come through &lt;code&gt;result&lt;/code&gt; with &lt;code&gt;ucp.status: "error"&lt;/code&gt; instead of the JSON-RPC error field. The upside: ECP errors can now use &lt;code&gt;recoverable&lt;/code&gt; severity, enabling retry logic that wasn't possible before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passive: Signals Replaces Risk Signals
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;risk_signals&lt;/code&gt; on checkout is deprecated but still accepted. Migrate to &lt;code&gt;signals&lt;/code&gt; when convenient — this is additive, not breaking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passive: Discount Extends Cart
&lt;/h3&gt;

&lt;p&gt;The discount extension's &lt;code&gt;extends&lt;/code&gt; field changed from a string to an array (&lt;code&gt;["dev.ucp.shopping.checkout", "dev.ucp.shopping.cart"]&lt;/code&gt;). If you're dynamically reading &lt;code&gt;extends&lt;/code&gt;, handle both string and array forms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Schema Explosion: 27 New Types
&lt;/h2&gt;

&lt;p&gt;This Universal Commerce Protocol release added 24 new shared type schemas on top of the 3 capability schemas. Here's the taxonomy:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Catalog Product Model&lt;/strong&gt; (12 schemas): &lt;code&gt;product&lt;/code&gt;, &lt;code&gt;variant&lt;/code&gt;, &lt;code&gt;product_option&lt;/code&gt;, &lt;code&gt;option_value&lt;/code&gt;, &lt;code&gt;detail_option_value&lt;/code&gt;, &lt;code&gt;selected_option&lt;/code&gt;, &lt;code&gt;category&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;media&lt;/code&gt;, &lt;code&gt;rating&lt;/code&gt;, &lt;code&gt;price&lt;/code&gt;, &lt;code&gt;price_range&lt;/code&gt;. This is a complete product data model — comparable to what you'd find in a PIM system's core schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search &amp;amp; Filter Types&lt;/strong&gt; (4 schemas): &lt;code&gt;search_filters&lt;/code&gt;, &lt;code&gt;price_filter&lt;/code&gt;, &lt;code&gt;pagination&lt;/code&gt;, &lt;code&gt;input_correlation&lt;/code&gt;. Cursor-based pagination with required &lt;code&gt;has_next_page&lt;/code&gt; and conditional &lt;code&gt;next_cursor&lt;/code&gt; — no more guessing whether there's another page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monetary Types&lt;/strong&gt; (3 schemas): &lt;code&gt;amount&lt;/code&gt;, &lt;code&gt;signed_amount&lt;/code&gt;, &lt;code&gt;totals&lt;/code&gt;. The &lt;code&gt;signed_amount&lt;/code&gt; type was the missing piece that enabled the totals fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt; (2 schemas): &lt;code&gt;error_code&lt;/code&gt;, &lt;code&gt;error_response&lt;/code&gt;. Standard error envelope with &lt;code&gt;ucp.status: "error"&lt;/code&gt; and &lt;code&gt;messages[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Types&lt;/strong&gt; (2 schemas): &lt;code&gt;signals&lt;/code&gt;, &lt;code&gt;reverse_domain_name&lt;/code&gt;. Foundation for the signals framework.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;variant.json&lt;/code&gt; schema deserves special attention. It carries &lt;code&gt;availability.status&lt;/code&gt; as an open vocabulary string (&lt;code&gt;in_stock&lt;/code&gt;, &lt;code&gt;backorder&lt;/code&gt;, &lt;code&gt;preorder&lt;/code&gt;, etc.) rather than a closed enum. This means platform adapters don't need to map proprietary availability states into a fixed set of values — they can pass them through and let the consumer decide what each status means. The &lt;a href="https://dev.to/rules#schema-drift-trap"&gt;Schema Drift Trap&lt;/a&gt; teaches us that closed enums in integration schemas are a maintenance burden — open vocabularies with well-known values are more resilient to upstream changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Integration Teams
&lt;/h2&gt;

&lt;h3&gt;
  
  
  If You're Building a UCP Platform Adapter
&lt;/h3&gt;

&lt;p&gt;Good news: the &lt;a href="https://github.com/OmnixHQ/ucp-js-sdk" rel="noopener noreferrer"&gt;ucp-js-sdk&lt;/a&gt; has already shipped v2.0.0 on npm with full support for the &lt;code&gt;v2026-04-08&lt;/code&gt; spec. All 27 new schemas are available as TypeScript types and Zod validators out of the box — no manual schema generation needed.&lt;/p&gt;

&lt;p&gt;The catalog model (&lt;code&gt;product&lt;/code&gt;, &lt;code&gt;variant&lt;/code&gt;, &lt;code&gt;option&lt;/code&gt;, &lt;code&gt;media&lt;/code&gt;, &lt;code&gt;rating&lt;/code&gt;) maps closely to standard commerce platform entities — but watch the &lt;code&gt;price&lt;/code&gt; type, which uses integer minor units per ISO 4217. If your upstream platform uses decimal amounts (most do), you need a conversion layer.&lt;/p&gt;

&lt;p&gt;The cart-to-checkout conversion is idempotent by spec. Your adapter must guarantee this — same &lt;code&gt;cart_id&lt;/code&gt; → same &lt;code&gt;checkout_id&lt;/code&gt;, always. Test this with concurrent requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You're Building on the Embedded Protocol
&lt;/h3&gt;

&lt;p&gt;The error response restructuring is your biggest migration item. All ECP delegation errors now use the standard &lt;code&gt;error_response&lt;/code&gt; envelope through &lt;code&gt;result&lt;/code&gt; instead of JSON-RPC &lt;code&gt;error&lt;/code&gt;. Update your error handling, but gain &lt;code&gt;recoverable&lt;/code&gt; severity for retry logic.&lt;/p&gt;

&lt;p&gt;New ECP capabilities: &lt;code&gt;ep.cart.*&lt;/code&gt; methods for cart management, &lt;code&gt;ec.auth&lt;/code&gt; / &lt;code&gt;ep.cart.auth&lt;/code&gt; for credential renewal during sessions. Plus &lt;code&gt;ec_color_scheme&lt;/code&gt; query parameter for light/dark/auto theming.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You're Consuming UCP via REST or MCP
&lt;/h3&gt;

&lt;p&gt;New endpoints and tools to integrate:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Capability&lt;/th&gt;
      &lt;th&gt;REST&lt;/th&gt;
      &lt;th&gt;MCP&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Cart&lt;/td&gt;
      &lt;td&gt;
&lt;code&gt;POST/GET/PUT /carts&lt;/code&gt;, &lt;code&gt;POST /carts/{id}/cancel&lt;/code&gt;
&lt;/td&gt;
      &lt;td&gt;
&lt;code&gt;create_cart&lt;/code&gt;, &lt;code&gt;get_cart&lt;/code&gt;, &lt;code&gt;update_cart&lt;/code&gt;, &lt;code&gt;cancel_cart&lt;/code&gt;
&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Catalog Search&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;POST /catalog/search&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;search_catalog&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Catalog Lookup&lt;/td&gt;
      &lt;td&gt;
&lt;code&gt;POST /catalog/lookup&lt;/code&gt;, &lt;code&gt;POST /catalog/product&lt;/code&gt;
&lt;/td&gt;
      &lt;td&gt;
&lt;code&gt;lookup_catalog&lt;/code&gt;, &lt;code&gt;get_product&lt;/code&gt;
&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Order (new)&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;GET /orders/{id}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;get_order&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Service Definition Cleanup
&lt;/h3&gt;

&lt;p&gt;The service definition files were renamed for clarity — &lt;code&gt;openapi.json&lt;/code&gt; → &lt;code&gt;rest.openapi.json&lt;/code&gt;, &lt;code&gt;openrpc.json&lt;/code&gt; → &lt;code&gt;mcp.openrpc.json&lt;/code&gt;, &lt;code&gt;embedded.json&lt;/code&gt; → &lt;code&gt;embedded.openrpc.json&lt;/code&gt;. If you're generating clients from these files, update your paths. The old filenames are gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Universal Commerce Protocol Schema Migration (do first)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Regenerate types from 27 new schema files&lt;/li&gt;
&lt;li&gt;[ ] Update &lt;code&gt;total&lt;/code&gt; handling for &lt;code&gt;signed_amount&lt;/code&gt; (discounts are negative)&lt;/li&gt;
&lt;li&gt;[ ] Rename &lt;code&gt;amount&lt;/code&gt; → &lt;code&gt;totals&lt;/code&gt; on order adjustments&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;currency&lt;/code&gt; as required field on Order&lt;/li&gt;
&lt;li&gt;[ ] Handle &lt;code&gt;extends&lt;/code&gt; as string or array on discount capability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New Capabilities (adopt incrementally)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Implement Cart CRUD operations&lt;/li&gt;
&lt;li&gt;[ ] Implement Catalog Search with cursor-based pagination&lt;/li&gt;
&lt;li&gt;[ ] Implement Catalog Lookup with batch correlation&lt;/li&gt;
&lt;li&gt;[ ] Wire cart-to-checkout conversion with idempotency guarantee&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;signals&lt;/code&gt; field to all outgoing requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Embedded Protocol (if applicable)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Migrate ECP error handling from JSON-RPC &lt;code&gt;error&lt;/code&gt; to &lt;code&gt;result&lt;/code&gt; envelope&lt;/li&gt;
&lt;li&gt;[ ] Implement &lt;code&gt;ep.cart.*&lt;/code&gt; methods&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;ec.auth&lt;/code&gt; / &lt;code&gt;ep.cart.auth&lt;/code&gt; reauth support&lt;/li&gt;
&lt;li&gt;[ ] Support &lt;code&gt;ec_color_scheme&lt;/code&gt; query parameter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Log all new capability requests with correlation IDs&lt;/li&gt;
&lt;li&gt;[ ] Track cart-to-checkout conversion rates&lt;/li&gt;
&lt;li&gt;[ ] Monitor catalog search latency by filter type&lt;/li&gt;
&lt;li&gt;[ ] Alert on signal feedback messages (code: &lt;code&gt;signal&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Integration Maestro Perspective
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The API Contract Rule&lt;/strong&gt;: The strength of an integration is determined by the precision of its contract — not the sophistication of its implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This UCP release demonstrates what happens when a protocol team takes schema governance seriously. Twenty-seven new schemas, five breaking changes — and every break has a clear migration path with sign constraints moved to a single source of truth, deprecated fields marked with transition annotations, and response envelopes unified across transports.&lt;/p&gt;

&lt;p&gt;The Universal Commerce Protocol's cart-checkout separation alone solves a problem I've battled in every commerce integration project: platforms that conflate "browsing" with "buying" force every downstream system to understand the implicit state machine. UCP makes it explicit. Cart is exploration. Checkout is commitment. The boundary is a protocol-level guarantee.&lt;/p&gt;

&lt;p&gt;For teams building agentic commerce, this release is the tipping point. Before April 2026, UCP handled checkout — which is valuable but incomplete. Now it covers discovery through purchase: search products, build a cart, convert to checkout, complete the order. The full lifecycle, with formal schemas at every step and signals flowing through every request for fraud prevention.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/rules#schema-drift-trap"&gt;Schema Drift Trap&lt;/a&gt; is the rule to watch here. Twenty-seven new schemas means twenty-seven new surfaces where your implementation can drift from the spec. Pin your SDK to the &lt;code&gt;v2026-04-08&lt;/code&gt; release. Run conformance tests on every deploy. Schema discipline now prevents production incidents later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related rules&lt;/strong&gt;: &lt;a href="https://dev.to/rules#api-contract-rule"&gt;The API Contract Rule&lt;/a&gt; · &lt;a href="https://dev.to/rules#schema-drift-trap"&gt;The Schema Drift Trap&lt;/a&gt; · &lt;a href="https://dev.to/rules#fallback-first"&gt;Fallback-First Design&lt;/a&gt; · &lt;a href="https://dev.to/rules#idempotency-mandate"&gt;The Idempotency Mandate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related articles&lt;/strong&gt;: &lt;a href="https://dev.to/articles/visa-vic-vs-ucp-agentic-commerce-architecture"&gt;Visa VIC vs UCP: Two Competing Visions for Agentic Commerce&lt;/a&gt; · &lt;a href="https://dev.to/articles/rest-vs-soap-vs-graphql-which-integration-protocol-wins-in-2025"&gt;REST vs SOAP vs GraphQL: What Wins for Integrations in 2025?&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ucp</category>
      <category>commerce</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Visa VIC vs UCP: Two Competing Visions for Agentic Commerce</title>
      <dc:creator>Artemii Karkusha</dc:creator>
      <pubDate>Fri, 10 Apr 2026 16:39:09 +0000</pubDate>
      <link>https://dev.to/integration-maestro/visa-vic-vs-ucp-two-competing-visions-for-agentic-commerce-1b8f</link>
      <guid>https://dev.to/integration-maestro/visa-vic-vs-ucp-two-competing-visions-for-agentic-commerce-1b8f</guid>
      <description>&lt;p&gt;Visa just published &lt;a href="https://github.com/visa/vic-reference-agent" rel="noopener noreferrer"&gt;vic-reference-agent&lt;/a&gt; — their open-source vision for how AI agents should buy things on behalf of humans. Five microservices, LangGraph orchestration, MCP tool integration, and a deep pipeline into Visa Token Service and Visa Intelligent Commerce APIs.&lt;/p&gt;

&lt;p&gt;I spent two days dissecting every file in that repository. Not because Visa needs my code review — but because when the world's largest payment network publishes their architectural opinion on agentic commerce, it reveals something important about where this space is heading.&lt;/p&gt;

&lt;p&gt;After building UCP (Universal Commerce Protocol) middleware that handles multi-merchant, multi-platform checkout for AI agents, I have a specific lens on what matters in this architecture. Here's the full analysis — what VIC gets right, where it falls short, and the fundamental design tension between card-network-centric and protocol-first approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  The VIC Architecture at a Glance
&lt;/h2&gt;

&lt;p&gt;Visa's reference agent is a 5-service system orchestrated via Docker Compose:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firlo98nvl8dy4nt4viyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firlo98nvl8dy4nt4viyn.png" alt="VIC Architecture — 5 microservices: Agent Frontend → Agent Backend → MCP Server → Merchant Backend, plus Merchant Frontend. Agent Backend connects to Visa VTS/VIC APIs" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Service&lt;/th&gt;
      &lt;th&gt;Stack&lt;/th&gt;
      &lt;th&gt;Role&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Agent Frontend&lt;/td&gt;
      &lt;td&gt;React 19, TypeScript, Vite&lt;/td&gt;
      &lt;td&gt;Shopping agent UI + card management&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Agent Backend&lt;/td&gt;
      &lt;td&gt;FastAPI, LangGraph, Python 3.12&lt;/td&gt;
      &lt;td&gt;AI agent orchestration + Visa API integration&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Merchant MCP&lt;/td&gt;
      &lt;td&gt;Express, @modelcontextprotocol/sdk&lt;/td&gt;
      &lt;td&gt;MCP tool server bridging agent to merchant&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Merchant Backend&lt;/td&gt;
      &lt;td&gt;FastAPI, SQLAlchemy, SQLite&lt;/td&gt;
      &lt;td&gt;Product catalog, cart, orders&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Merchant Frontend&lt;/td&gt;
      &lt;td&gt;React, JSX, Vite&lt;/td&gt;
      &lt;td&gt;Traditional merchant storefront&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The tech choices are solid for a reference implementation. FastAPI for the Python services, LangGraph for stateful agent orchestration, and the official MCP SDK with Streamable HTTP transport. Nothing exotic.&lt;/p&gt;

&lt;p&gt;But the architecture reveals something deeper about Visa's mental model: &lt;strong&gt;the agent is a Visa customer, not a merchant customer&lt;/strong&gt;. The entire system is designed around Visa's token lifecycle, not around merchant flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  What VIC Gets Right
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Payment Credential Security Is Best-in-Class
&lt;/h3&gt;

&lt;p&gt;This is where VIC genuinely shines. The payment credential flow is the most sophisticated I've seen in any agentic commerce implementation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmq888trz7z362lxknby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmq888trz7z362lxknby.png" alt="VIC Payment Credential Flow — PAN enrollment through VTS token provisioning, VIC enrollment, intent creation, credential retrieval, and transaction confirmation" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The credential never touches the AI agent in plaintext. Here's the actual flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User enrolls their card PAN into Visa Token Service (encrypted with JWE)&lt;/li&gt;
&lt;li&gt;VTS provisions a token with &lt;code&gt;presentationType: ["AI_AGENT"]&lt;/code&gt; — a new token type specifically for agent commerce&lt;/li&gt;
&lt;li&gt;The token gets enrolled in VIC (Visa Intelligent Commerce)&lt;/li&gt;
&lt;li&gt;At checkout, VIC creates an &lt;em&gt;intent&lt;/em&gt; with FIDO assurance data from the user's passkey&lt;/li&gt;
&lt;li&gt;VIC retrieves tokenized credentials — a dynamic card number, expiry, and cryptographic CVV&lt;/li&gt;
&lt;li&gt;These credentials flow through MCP elicitation to the merchant&lt;/li&gt;
&lt;li&gt;After the merchant processes payment, VIC confirms the transaction status&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The security layers are serious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Message Level Encryption (MLE)&lt;/strong&gt;: RSA-OAEP-256 + A256GCM (JWE) for all VIC API calls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Field-level encryption&lt;/strong&gt;: A256GCMKW for sensitive fields like PAN and risk data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HMAC-SHA256 request signing&lt;/strong&gt;: Every API call gets an &lt;code&gt;x-pay-token&lt;/code&gt; header&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FIDO2/WebAuthn passkeys&lt;/strong&gt;: Biometric step-up for payment authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-World Example:&lt;/strong&gt;&lt;br&gt;
  &lt;span&gt;The &lt;code&gt;AI_AGENT&lt;/code&gt; token presentation type is new. Traditional e-commerce uses &lt;code&gt;E_COMMERCE&lt;/code&gt;. By creating a distinct type, Visa can apply different risk scoring, different liability rules, and different fraud models specifically for agent-initiated transactions. This is a smart regulatory play — it gives card networks a way to treat agent purchases differently from human-initiated ones without breaking existing payment rails.&lt;/span&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. MCP Elicitation Pattern Is Elegant
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;checkout_cart&lt;/code&gt; MCP tool uses &lt;code&gt;server.elicitInput()&lt;/code&gt; to request payment details at checkout time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Merchant MCP server — checkout tool&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;elicitInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment information required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;requestedSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;card_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Card Number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;expiry_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Expiry Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;cvv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CVV&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card_number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;expiry_date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cvv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent backend responds to this elicitation via a callback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Agent backend — elicitation handler
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_elicitation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ElicitationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;current_credentials&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ElicitationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;decline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a genuinely good pattern. The merchant doesn't know where the credentials come from — it just asks. The agent doesn't expose credentials until the merchant specifically requests them during a checkout operation. Clean separation of concerns at the protocol level.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Intent-Mandate-Transaction Model
&lt;/h3&gt;

&lt;p&gt;VIC introduces a three-level hierarchy for purchase authorization:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Concept&lt;/th&gt;
      &lt;th&gt;Purpose&lt;/th&gt;
      &lt;th&gt;Lifecycle&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Intent&lt;/td&gt;
      &lt;td&gt;What the buyer wants to buy&lt;/td&gt;
      &lt;td&gt;Created per checkout session&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mandate&lt;/td&gt;
      &lt;td&gt;Spending limit + constraints + time window&lt;/td&gt;
      &lt;td&gt;Bound to an intent, has &lt;code&gt;effective_until_time&lt;/code&gt;
&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Transaction&lt;/td&gt;
      &lt;td&gt;Actual charge against a mandate&lt;/td&gt;
      &lt;td&gt;SUCCESS or FAILURE, confirmed back to VIC&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This maps well to real-world agent scenarios. An autonomous agent might have a mandate to "spend up to $500/month on office supplies" — the intent is each purchase, the mandate is the budget constraint, and transactions are individual charges.&lt;/p&gt;

&lt;p&gt;What's interesting is that UCP arrived at a remarkably similar abstraction independently — the &lt;strong&gt;AP2 Mandates Extension&lt;/strong&gt;. UCP uses Verifiable Digital Credentials (VDCs) to formalize three distinct mandate types:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;UCP Mandate&lt;/th&gt;
      &lt;th&gt;Purpose&lt;/th&gt;
      &lt;th&gt;Scenario&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Intent Mandate&lt;/td&gt;
      &lt;td&gt;Grants the agent authority to purchase within defined constraints (budget, time window, categories)&lt;/td&gt;
      &lt;td&gt;Human-not-present: autonomous agent shopping&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cart Mandate&lt;/td&gt;
      &lt;td&gt;User's cryptographic signature on a specific cart — exact items and price, non-repudiable&lt;/td&gt;
      &lt;td&gt;Human-present: user reviews and approves&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Mandate&lt;/td&gt;
      &lt;td&gt;Signals AI agent involvement and user presence status to payment networks and issuers&lt;/td&gt;
      &lt;td&gt;Shared with payment rails for risk assessment&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The key difference: VIC's mandate model is &lt;strong&gt;payment-rail-centric&lt;/strong&gt; — the mandate lives inside Visa's infrastructure and is enforced by VIC. UCP's mandates are &lt;strong&gt;cryptographic and portable&lt;/strong&gt; — they're signed VDCs that travel with the transaction and can be verified by any party in the chain (merchant, payment processor, issuer) regardless of the specific payment network.&lt;/p&gt;

&lt;p&gt;UCP also makes a critical architectural distinction that VIC doesn't: &lt;strong&gt;human-present vs human-not-present&lt;/strong&gt; scenarios. The Intent Mandate grants an agent autonomous spending authority with guardrails. The Cart Mandate requires the user's explicit, cryptographic approval of a specific cart. VIC's model conflates these two scenarios into a single intent — you always need a FIDO passkey assertion, even for autonomous agent purchases, which undermines the "autonomous" part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-World Example:&lt;/strong&gt;&lt;br&gt;
  &lt;span&gt;Consider a corporate procurement agent authorized to buy office supplies up to $500/month. With UCP's Intent Mandate, the agent operates autonomously within those constraints — no human step-up needed for each purchase. With VIC, every purchase requires a FIDO passkey assertion, meaning someone has to physically authenticate with their device. That's secure, but it's not autonomous — it's just adding an AI layer on top of human-initiated payments.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The convergence on mandate abstractions from both a card network (Visa) and an open protocol (UCP) validates that this is the right architectural pattern for agentic commerce. But the implementation philosophy diverges: centralized enforcement (VIC) vs. portable, cryptographic proof (UCP).&lt;/p&gt;

&lt;h2&gt;
  
  
  Where VIC Falls Short
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Single Merchant, Single Network, Zero Extensibility
&lt;/h3&gt;

&lt;p&gt;Here's the fundamental problem: VIC is hardcoded to one merchant and one payment network.&lt;/p&gt;

&lt;p&gt;The MCP server connects to exactly one merchant backend at &lt;code&gt;http://reference-merchant-backend:8001&lt;/code&gt;. There's no adapter pattern, no registry, no routing. If an AI agent needs to comparison-shop across multiple merchants — which is literally the core value proposition of agentic commerce — the entire MCP server needs to be duplicated.&lt;/p&gt;

&lt;p&gt;Compare this to a protocol-first approach where a single gateway handles multiple merchants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// UCP approach — adapter pattern with tenant isolation&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PlatformAdapter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;searchProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SearchQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;createCart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;CartItem&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Cart&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;placeOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// One gateway, N merchants via adapter registry&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;adapterRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tenant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platformType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;searchProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VIC's design means each merchant needs its own MCP server, its own tool definitions, its own connection management. In production, this creates an N-microservices problem for N merchants.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Global Mutable State Kills Concurrency
&lt;/h3&gt;

&lt;p&gt;This one surprised me in a Visa reference implementation. The agent service uses module-level globals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# From reference-agent-backend/src/services/agent.py
&lt;/span&gt;&lt;span class="n"&gt;current_thread_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="n"&gt;current_credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two users checking out simultaneously would corrupt each other's credentials. This is a demo-level pattern that would be a critical security vulnerability in production. Session isolation isn't optional in payment systems — it's the bare minimum.&lt;/p&gt;


&lt;p&gt;Production Pattern&lt;/p&gt;
&lt;br&gt;
  &lt;p&gt;Payment credentials must be scoped to a session, never stored in global state. Use Redis-backed session stores with tenant isolation, TTL-based expiration, and cryptographic session IDs. The credential retrieval and the checkout completion must happen within the same session boundary — ideally with an idempotency key to prevent double-charge on retry.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. No Formal Schema Governance
&lt;/h3&gt;

&lt;p&gt;VIC has no published schema, no JSON Schema files, no OpenAPI specification, no automated compliance checks. The data contracts are implicit in Python Pydantic models and TypeScript Zod schemas within the MCP tool definitions.&lt;/p&gt;

&lt;p&gt;This matters because schema drift is one of the most common failure modes in integrations. When Visa updates their VTS or VIC APIs, there's no automated way to detect breaking changes in this reference implementation. No conformance test suite, no gap analysis, no version tracking.&lt;/p&gt;

&lt;p&gt;For comparison, production-grade protocol implementations track schema coverage explicitly — every field, every constraint, every validation rule mapped to a spec version. The &lt;a href="https://dev.to/rules#schema-drift-trap"&gt;Schema Drift Trap&lt;/a&gt; catches teams who skip this step: what works today breaks silently when the upstream API evolves.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Visa-Only Payment Rail
&lt;/h3&gt;

&lt;p&gt;VIC only supports Visa cards. The entire system — VTS token provisioning, VIC enrollment, intent creation, credential retrieval — is built on Visa-proprietary APIs at &lt;code&gt;cert.api.visa.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the real world, merchants accept Mastercard, Amex, PayPal, Apple Pay, buy-now-pay-later, crypto, and bank transfers. An agentic commerce protocol that only works with one card network is like an integration middleware that only supports one ERP — technically correct but architecturally limited.&lt;/p&gt;

&lt;p&gt;Open protocols handle this differently by abstracting the payment method behind a handler interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PaymentHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redirect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;other&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Payment network is a detail, not a constraint&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSupportedPaymentMethods&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Returns: Visa, Mastercard, PayPal, Klarna, etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Architecture Comparison
&lt;/h2&gt;

&lt;p&gt;Here's the systematic comparison across every dimension that matters for production agentic commerce:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Dimension&lt;/th&gt;
      &lt;th&gt;Visa VIC&lt;/th&gt;
      &lt;th&gt;UCP / Open Protocol&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Nature&lt;/td&gt;
      &lt;td&gt;Reference demo&lt;/td&gt;
      &lt;td&gt;Production gateway framework&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Protocol support&lt;/td&gt;
      &lt;td&gt;MCP only&lt;/td&gt;
      &lt;td&gt;REST + MCP + A2A + Embedded&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment networks&lt;/td&gt;
      &lt;td&gt;Visa only&lt;/td&gt;
      &lt;td&gt;Network-agnostic (adapter-driven)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Merchant integration&lt;/td&gt;
      &lt;td&gt;Single hardcoded merchant&lt;/td&gt;
      &lt;td&gt;Multi-tenant, multi-platform&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Adapter pattern&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;First-class PlatformAdapter interface&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Schema governance&lt;/td&gt;
      &lt;td&gt;Implicit (Pydantic/Zod)&lt;/td&gt;
      &lt;td&gt;SDK-derived schemas, 150+ checks&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Session management&lt;/td&gt;
      &lt;td&gt;In-memory + global state&lt;/td&gt;
      &lt;td&gt;Redis-backed, tenant-isolated, idempotent&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Auth model&lt;/td&gt;
      &lt;td&gt;Visa API keys + HMAC + MLE + FIDO2&lt;/td&gt;
      &lt;td&gt;JWS request signing + tenant JWT&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Agent orchestration&lt;/td&gt;
      &lt;td&gt;LangGraph baked in&lt;/td&gt;
      &lt;td&gt;Agent-agnostic (any HTTP client)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Testing&lt;/td&gt;
      &lt;td&gt;3 unit tests&lt;/td&gt;
      &lt;td&gt;222+ integration tests, E2E per adapter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment depth&lt;/td&gt;
      &lt;td&gt;Deep (VTS + VIC + FIDO)&lt;/td&gt;
      &lt;td&gt;Abstract (payment handler interface)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mandate model&lt;/td&gt;
      &lt;td&gt;Intent → Mandate → Transaction (VIC-enforced)&lt;/td&gt;
      &lt;td&gt;3 VDC types: Intent / Cart / Payment (cryptographic, portable)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Human-not-present&lt;/td&gt;
      &lt;td&gt;Requires FIDO passkey for every purchase&lt;/td&gt;
      &lt;td&gt;Intent Mandate grants autonomous authority&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Flexibility Question
&lt;/h2&gt;

&lt;p&gt;Is VIC more flexible than open protocols? &lt;strong&gt;No — and it's not trying to be.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VIC optimizes for a different axis: &lt;strong&gt;payment security depth&lt;/strong&gt; over &lt;strong&gt;integration breadth&lt;/strong&gt;. And within that axis, it's genuinely impressive. The token lifecycle management, the MLE encryption, the FIDO2 passkey integration — this is how a card network with decades of fraud prevention experience thinks about agent payments.&lt;/p&gt;

&lt;p&gt;But flexibility in agentic commerce means:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Flexibility axis&lt;/th&gt;
      &lt;th&gt;VIC&lt;/th&gt;
      &lt;th&gt;Open Protocol&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Add a new merchant&lt;/td&gt;
      &lt;td&gt;Duplicate MCP server&lt;/td&gt;
      &lt;td&gt;Register adapter + tenant&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Support non-Visa payments&lt;/td&gt;
      &lt;td&gt;Impossible&lt;/td&gt;
      &lt;td&gt;Add payment handler&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Switch LLM framework&lt;/td&gt;
      &lt;td&gt;Rewrite agent.py&lt;/td&gt;
      &lt;td&gt;Any HTTP client works&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Deploy without Docker&lt;/td&gt;
      &lt;td&gt;Difficult (5-service coupling)&lt;/td&gt;
      &lt;td&gt;Single deployable + Redis&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Add new protocol binding&lt;/td&gt;
      &lt;td&gt;Not supported&lt;/td&gt;
      &lt;td&gt;Add route handler&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What Open Protocols Can Learn from VIC
&lt;/h2&gt;

&lt;p&gt;Despite VIC being less flexible, it has patterns worth adopting:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. MCP Elicitation for Credential Transfer
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;elicitInput()&lt;/code&gt; pattern is protocol-level elegance. Instead of passing payment tokens in the request body, the merchant &lt;em&gt;requests&lt;/em&gt; credentials at the exact moment they're needed. This creates a just-in-time credential flow that minimizes the window of credential exposure.&lt;/p&gt;

&lt;p&gt;Open protocols that support MCP bindings should adopt this for checkout completion — it's strictly better than embedding payment tokens in a complete-session POST body.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Token Presentation Types
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;AI_AGENT&lt;/code&gt; token type is forward-thinking. As regulators begin distinguishing between human-initiated and agent-initiated purchases, having distinct token types allows different risk scoring, liability rules, and fraud models per presentation type.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. API Log Transparency
&lt;/h3&gt;

&lt;p&gt;VIC logs every Visa API call and displays the full request/response in a dedicated UI panel. This follows the &lt;a href="https://dev.to/rules#observability-rule"&gt;Observability Rule&lt;/a&gt; — if you can't see the data flowing through your integration, you can't debug it.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Convergent Evolution on Mandates
&lt;/h3&gt;

&lt;p&gt;Both VIC and UCP independently arrived at mandate-based authorization for agent spending. This convergent evolution validates the pattern — any agentic commerce system needs a way to express spending authority with constraints. Where VIC adds value is in demonstrating how card networks can consume these mandates for risk scoring. The Payment Mandate concept (signaling agent involvement to issuers) is especially relevant as regulators begin distinguishing between human-initiated and agent-initiated purchases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fundamental Design Tension
&lt;/h2&gt;

&lt;p&gt;Here's what this comparison really reveals: &lt;strong&gt;card networks and open protocols are optimizing for different stakeholders.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Visa's VIC optimizes for the &lt;strong&gt;card network&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every transaction flows through Visa rails&lt;/li&gt;
&lt;li&gt;Token lifecycle is managed by Visa&lt;/li&gt;
&lt;li&gt;Risk scoring happens at Visa's layer&lt;/li&gt;
&lt;li&gt;The merchant sees tokenized credentials, not raw PANs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open protocols optimize for the &lt;strong&gt;merchant ecosystem&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any payment network can participate&lt;/li&gt;
&lt;li&gt;Merchants keep their existing platform (Magento, Shopware, Shopify)&lt;/li&gt;
&lt;li&gt;The protocol doesn't mandate a specific payment rail&lt;/li&gt;
&lt;li&gt;Multi-tenant by design — one gateway serves many merchants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither approach is wrong. But they serve different masters. A merchant who already accepts multiple payment methods won't lock into a Visa-only agent flow. A bank that wants maximum control over the payment security stack won't trust an open protocol's payment handler abstraction.&lt;/p&gt;


&lt;p&gt;Production Pattern&lt;/p&gt;
&lt;br&gt;
  &lt;p&gt;The winning architecture in production is probably a hybrid: an open protocol layer for merchant integration and multi-network support, with card-network-specific modules (like VIC) plugged in as payment handlers. VIC becomes an adapter, not the entire system. The protocol handles discovery, cart, and session management. The card network handles token lifecycle, credential retrieval, and transaction confirmation. Each layer does what it's best at.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Agentic Commerce Landscape
&lt;/h2&gt;

&lt;p&gt;VIC and UCP aren't the only players. The agentic commerce space is moving fast, with major infrastructure bets from every layer of the stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google's A2A protocol&lt;/strong&gt; (now under the Linux Foundation with 50+ partners) handles agent-to-agent communication -- discovery via Agent Cards, task delegation, and real-time status updates. It's transport-agnostic (JSON-RPC, gRPC, REST bindings) and doesn't prescribe a commerce model. A2A operates at a different layer than UCP: it's how agents find and delegate work to each other, not how they buy things.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic's MCP&lt;/strong&gt; (Model Context Protocol) connects AI models to external systems via tools, resources, and prompts. VIC uses MCP as its agent-to-merchant bridge. UCP defines its own protocol with REST as the primary transport today, with MCP as a potential future transport binding. MCP and UCP operate at different layers -- MCP is a model-to-system integration protocol; UCP is a commerce-domain protocol that could use MCP as one of its transports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shopify&lt;/strong&gt; has gone all-in on agentic commerce -- far beyond wrapping existing APIs. They built entirely new infrastructure: a &lt;strong&gt;Catalog API&lt;/strong&gt; for cross-merchant product search (billions of products, all Shopify stores), a &lt;strong&gt;Universal Cart&lt;/strong&gt; that holds items from multiple merchants simultaneously, a &lt;strong&gt;Checkout Kit&lt;/strong&gt; for embedded checkout in agent UIs, and multiple &lt;strong&gt;MCP servers&lt;/strong&gt; (Catalog MCP, Storefront MCP). Shopify also co-developed UCP with Google as an open standard, with Walmart, Target, Etsy, and 20+ other retailers endorsing it. Their Agentic Storefronts feature makes all Shopify merchants discoverable in ChatGPT, Copilot, and Gemini by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe&lt;/strong&gt; launched the &lt;strong&gt;Agentic Commerce Suite&lt;/strong&gt; with purpose-built payment primitives: &lt;strong&gt;Shared Payment Tokens (SPTs)&lt;/strong&gt; that scope a buyer's payment method to a specific seller, amount, and time window; &lt;strong&gt;Agentic Network Tokens&lt;/strong&gt; issued by Visa/Mastercard for agent-initiated payments; and the &lt;strong&gt;Agentic Commerce Protocol (ACP)&lt;/strong&gt; co-developed with OpenAI. They also ship an official MCP server at &lt;code&gt;mcp.stripe.com&lt;/code&gt; and the &lt;code&gt;@stripe/agent-toolkit&lt;/code&gt; for LangChain, CrewAI, and Vercel AI SDK integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adyen&lt;/strong&gt; is building a &lt;strong&gt;Universal Token Vault&lt;/strong&gt; -- a bank-grade, provider-agnostic tokenization system for agent transactions with portable tokens. They're collaborating on Google's AP2 (Agent Payments Protocol) and Visa's Trusted Agent Protocol, with a merchant-first framework that keeps merchants in control of tokenization strategies and payment routing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Omnix&lt;/strong&gt; takes a different angle entirely: source-available middleware that connects existing stores (Magento, Shopware, Shopify) to AI agents through UCP without replatforming. Instead of building new storefronts, &lt;a href="https://github.com/omnixhq/omnix-gateway" rel="noopener noreferrer"&gt;Omnix Gateway&lt;/a&gt; translates existing platform APIs into UCP -- one integration, any agent. Paired with &lt;code&gt;@omnixhq/ucp-js-sdk&lt;/code&gt; for runtime-validated schemas and &lt;code&gt;@omnixhq/ucp-client&lt;/code&gt; for capability-aware UCP consumption, it's the adapter layer that makes UCP practical for merchants who aren't Shopify-native.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://dev.to/rules#api-contract-rule"&gt;API Contract Rule&lt;/a&gt; applies here: in a fragmenting ecosystem, the implementations that survive are the ones with formal, versioned, machine-readable contracts. VIC has strong security contracts but weak interface contracts. Open protocols tend to have the inverse. The ones that get both right will win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Checklist
&lt;/h2&gt;

&lt;p&gt;If you're building agentic commerce infrastructure, here's what to evaluate:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protocol Layer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Multi-protocol support (REST for legacy, MCP for AI agents, A2A for agent-to-agent)&lt;/li&gt;
&lt;li&gt;[ ] Formal schema governance with versioned specs&lt;/li&gt;
&lt;li&gt;[ ] Automated conformance testing against the spec&lt;/li&gt;
&lt;li&gt;[ ] Agent-agnostic design (no LLM framework lock-in)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Commerce Layer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Multi-merchant support via adapter pattern&lt;/li&gt;
&lt;li&gt;[ ] Multi-tenant session isolation with idempotency&lt;/li&gt;
&lt;li&gt;[ ] Payment network abstraction (not locked to one rail)&lt;/li&gt;
&lt;li&gt;[ ] Full checkout lifecycle: search → cart → totals → shipping → payment → order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Payment Security&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Tokenized credentials (never raw PANs in agent context)&lt;/li&gt;
&lt;li&gt;[ ] Just-in-time credential retrieval (elicitation pattern or equivalent)&lt;/li&gt;
&lt;li&gt;[ ] Step-up authentication for high-value purchases&lt;/li&gt;
&lt;li&gt;[ ] Transaction confirmation loop back to the payment provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Full request/response logging for all payment API calls&lt;/li&gt;
&lt;li&gt;[ ] Agent decision audit trail&lt;/li&gt;
&lt;li&gt;[ ] Credential access logging with session correlation&lt;/li&gt;
&lt;li&gt;[ ] Alerting on checkout abandonment and payment failures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Integration Maestro Perspective
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The API Contract Rule&lt;/strong&gt;: The strength of an integration is determined by the precision of its contract — not the sophistication of its implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Visa's VIC reference agent is an impressive demonstration of payment security engineering. The token lifecycle, the MLE encryption, the FIDO2 passkeys — this is what 60 years of payment infrastructure experience looks like when applied to AI agents.&lt;/p&gt;

&lt;p&gt;But a payment security demo is not a commerce protocol. Production agentic commerce needs multi-merchant discovery, multi-network payments, formal schema governance, and session isolation that doesn't rely on global Python variables.&lt;/p&gt;

&lt;p&gt;The right mental model: VIC is a &lt;strong&gt;payment handler adapter&lt;/strong&gt; for an open commerce protocol — not a replacement for one. The future architecture has an open protocol layer (UCP, or something like it) handling the commerce lifecycle, with Visa's VIC, Mastercard's equivalent, and every other payment network plugged in as adapters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related rules&lt;/strong&gt;: &lt;a href="https://dev.to/rules#api-contract-rule"&gt;The API Contract Rule&lt;/a&gt; · &lt;a href="https://dev.to/rules#schema-drift-trap"&gt;The Schema Drift Trap&lt;/a&gt; · &lt;a href="https://dev.to/rules#observability-rule"&gt;The Observability Rule&lt;/a&gt; · &lt;a href="https://dev.to/rules#fallback-first"&gt;Fallback-First Design&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related articles&lt;/strong&gt;: &lt;a href="https://dev.to/articles/rest-vs-soap-vs-graphql-which-integration-protocol-wins-in-2025"&gt;REST vs SOAP vs GraphQL: What Wins for Integrations in 2025?&lt;/a&gt; · &lt;a href="https://dev.to/articles/polling-vs-webhooks-integration-trigger-strategy"&gt;Polling vs Webhooks: How to Choose the Right Integration Trigger&lt;/a&gt;&lt;/p&gt;

</description>
      <category>commerce</category>
      <category>ai</category>
      <category>news</category>
      <category>agents</category>
    </item>
    <item>
      <title>A 2 AM Integration Failure That Changed How I Design Systems Forever</title>
      <dc:creator>Artemii Karkusha</dc:creator>
      <pubDate>Tue, 07 Apr 2026 12:51:02 +0000</pubDate>
      <link>https://dev.to/integration-maestro/a-2-am-integration-failure-that-changed-how-i-design-systems-forever-275p</link>
      <guid>https://dev.to/integration-maestro/a-2-am-integration-failure-that-changed-how-i-design-systems-forever-275p</guid>
      <description>&lt;p&gt;&lt;strong&gt;Black Friday doesn't break systems.&lt;/strong&gt;&lt;br&gt;
It reveals them.&lt;/p&gt;

&lt;p&gt;This story is about one of those moments — not because everything went down, but because it almost did. And because it permanently changed how I design enterprise architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Night Everything Converged
&lt;/h2&gt;

&lt;p&gt;It was Black Friday season — after weeks of preparation.&lt;/p&gt;

&lt;p&gt;There had been planning. There had been load testing. There had even been a strict code freeze in place more than a month before Black Friday.&lt;/p&gt;

&lt;p&gt;From a customer traffic perspective, the system was considered ready.&lt;/p&gt;

&lt;p&gt;What hadn't been tested — at least not deeply enough — was &lt;strong&gt;integration behavior under real customer-driven change&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And now it was live traffic.&lt;/p&gt;

&lt;p&gt;Product attributes were changing constantly. Prices were being updated. Content adjustments were rolling in.&lt;/p&gt;

&lt;p&gt;At the same time, data was flowing from every direction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PIM&lt;/li&gt;
&lt;li&gt;ERP&lt;/li&gt;
&lt;li&gt;OMS&lt;/li&gt;
&lt;li&gt;Commerce systems&lt;/li&gt;
&lt;li&gt;Cloud infrastructure&lt;/li&gt;
&lt;li&gt;External search engines&lt;/li&gt;
&lt;li&gt;Product feeds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eighteen websites. Dozens of dependent systems. All expected to stay in exactly the same state.&lt;/p&gt;

&lt;p&gt;In this architecture, one system was responsible for keeping everything consistent.&lt;/p&gt;

&lt;p&gt;And that system lived inside the eCommerce platform.&lt;/p&gt;

&lt;p&gt;On normal days, this platform processed &lt;strong&gt;250+ million events&lt;/strong&gt; coming from external systems. During Black Friday, that number exploded.&lt;/p&gt;

&lt;p&gt;One attribute change could trigger updates across &lt;strong&gt;1.5 million products&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storefront&lt;/li&gt;
&lt;li&gt;PLP / PDP&lt;/li&gt;
&lt;li&gt;Search&lt;/li&gt;
&lt;li&gt;Feeds&lt;/li&gt;
&lt;li&gt;External discovery platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the full update cycle took &lt;strong&gt;4 hours and 27 minutes&lt;/strong&gt;, it wasn't "just latency."&lt;/p&gt;

&lt;p&gt;It meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prices appearing late&lt;/li&gt;
&lt;li&gt;Products missing from search&lt;/li&gt;
&lt;li&gt;Feeds out of sync&lt;/li&gt;
&lt;li&gt;Customers seeing different realities across channels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With traffic peaks of &lt;strong&gt;75,000 users per minute&lt;/strong&gt;, even a &lt;strong&gt;1% inconsistency&lt;/strong&gt; scaled into millions in lost revenue across the ecosystem.&lt;/p&gt;

&lt;p&gt;At that moment, this stopped being a performance problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It became a systemic risk.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Was on the Line — Personally
&lt;/h2&gt;

&lt;p&gt;I wasn't the person who originally designed this system.&lt;/p&gt;

&lt;p&gt;But I was part of the core team as a Technical Architect — which meant that when things started to bend under pressure, I was expected to deliver a solution within hours or days, not weeks.&lt;/p&gt;

&lt;p&gt;I always feel accountable, even when I'm technically not.&lt;/p&gt;

&lt;p&gt;Because that's the responsibility of a good Solution Architect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notice problems before others see them&lt;/li&gt;
&lt;li&gt;Explain why they will fail&lt;/li&gt;
&lt;li&gt;Show how to fix them&lt;/li&gt;
&lt;li&gt;Clearly communicate the business consequences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even when clients don't want to hear it. Even when managers think it's too risky to change. Even when owners prefer short-term stability over structural fixes.&lt;/p&gt;

&lt;p&gt;You still have to say it.&lt;/p&gt;

&lt;p&gt;Because if you see the failure coming and stay silent — the outcome is worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architectural Mistake That Made This Inevitable
&lt;/h2&gt;

&lt;p&gt;There were many issues. But one mistake stood above all others:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The eCommerce platform was acting as an integration bridge between enterprise systems.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That decision is often ignored — especially because it &lt;em&gt;works&lt;/em&gt; at first.&lt;/p&gt;

&lt;p&gt;For small systems. For medium complexity. For early growth stages.&lt;/p&gt;

&lt;p&gt;But at enterprise scale? It creates a dangerous situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every external change puts pressure on eCommerce&lt;/li&gt;
&lt;li&gt;Every sync increases coupling&lt;/li&gt;
&lt;li&gt;Every retry amplifies load&lt;/li&gt;
&lt;li&gt;Every small update becomes a system-wide event&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The platform designed to serve customers becomes responsible for orchestrating the enterprise.&lt;/p&gt;

&lt;p&gt;And under peak load, that responsibility becomes unbearable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix — And the Real Lesson
&lt;/h2&gt;

&lt;p&gt;We redesigned how updates were handled.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removed unnecessary fan-out&lt;/li&gt;
&lt;li&gt;Changed how feeds were indexed&lt;/li&gt;
&lt;li&gt;Stopped treating all updates as equal&lt;/li&gt;
&lt;li&gt;Reduced full queue processing from &lt;strong&gt;4+ hours to 26 minutes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the deeper fix wasn't technical. &lt;strong&gt;It was architectural.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rule I Follow Since That Night
&lt;/h2&gt;

&lt;p&gt;Since that Black Friday, I never design eCommerce systems that act as integration bridges in an enterprise.&lt;/p&gt;

&lt;p&gt;Even if it works today. Even if it's cheaper now. Even if it feels simpler.&lt;/p&gt;

&lt;p&gt;Because slow sync doesn't just delay data — it silently erodes revenue, trust, and stability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Black Friday didn't change how I design systems.&lt;/p&gt;

&lt;p&gt;It confirmed what enterprise scale demands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear ownership boundaries&lt;/li&gt;
&lt;li&gt;Decoupled integrations&lt;/li&gt;
&lt;li&gt;eCommerce focused on serving customers — not coordinating the enterprise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cost of learning this lesson late is far higher than the cost of designing it right from the start.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write about integration architecture, production failures, and patterns that actually hold up at scale → &lt;a href="https://integration-maestro.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=devto-article" rel="noopener noreferrer"&gt;integration-maestro.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>backend</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
