UCP Checker
Guides · Retail

How UCP works: a real agent buys flowers, step by step

· 21 October 2026 · 10 min read

The Universal Commerce Protocol is easiest to understand by watching it work. So we sent a real AI agent to buy a bouquet of roses from a UCP store and recorded every call it made: how it found the store, what the two sides agreed to use, how the checkout moved from one state to the next, what happened when the card was declined, and how the buyer linked their account to see the order afterwards.

Everything below is from real runs on the 2026-08-25 release of UCP, on test stores built to the spec. The requests and responses are copied from the recordings, trimmed only where noted.

What is UCP?

UCP (the Universal Commerce Protocol) is an open standard that lets an AI agent shop at a store through the store's own APIs: it discovers what the store supports, searches its catalogue, builds a checkout, pays and follows the order, without scraping web pages. A store publishes a UCP profile at /.well-known/ucp; an agent publishes one too; and every request carries the agent's profile so the store knows who is calling and what it can do.

The setup for these runs:

  • The store: Northlight Flowers, three copies of one test store. flowers.ucpsandbox.com takes payment, flowers-decline.ucpsandbox.com declines every card, and flowers-account.ucpsandbox.com offers account linking.
  • The agent: UCP Playground's agent, running Gemini 3.6 Flash, reaching the store over MCP.
  • The task: "Buy one Bouquet of Red Roses for delivery to Sam Lee, 123 Market St, San Francisco, CA 94105, email [email protected], with the cheapest delivery. Pay with the test card and complete the purchase."

The run in UCP Playground: the buyer's conversation on the left, every call in the trace on the right

Play the whole run below, or open it with the full trace.

Step 1: Discovery

Before any shopping, the agent reads the store's profile:

GET https://flowers.ucpsandbox.com/.well-known/ucp

The profile says which release the store speaks, where its services are, which capabilities it offers and how it takes payment. For this store (trimmed):

{
  "ucp": {
    "version": "2026-08-25",
    "services": {
      "dev.ucp.shopping": [
        { "transport": "rest", "endpoint": "https://flowers.ucpsandbox.com/ucp" },
        { "transport": "mcp", "endpoint": "https://flowers.ucpsandbox.com/mcp" }
      ]
    },
    "capabilities": {
      "dev.ucp.shopping.catalog.search": [...],
      "dev.ucp.shopping.catalog.lookup": [...],
      "dev.ucp.shopping.cart": [...],
      "dev.ucp.shopping.checkout": [...],
      "dev.ucp.shopping.order": [...],
      "dev.ucp.shopping.discount": [...],
      "dev.ucp.shopping.fulfillment": [...],
      "dev.ucp.shopping.buyer_consent": [...],
      "dev.ucp.common.location.search": [...],
      "dev.ucp.common.location.lookup": [...]
    },
    "payment_handlers": { "dev.mock.payment_handler": [...] }
  }
}

Ten capabilities, two transports (REST and MCP), and one payment handler. The agent uses MCP for the whole run.

Step 2: Negotiation

The agent has a profile too, at https://ucpplayground.com/.well-known/ucp-agent. Over MCP, every tool call carries it in meta:

{
  "name": "search_catalog",
  "arguments": {
    "meta": { "ucp-agent": { "profile": "https://ucpplayground.com/.well-known/ucp-agent" } },
    "catalog": { ... }
  }
}

The store reads it and works out what the two sides can use together. The spec calls this capability intersection: the store "determines the active capabilities by computing the intersection of its own declared capabilities with those in the platform's profile", picking the latest version both sides support.

Here, the store declares ten capabilities and the agent eleven. The agent's extra one is identity linking, which this store doesn't offer, so it drops out, and all ten of the store's capabilities are active. The version is 2026-08-25: the store also accepts 2026-04-08, but 2026-08-25 is the latest both support. Three of the ten are extensions of checkout (fulfillment, discount and buyer consent), active because checkout is. Each response then names the capabilities that apply to it: the checkout responses in this run list checkout, fulfillment, discount and buyer consent.

Discovery and negotiation in the run: the agent read the store's profile, agreed 2026-08-25, 10 of 10 capabilities active, every call signed

The agent searches the catalogue, passing the buyer's country, currency and language as context:

{
  "name": "search_catalog",
  "arguments": {
    "catalog": {
      "query": "Bouquet of Red Roses",
      "context": { "address_country": "US", "currency": "USD", "language": "en" }
    }
  }
}

The store returns the product, with prices in minor units: 3500 is $35.00.

Step 4: Checkout starts, and the store asks for more

The agent creates a checkout with the item, the buyer and the delivery address:

