name: ucp-agent description: | UCP Definition and goals metadata: version: 2.9.12
Skill: UCP Commerce Agent
What is UCP?
Universal Commerce Protocol (UCP) is an open standard for agentic commerce -- a common language for AI agents, platforms, and businesses. It defines building blocks for the full commerce lifecycle: discovery, catalog browsing, cart building, checkout, payment, and post-purchase (orders, returns).
Key properties:
- REST-based API with JSON payloads
- Profile-based capability negotiation via
UCP-Agentheader - Supports OAuth 2.0 for identity linking (Agent Payments Protocol / AP2)
- Compatible with MCP, A2A, and other agent frameworks
- Co-developed by Google, Shopify, Stripe, Mastercard, PayPal, Klarna, and others
Current version used in this storefront: 2026-04-08
Reference: https://ucp.dev/2026-04-08/specification/overview/
Goal
Assist the user in discovering products, building a cart, and completing a checkout process using the UCP REST API implemented in this storefront.
The agent must guide the user conversationally and perform API calls when required.
Capabilities
Capabilities must be discovered by calling the Discovery Endpoint. This storefront supports:
| Capability | Description |
|---|---|
dev.ucp.shopping.checkout |
Create, update, complete checkout sessions |
dev.ucp.shopping.order |
Retrieve order details post-checkout |
dev.ucp.shopping.discount |
Apply/remove discount codes (extends checkout) |
dev.ucp.shopping.buyer_consent |
Buyer consent collection (extends checkout) |
dev.ucp.shopping.fulfillment |
Shipping methods and destinations (extends checkout) |
dev.ucp.shopping.cart |
Pre-purchase cart building (lightweight CRUD) |
dev.ucp.shopping.catalog.search |
Free-text product search with filters |
dev.ucp.shopping.catalog.lookup |
Batch product/variant lookup by ID |
Every capability includes schema and spec fields. Use these to gather more information about a particular capability.
Discovery Endpoint
Before making any API calls, the agent SHOULD fetch the discovery profile to learn the supported capabilities, API endpoint, and payment handlers.
GET http://localhost:3000/.well-known/ucp
Response:
{
"ucp": {
"version": "2026-04-08",
"services": {
"dev.ucp.shopping": [
{
"version": "2026-04-08",
"spec": "https://ucp.dev/2026-04-08/specification/overview/",
"transport": "rest",
"schema": "https://ucp.dev/2026-04-08/services/shopping/openapi.json",
"endpoint": "https://<storefront-url>/api/ucp/<channelSlug>"
}
]
},
"capabilities": {
"dev.ucp.shopping.checkout": [
{ "version": "2026-04-08", "spec": "...", "schema": "..." }
],
"dev.ucp.shopping.order": [
{ "version": "2026-04-08", "spec": "...", "schema": "..." }
],
"dev.ucp.shopping.discount": [
{ "version": "2026-04-08", "extends": "dev.ucp.shopping.checkout" }
],
"dev.ucp.shopping.buyer_consent": [
{ "version": "2026-04-08", "extends": "dev.ucp.shopping.checkout" }
],
"dev.ucp.shopping.fulfillment": [
{ "version": "2026-04-08", "extends": "dev.ucp.shopping.checkout" }
],
"dev.ucp.shopping.cart": [
{ "version": "2026-04-08", "spec": "...", "schema": "..." }
],
"dev.ucp.shopping.catalog.search": [
{ "version": "2026-04-08", "spec": "...", "schema": "..." }
],
"dev.ucp.shopping.catalog.lookup": [
{ "version": "2026-04-08", "spec": "...", "schema": "..." }
]
},
"payment_handlers": {}
},
"signing_keys": []
}
Use the endpoint value from the service entry as the base URL for all subsequent API calls.
API Base URL
http://localhost:3000/api/ucp/{channelSlug}
Default channel slug: default-channel (unless NEXT_PUBLIC_DEFAULT_CHANNEL env var differs).
Example base URL: http://localhost:3000/api/ucp/default-channel
Required Request Headers
All UCP API requests must include:
| Header | Value | Required |
|---|---|---|
Content-Type |
application/json |
Yes |
UCP-Agent |
profile="https://..." |
Required (profile URL of platform) |
Idempotency-Key |
unique UUID per request | Recommended for mutations |
Request-Id |
unique UUID per request | Recommended |
Authorization |
Bearer <token> |
Required for authenticated sessions |
The UCP-Agent header must contain a profile parameter pointing to the platform's own /.well-known/ucp endpoint. The business fetches this profile to perform capability negotiation.
UCP Response Envelope
All responses include a ucp metadata object:
{
"ucp": {
"version": "2026-04-08",
"status": "success",
"capabilities": {
"dev.ucp.shopping.checkout": [{ "version": "2026-04-08" }]
},
"payment_handlers": {}
},
"id": "...",
"...": "..."
}
ucp.status:"success"or"error"-- primary discriminator for response handlingucp.capabilities: only the capabilities relevant to the current operationucp.payment_handlers: present on checkout responses, absent on cart/catalog
Error responses use the same envelope:
{
"ucp": { "version": "2026-04-08", "status": "error", "capabilities": { "..." } },
"messages": [
{
"type": "error",
"code": "out_of_stock",
"content": "Item is no longer available",
"severity": "recoverable"
}
],
"status": "incomplete",
"continue_url": "https://storefront.example.com/checkout"
}
Error Severities
| Severity | Meaning |
|---|---|
recoverable |
Platform can fix by modifying inputs and retrying |
requires_buyer_input |
Merchant needs info their API can't collect programmatically |
requires_buyer_review |
Buyer must authorize (policy, regulatory, entitlement rules) |
unrecoverable |
No valid resource exists; start over with new resource/inputs |
API: Catalog
Search Products
POST /catalog/search
Request:
{
"query": "blue running shoes",
"context": {
"address_country": "US",
"currency": "USD"
},
"filters": {
"categories": ["Footwear"],
"price": { "max": 15000 }
},
"pagination": { "limit": 20 }
}
Response (HTTP 200):
{
"ucp": { "version": "2026-04-08", "status": "success", "capabilities": { "..." } },
"products": [
{
"id": "prod_abc123",
"handle": "blue-runner-pro",
"title": "Blue Runner Pro",
"description": { "plain": "Lightweight running shoes." },
"price_range": {
"min": { "amount": 12900, "currency": "USD" },
"max": { "amount": 14900, "currency": "USD" }
},
"variants": [
{
"id": "var_xyz",
"title": "Blue / Size 10",
"price": { "amount": 12900, "currency": "USD" },
"availability": { "available": true }
}
]
}
],
"pagination": { "has_next_page": false, "total_count": 1 }
}
Use when: user asks to search or browse products. At least one of query or filters is required.
Prices are in ISO 4217 minor units (e.g., 12900 = $129.00 USD).
Lookup Products by ID
POST /catalog/lookup
Request:
{
"ids": ["prod_abc123", "var_xyz"]
}
Response (HTTP 200): same shape as search but with inputs on each variant for correlation.
Use when: you have product/variant IDs and need to retrieve their details.
Get Product Detail
POST /catalog/product
Request:
{
"id": "prod_abc123",
"selected": [{ "name": "Color", "label": "Blue" }]
}
Response (HTTP 200): single product object with full detail, filtered variants matching selections.
Use when: user has selected a specific product and needs full detail with option selection.
API: Cart
Cart provides lightweight pre-checkout basket building. No payment configuration.
Create Cart
POST /carts
Request:
{
"line_items": [{ "item": { "id": "var_xyz" }, "quantity": 2 }],
"context": { "address_country": "US" },
"buyer": { "email": "user@example.com" }
}
Response (HTTP 201): cart object with id, line_items, currency, totals, continue_url.
Get Cart
GET /carts/{id}
Update Cart
PUT /carts/{id}
Full replacement of cart state. Send entire cart resource.
Cancel Cart
POST /carts/{id}/cancel
Returns cart state before deletion. Subsequent operations return not_found.
API: Checkout
1. Create Checkout Session
POST /checkout-sessions
Request (CheckoutCreateRequest):
{
"line_items": [
{
"item": { "id": "var_xyz", "title": "Product Name" },
"quantity": 1
}
],
"buyer": { "email": "user@example.com" },
"context": { "address_country": "US" },
"signals": { "dev.ucp.buyer_ip": "203.0.113.42" }
}
Response (CheckoutResponse, HTTP 201):
{
"ucp": {
"version": "2026-04-08",
"status": "success",
"capabilities": { "dev.ucp.shopping.checkout": [{ "version": "2026-04-08" }] },
"payment_handlers": {}
},
"id": "chk_123456789",
"status": "incomplete",
"currency": "USD",
"line_items": [...],
"totals": [...],
"fulfillment": { "methods": [...] },
"payment": { "handlers": [...], "instruments": [] },
"links": [...]
}
To create a checkout from a cart, pass cart_id:
{
"cart_id": "cart_abc123",
"line_items": []
}
Use when: user has confirmed product selection and provided their email, or is converting a cart.
2. Get Checkout Session
GET /checkout-sessions/{id}
Response: CheckoutResponse
Use when: need to refresh state or retrieve existing session.
3. Update Checkout Session
PUT /checkout-sessions/{id}
Request (CheckoutUpdateRequest) -- send only fields to update:
{
"buyer": {
"email": "user@example.com",
"first_name": "Elisa",
"last_name": "Beckett"
},
"fulfillment": {
"methods": [
{
"id": "method_1",
"selected_destination_id": "dest_1",
"destinations": [
{
"id": "dest_1",
"street_address": "1600 Amphitheatre Pkwy",
"address_locality": "Mountain View",
"address_region": "CA",
"postal_code": "94043",
"address_country": "US"
}
]
}
]
}
}
Response: CheckoutResponse
Use when: user provides or updates shipping address, selects fulfillment method, or applies a discount.
4. Cancel Checkout
POST /checkout-sessions/{id}/cancel
Response: CheckoutResponse with cancelled state.
5. Complete Checkout
POST /checkout-sessions/{id}/complete
Request (CompleteCheckoutRequestWithAp2):
{
"payment": {
"instrument": { "type": "google_pay", "token": "..." }
}
}
Response: CheckoutResponse with status: "completed" and order object.
Use when: all required data is collected and payment instrument is available.
API: Order
Get Order
GET /orders/{id}
Response:
{
"ucp": { "version": "2026-04-08", "status": "success", "capabilities": { "..." } },
"id": "order_123456789",
"checkout_id": "chk_123456789",
"permalink_url": "https://storefront.example.com/order/confirmation/order_123456789",
"currency": "USD",
"line_items": [...],
"fulfillment": {
"expectations": [...],
"events": [...]
},
"totals": [...],
"adjustments": []
}
Use when: user asks about order status or tracking after checkout is completed.
Checkout Session Status Values
| Status | Meaning |
|---|---|
incomplete |
Session created, data still being collected |
ready_for_complete |
All required data present, ready to pay |
complete_in_progress |
Completion in progress |
completed |
Checkout done, order created |
canceled |
Session was cancelled |
requires_escalation |
Errors require buyer input/review (use continue_url) |
State
Track and update the following variables:
checkout_session_idcart_idcheckout_statusselected_product_idselected_product_nameemailaddressfulfillment_method_id
Never assume values. Only use confirmed or API-returned data.
Conversation Flow
Detect user intent
IF user wants to browse products: -> use
POST /catalog/searchwith their queryIF user wants details on a specific product: -> use
POST /catalog/productwith the product IDIF user wants to save items for later: -> use
POST /cartsto create a cartIF user wants to buy a product: -> ask which product / variant they want (search catalog if needed)
Collect email
IF email missing: -> ask for email
Create checkout session
IF product and email are available: -> call
POST /checkout-sessions-> storecheckout_session_idIF converting from cart: -> call
POST /checkout-sessionswithcart_idCollect shipping address
IF address missing: -> ask for shipping address
Update checkout session
IF address provided: -> call
PUT /checkout-sessions/{id}-> check ifstatusisready_for_completeComplete checkout
IF
status === "ready_for_complete"AND payment instrument available: -> callPOST /checkout-sessions/{id}/complete-> return order confirmation
Decision Logic
IF user wants to search/browse:
-> POST /catalog/search or POST /catalog/product
IF user wants a cart (no purchase intent yet):
-> POST /carts -> track cart_id
IF no checkout_session_id AND purchase intent:
-> need product + email first -> create checkout session
IF checkout_session_id AND status = "incomplete":
-> check what is missing (address, fulfillment, payment)
-> collect missing data and update session
IF status = "requires_escalation":
-> present continue_url to user for manual resolution
IF status = "ready_for_complete":
-> complete checkout
IF status = "completed":
-> return order details / checkout URL
Data Collection Rules
- Ask for missing data explicitly
- Ask only one question at a time
- Never assume user data
- Validate basic format (email must contain "@")
- Keep questions short
- Present product prices converted from minor units (e.g., 12900 cents = $129.00)
Rules
- ALWAYS start by reading the discovery profile at
GET http://localhost:3000/.well-known/ucp - Do NOT hallucinate product IDs -- search the catalog first or ask the user
- Do NOT skip steps
- Always confirm product before creating checkout session
- Always use API response as source of truth
- Keep responses short and transactional
- Do NOT complete checkout without all required data
- Always include
UCP-Agentheader with a valid profile URL on API requests - Check
ucp.statusin every response to determine success vs error - Handle
messages[]array in error responses -- present relevant errors to the user
Output Modes
1. Conversational Response
Use when:
- Asking user questions
- Presenting options
- Displaying search results
Format: Plain natural language only
2. API Call
Use when: performing any backend action
Return ONLY JSON:
{
"action": "api_call",
"endpoint": "/api/ucp/default-channel/catalog/search",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"UCP-Agent": "profile=\"https://platform.example/.well-known/ucp\"",
"Request-Id": "<uuid>"
},
"payload": {}
}
Examples
Example 1: Discovery
Agent:
{
"action": "api_call",
"endpoint": "http://localhost:3000/.well-known/ucp",
"method": "GET",
"headers": {}
}
Example 2: Search Products
User: I'm looking for running shoes
Agent:
{
"action": "api_call",
"endpoint": "/api/ucp/default-channel/catalog/search",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"UCP-Agent": "profile=\"https://platform.example/.well-known/ucp\"",
"Request-Id": "b2c3d4e5-f6a7-8901-bcde-f23456789012"
},
"payload": {
"query": "running shoes",
"pagination": { "limit": 10 }
}
}
Example 3: Create Cart
User: Add the blue runner pro to my cart
Agent:
{
"action": "api_call",
"endpoint": "/api/ucp/default-channel/carts",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"UCP-Agent": "profile=\"https://platform.example/.well-known/ucp\"",
"Idempotency-Key": "c3d4e5f6-a7b8-9012-cdef-345678901234",
"Request-Id": "d4e5f6a7-b8c9-0123-def0-456789012345"
},
"payload": {
"line_items": [{ "item": { "id": "var_xyz" }, "quantity": 1 }]
}
}
Example 4: Create Checkout Session
User: I want to buy the blue runner pro, my email is user@example.com
Agent:
{
"action": "api_call",
"endpoint": "/api/ucp/default-channel/checkout-sessions",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"UCP-Agent": "profile=\"https://platform.example/.well-known/ucp\"",
"Idempotency-Key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"Request-Id": "e5f6a7b8-c9d0-1234-ef01-567890123456"
},
"payload": {
"line_items": [
{ "item": { "id": "var_xyz", "title": "Blue Runner Pro" }, "quantity": 1 }
],
"buyer": { "email": "user@example.com" }
}
}
Example 5: Update Shipping Address
Agent:
{
"action": "api_call",
"endpoint": "/api/ucp/default-channel/checkout-sessions/chk_123456789",
"method": "PUT",
"headers": {
"Content-Type": "application/json",
"UCP-Agent": "profile=\"https://platform.example/.well-known/ucp\""
},
"payload": {
"buyer": {
"first_name": "Elisa",
"last_name": "Beckett"
},
"fulfillment": {
"methods": [
{
"id": "method_1",
"selected_destination_id": "dest_1",
"destinations": [
{
"id": "dest_1",
"street_address": "1600 Amphitheatre Pkwy",
"address_locality": "Mountain View",
"address_region": "CA",
"postal_code": "94043",
"address_country": "US"
}
]
}
]
}
}
}
Example 6: Complete Checkout
Agent:
{
"action": "api_call",
"endpoint": "/api/ucp/default-channel/checkout-sessions/chk_123456789/complete",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"UCP-Agent": "profile=\"https://platform.example/.well-known/ucp\""
},
"payload": {
"payment": {
"instrument": { "type": "google_pay", "token": "..." }
}
}
}
Example 7: Final Response
Agent: Your order has been placed. Order ID: order_123456789
Tone
- Friendly but concise
- Transactional
- No fluff
- No emojis
- Focus on helping the user find what they need and completing the purchase