You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After identity linking (OAuth 2.0), the checkout response's payment.handlers only reflects store-level payment capabilities (Stripe, delegate). There is no mechanism to surface buyer-specific instruments that become available after authentication — wallet balance, saved cards, loyalty points, store credit. The agent can see WHO the buyer is (buyer object is populated) but not WHAT they can pay with. This blocks autonomous checkout for authenticated sessions, forcing escalation to the store's checkout page every time.
Motivation
This is the missing link between identity linking and autonomous checkout. In live testing between UCP Playground and a WooCommerce store (UCPReady), an identity-linked buyer with wallet balance hit this wall:
But payment.instruments: [] — empty, no wallet surfaced
Agent tries the only declared handler (dev.ucp.delegate_payment) — store rejects it: "Selected payment method is not available"
Session escalates to continue_url — autonomous checkout blocked
We propose adding payment.available_instruments to checkout responses for authenticated sessions — a per buyer, per-session list of usable payment methods resolved at runtime. This is distinct from #187 (store-level available_instruments in handler config). The target users are agent platforms that need to complete checkout programmatically after identity linking.
Authenticated checkout responses include payment.available_instruments — a per-buyer list of usable payment methods (wallet, saved cards, loyalty) resolved at runtime from the identity-linked session
Agents can select a buyer-specific instrument via update_checkout with selected_instrument_id without trial-and-error or escalation
Guest checkouts are unaffected — available_instruments returns empty for unauthenticated sessions
Non-Goals
Not changing store-level payment_handlers in the manifest — that's generic capability declaration and stays as-is
Not defining how merchants tokenize or secure payment credentials — that's handler-specific (Stripe, PayPal, etc.)
type — enum: store_credit, saved_card, loyalty, bnpl, gift_card
label — human-readable display name
balance / sufficient — optional, for balance-based instruments
brand / last_digits — optional, for card-type instruments
API Changes
create_checkout / get_checkout response — add payment.available_instruments array. Only populated when the session is authenticated via identity linking.
Empty array for guest sessions.
update_checkout request — no schema change needed. Agents select an instrument by setting payment.selected_instrument_id to an id from available_instruments. The existing field already supports this.
Behavioral Changes
Merchants resolve available_instruments at checkout creation time based on the authenticated buyer's account (stored cards, wallet balance, loyalty tier)
The list MAY change between create_checkout and update_checkout calls (e.g., wallet balance changes) - agents should re-read from get_checkout if needed
If available_instruments is empty or absent, the agent falls back to store-level payment.handlers as today (no breaking change)
Risks and Mitigations
Security:available_instruments exposes buyer-specific payment data (wallet balance, saved card last digits). Mitigation: this data only appears in authenticated sessions — the buyer already consented via OAuth. Instrument IDs are opaque references, not credentials. No card numbers or tokens are exposed — only display metadata (last 4 digits, brand, label). Merchants MUST NOT include full card numbers or sensitive credentials in this field.
Performance: Merchants must resolve buyer instruments at checkout creation time, which may require additional database lookups (wallet balance, saved cards). Mitigation: this is a single query at create_checkout time, same request lifecycle. Merchants already resolve buyer identity in authenticated sessions — instrument lookup piggybacks on that. No additional round trips for the agent.
Backward Compatibility: No breaking change. available_instruments is a new optional field on the checkout response. Existing clients that don't read it are unaffected. Guest checkouts return an empty array (or omit the field entirely). Agents that don't understand it fall back to payment.handlers as they do today.
Complexity: Adds one new array field to the checkout response schema. The selection mechanism reuses the existing selected_instrument_id field — no new API endpoints or tool schemas required. Merchant implementation complexity is proportional to the payment methods they support (wallet = 1 query, saved cards = 1 query to Stripe/vault).
Test Plan
Unit Tests:
Checkout response schema validation — available_instruments array is present and well-formed for authenticated sessions
available_instruments is empty array or absent for guest (unauthenticated) sessions
Each instrument has required fields: id, handler_id, type, label
selected_instrument_id accepts an ID from available_instruments via update_checkout
Selecting an invalid instrument ID returns a structured error
Summary
After identity linking (OAuth 2.0), the checkout response's
payment.handlersonly reflects store-level payment capabilities (Stripe, delegate). There is no mechanism to surface buyer-specific instruments that become available after authentication — wallet balance, saved cards, loyalty points, store credit. The agent can see WHO the buyer is (buyer object is populated) but not WHAT they can pay with. This blocks autonomous checkout for authenticated sessions, forcing escalation to the store's checkout page every time.Motivation
This is the missing link between identity linking and autonomous checkout. In live testing between UCP Playground and a WooCommerce store (UCPReady), an identity-linked buyer with wallet balance hit this wall:
buyer: {first_name: "Jane", email: "jane@example.com"}payment.instruments: []— empty, no wallet surfaceddev.ucp.delegate_payment) — store rejects it: "Selected payment method is not available"We propose adding
payment.available_instrumentsto checkout responses for authenticated sessions — a per buyer, per-session list of usable payment methods resolved at runtime. This is distinct from #187 (store-levelavailable_instrumentsin handler config). The target users are agent platforms that need to complete checkout programmatically after identity linking.*Co-authored with @zologic (Almin Zolotic)
Goals
payment.available_instruments— a per-buyer list of usable payment methods (wallet, saved cards, loyalty) resolved at runtime from the identity-linked sessionupdate_checkoutwithselected_instrument_idwithout trial-and-error or escalationavailable_instrumentsreturns empty for unauthenticated sessionsNon-Goals
payment_handlersin the manifest — that's generic capability declaration and stays as-isavailable_instrumentsat handler config level) — this proposal is per-buyer, per-session, complementaryavailable_instruments— it's optional, only populated for authenticated sessionsDetailed Design
Data Structures
Add
available_instrumentsarray to the checkout responsepaymentobject:Each instrument has:
id— unique identifier for selectionhandler_id— links to parent payment handlertype— enum:store_credit,saved_card,loyalty,bnpl,gift_cardlabel— human-readable display namebalance/sufficient— optional, for balance-based instrumentsbrand/last_digits— optional, for card-type instrumentsAPI Changes
create_checkout/get_checkoutresponse — addpayment.available_instrumentsarray. Only populated when the session is authenticated via identity linking.Empty array for guest sessions.
update_checkoutrequest — no schema change needed. Agents select an instrument by settingpayment.selected_instrument_idto anidfromavailable_instruments. The existing field already supports this.Behavioral Changes
available_instrumentsat checkout creation time based on the authenticated buyer's account (stored cards, wallet balance, loyalty tier)create_checkoutandupdate_checkoutcalls (e.g., wallet balance changes) - agents should re-read fromget_checkoutif neededavailable_instrumentsis empty or absent, the agent falls back to store-levelpayment.handlersas today (no breaking change)Risks and Mitigations
Security:
available_instrumentsexposes buyer-specific payment data (wallet balance, saved card last digits). Mitigation: this data only appears in authenticated sessions — the buyer already consented via OAuth. Instrument IDs are opaque references, not credentials. No card numbers or tokens are exposed — only display metadata (last 4 digits, brand, label). Merchants MUST NOT include full card numbers or sensitive credentials in this field.Performance: Merchants must resolve buyer instruments at checkout creation time, which may require additional database lookups (wallet balance, saved cards). Mitigation: this is a single query at
create_checkouttime, same request lifecycle. Merchants already resolve buyer identity in authenticated sessions — instrument lookup piggybacks on that. No additional round trips for the agent.Backward Compatibility: No breaking change.
available_instrumentsis a new optional field on the checkout response. Existing clients that don't read it are unaffected. Guest checkouts return an empty array (or omit the field entirely). Agents that don't understand it fall back topayment.handlersas they do today.Complexity: Adds one new array field to the checkout response schema. The selection mechanism reuses the existing
selected_instrument_idfield — no new API endpoints or tool schemas required. Merchant implementation complexity is proportional to the payment methods they support (wallet = 1 query, saved cards = 1 query to Stripe/vault).Test Plan
Unit Tests:
available_instrumentsarray is present and well-formed for authenticated sessionsavailable_instrumentsis empty array or absent for guest (unauthenticated) sessionsid,handler_id,type,labelselected_instrument_idaccepts an ID fromavailable_instrumentsviaupdate_checkoutIntegration Tests:
create_checkout→ verifyavailable_instrumentscontains buyer's stored payment methodsupdate_checkoutwithselected_instrument_idfromavailable_instruments→ verify checkout status transitions towardready_for_completeavailable_instrumentsis empty and behavior falls back topayment.handlerssufficient: false(insufficient wallet balance) → verify checkout rejects or requests supplementary paymentEnd-to-End Tests:
available_instruments→ select wallet → complete checkout → order createdavailable_instruments→ correctly falls back to delegate payment handler → escalates to continue_urlGraduation Criteria
Working Draft → Candidate:
Candidate → Stable:
Implementation History
Code of Conduct