{
  "name": "create_checkout",
  "arguments": {
    "checkout": {
      "line_items": [{ "item": { "id": "bouquet_roses" }, "quantity": 1 }],
      "buyer": { "first_name": "Sam", "last_name": "Lee", "email": "[email protected]" },
      "fulfillment": {
        "methods": [{
          "type": "shipping",
          "destinations": [{
            "id": "dest_1", "first_name": "Sam", "last_name": "Lee",
            "street_address": "123 Market St", "address_locality": "San Francisco",
            "address_region": "CA", "postal_code": "94105", "address_country": "US"
          }]
        }]
      }
    }
  }
}

The store creates the checkout and answers with its status and a message:

{
  "status": "incomplete",
  "messages": [{
    "type": "error",
    "code": "missing",
    "path": "$.fulfillment.methods[0].groups[0].selected_option_id",
    "severity": "recoverable"
  }]
}

This is how UCP checkouts talk. A checkout is always in one of six states: incomplete, requires_escalation, ready_for_complete, complete_in_progress, completed or canceled. Messages say what's missing, with a path to the exact field and a severity (recoverable, requires_buyer_input, requires_buyer_review or unrecoverable). Here, nothing is wrong: the store just needs a delivery option, and offers three:

Option Price
Free Shipping (free-ship) $0.00
Standard Shipping (std-ship) $5.00
Express Shipping (US) (exp-ship-us) $15.00

Step 5: The agent picks delivery

The buyer asked for the cheapest delivery, so the agent selects free-ship with update_checkout. The store recalculates and the status moves on:

{
  "status": "ready_for_complete",
  "totals": [
    { "type": "subtotal", "amount": 3500 },
    { "type": "fulfillment", "amount": 0 },
    { "type": "total", "amount": 3500 }
  ]
}

ready_for_complete means the store has everything it needs except payment.

The checkout as the buyer sees it: "Needs more details", the store asking for a delivery option, then "Ready to pay" with free shipping. Nothing charged yet

Step 6: Payment and the order

To pay, the agent calls complete_checkout with a payment instrument from the store's payment handler. This call also carries an idempotency key, so a retried request can never charge twice:

{
  "name": "complete_checkout",
  "arguments": {
    "meta": {
      "ucp-agent": { "profile": "https://ucpplayground.com/.well-known/ucp-agent" },
      "idempotency-key": "41107da3-7536-4167-bfe5-2848137e39ca"
    },
    "id": "01a15ea7-75a9-7038-89ef-1eccf158ab6f",
    "checkout": {
      "payment": {
        "instruments": [{ "id": "instr_1", "type": "card", "handler_id": "mock_payment_handler" }]
      }
    }
  }
}

The request is also signed (HTTP Message Signatures, with Signature, Signature-Input and Content-Digest headers), so the store can check it came from the agent its profile names.

The store takes payment and answers completed, with the order:

{
  "status": "completed",
  "order": {
    "id": "01a15ea7-ac36-73f9-a047-33a148f3dd3e",
    "label": "NF-W7MHA3",
    "permalink_url": "https://flowers.ucpsandbox.com/orders/01a15ea7-ac36-73f9-a047-33a148f3dd3e"
  }
}

$35.00, free shipping, order NF-W7MHA3. Start to finish: four tool calls.

Order placed: the paid checkout with order NF-W7MHA3, and the agent's summary for the buyer

Step 7: When the card is declined

On flowers-decline.ucpsandbox.com, the same task runs the same way until payment. Then the store declines the card:

{
  "status": "ready_for_complete",
  "messages": [{
    "type": "error",
    "code": "payment_failed",
    "content": "Payment was declined by the issuer.",
    "path": "$.payment.instruments[0]",
    "severity": "recoverable"
  }]
}

Three things are worth noticing. The checkout doesn't fail: it stays ready_for_complete, so the buyer can still pay another way. The message points at the exact instrument that failed. And the severity is recoverable: the store is saying "this can still work", not "stop".

What the agent does next matters as much as the protocol. Sending the same card again would only be declined again, so the agent stops, tells the buyer the card was declined, and offers the store's own checkout to finish with another payment method. One complete_checkout, no retries.

A declined card: the checkout stays "Ready to pay", the store says the payment was declined, and the agent tells the buyer instead of trying again

Play the declined run, or open it with the full trace:

Step 8: After the sale, linking the buyer's account

Orders belong to buyers, so a store can ask for proof of who is asking before it shares one. On flowers-account.ucpsandbox.com, the store offers identity linking (dev.ucp.common.identity_linking), built on OAuth 2.0. Asked "where is my order?" before any link, the store answers that it needs a linked buyer account.

Linking takes four steps, each a standard the spec builds on:

  1. Read the store's sign-in metadata (RFC 8414): GET /.well-known/oauth-authorization-server names the authorization, token and registration endpoints and the scopes on offer, here dev.ucp.shopping.order:read and dev.ucp.shopping.order:manage.
  2. Register as a client (RFC 7591): the agent registers itself with the store on the fly. No prior agreement needed.
  3. Send the buyer to sign in, with PKCE (S256). The buyer signs in at the store and approves the agent's access. Their password never passes through the agent.
  4. Exchange the code for a token, scoped to orders, valid for an hour, with a refresh token.

Account linking in the trace of an Inspect session: the store's sign-in metadata, client registration, the buyer's sign-in, the code exchange, then get_order. The first sign-in wasn't finished, so registration and sign-in show twice

With the link in place, get_order returns the order (trimmed):

{
  "label": "NF-HJEMQM",
  "line_items": [{
    "item": { "id": "bouquet_roses", "title": "Bouquet of Red Roses", "price": 3500 },
    "quantity": { "original": 1, "total": 1, "fulfilled": 1 },
    "status": "fulfilled"
  }],
  "fulfillment": {
    "expectations": [{ "description": "Free Shipping", ... }]
  }
}

The order as Inspect shows it: Bouquet of Red Roses, free shipping, and the store's own update: shipped, out for delivery

What it means for stores and agent builders

  • The profile is the contract. Everything the agent did came from what the store declared at /.well-known/ucp. A capability left out of the profile isn't used, even if the API supports it.
  • Messages carry the conversation. The store never returned a vague failure. Every gap came back as a message with a code, a path and a severity, and the agent could act on each one.
  • Declines are part of the flow. A store that keeps the checkout open after a decline, with a recoverable message pointing at the instrument, lets the buyer finish the purchase. An agent that resends the same card doesn't.
  • After-sale needs identity. Order lookups are where buyer accounts come in, and UCP uses standard OAuth for them, discovered and registered at run time.

Try it yourself

Both runs above are public and replayable. The test stores are public too, and UCP Playground runs an agent against them, or against your own store, with the full trace.

FAQ

What is a UCP profile? A JSON document a store publishes at /.well-known/ucp. It says which UCP release the store supports, where its services are (REST, MCP), which capabilities it offers and how it takes payment. Agents publish a profile too.

How does an agent know what a store supports? It reads the store's profile, and sends its own with every request. The store uses the capabilities both sides declare, at the latest version both support, and each response names the capabilities that apply to it.

What are the checkout statuses in UCP? incomplete, requires_escalation, ready_for_complete, complete_in_progress, completed and canceled (UCP 2026-08-25).

What happens when a payment is declined in UCP? The store returns an error message with code payment_failed, a path to the instrument and a severity. In these runs the checkout stayed ready_for_complete with severity recoverable, so the buyer could still pay another way.

Does an agent need an account with each store? Not to shop. It registers as an OAuth client on the fly (RFC 7591) only when the buyer links their account, for example to look up an order.

Is the payment real? Not here. These are test stores with a mock payment handler, built to the spec so every step can be shown.


About UCP Checker

UCP Checker is the independent validation and observability layer for the Universal Commerce Protocol. We crawl, validate and grade every public UCP manifest we can find, run the merchant directory, the UCP Score, live adoption stats, the vertical guides and the authority-bound vendor map, and track the spec as it evolves so you don't have to — measured from two vantages (what a business declares, and what actually happens when an agent transacts), the same way for everyone, without picking winners.

Sources

  • UCP specification, release 2026-08-25: overview, checkout (MCP binding), order, identity linking and signatures. ucp.dev.
  • UCP core concepts: capability intersection. ucp.dev.
  • RFC 8414, OAuth 2.0 Authorization Server Metadata. IETF.
  • RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol. IETF.
  • RFC 7636, Proof Key for Code Exchange (PKCE). IETF.
  • RFC 9421, HTTP Message Signatures. IETF.
  • Runs recorded on UCP Playground, 21 October 2026.

Related coverage: How the Personal Agent Protocol works: a real agent, step by step · Agent identity in UCP: Web Bot Auth interop · Two routes to checkout: UCP and WebMCP · When the total isn't final: payment proposals in UCP

What does a UCP agent find at your store?
Check it once and it gets its own status page.
Check a store

Keep reading

8 Oct 2026 Google's UCP Integration Hub in Merchant Center: How to Get Your Store In Guides · 7 min 7 Oct 2026 UCP's Ask Is Merged: Six Review Questions and How the Spec Answered Them Guides · 8 min 6 Oct 2026 UCP Gets a Product Feed: Inside the Catalog Feed Draft Guides · 9 min