Safeguard
Supply Chain Security•

Agent Payments Protocol (AP2) Explained: Mandates, Credentials, Risks

AP2 lets AI agents pay with signed mandates: open and closed checkout and payment mandates as SD-JWT credentials. How it works, its flows and its risks.

Safeguard Security Team
38 min read

The Agent Payments Protocol (AP2) is an open protocol, first published by Google on 16 September 2025, that lets an AI agent prove a person authorised a specific purchase. It does this with signed mandates: tamper evident credentials that bind the user's approval to an exact checkout and payment, so merchants, card networks and processors can verify intent instead of trusting the agent.

Version 0.2, released on 28 April 2026 alongside Google's donation of AP2 to the FIDO Alliance, reshaped the vocabulary. The original "Intent Mandate" and "Cart Mandate" became open and closed forms of a Checkout Mandate and a Payment Mandate, secured as SD-JWTs. This post goes one level deeper than our posts on x402 and agent payments, A2A versus MCP on the wire, A2A for security teams and sandboxing computer-use agents. Those cover how agents talk; this one covers how they are allowed to spend.

Key takeaways

  • What it is. A security and evidence layer for agent commerce, not a payment rail. It works over cards today and has samples for the x402 crypto payment scheme.
  • Who publishes it. Google announced AP2 on 16 September 2025. Version 0.2 shipped on 28 April 2026, when the FIDO Alliance took on agent commerce standards starting from AP2 and a Mastercard contribution.
  • Two mandates, two states. A Checkout Mandate covers the merchant's exact checkout; a Payment Mandate covers the payment. Each is open (constraints) or closed (bound to one transaction).
  • The trust anchor is a Trusted Surface, a deterministic interface, never an LLM, where the user approves mandate content.
  • Human present or not changes who signs the closed mandate: the user, or an agent key the user's open mandate named in a cnf claim.
  • The spec assumes prompt injection cannot be prevented, so it caps damage with deterministic checks of hashes, signatures and constraints.
  • Real risks remain: wide open mandates, double spend, weak agent key custody, constraint bugs, units mismatches, and liability left to payment networks.

What AP2 is, who published it and what problem it solves

Online payments assume a human clicked "buy" on a page they trust; fraud tools, 3-D Secure and chargeback rules all lean on that. When an agent pays, the AP2 documentation says three questions lack answers:

  1. Authorisation. What proves the user gave this agent authority for this purchase?
  2. Authenticity. How can a merchant know the request reflects the user's real intent, not an agent error or hallucination?
  3. Accountability. If it goes wrong, who answers: user, agent developer, merchant, issuer or processor?

AP2's answer is "verifiable intent, not inferred action": each party gets a signed statement of what the user approved and checks the transaction against it in deterministic code.

Dated timeline

DateEventSource
15 May 2025W3C Verifiable Credentials Data Model 2.0 becomes a W3C RecommendationW3C
9 July 2025OpenID for Verifiable Presentations 1.0 published as a final specification (used by AP2 v0.2 for user credential delegation)OpenID Foundation
16 September 2025Google Cloud announces AP2 and publishes v0.1.0 on GitHub. The post lists more than 60 collaborating organisations and an A2A x402 extension for crypto paymentsGoogle Cloud blog; GitHub release v0.1.0
16 September 2025v0.1 specification defines three verifiable credentials: Intent Mandate, Cart Mandate and Payment MandateAP2 v0.1.0 docs/specification.md
November 2025SD-JWT published as RFC 9901 (the format AP2 v0.2 uses for mandates)RFC Editor
28 April 2026AP2 v0.2.0 released; Google donates AP2 to the FIDO Alliance; FIDO announces an Agentic Authentication Technical Working Group and agent commerce work in its Payments Technical Working GroupGitHub release v0.2.0; Google blog; FIDO Alliance
23 October 2026Current documentation at ap2-protocol.org describes "Agentic Payment Protocol (v0.2)"ap2-protocol.org

The repository is licensed under Apache 2.0, and standardisation now continues in FIDO's working groups.

What AP2 is not

AP2 does not move money. The v0.2 specification says it "operates as a security feature within a Commerce Protocol"; catalog and checkout APIs are out of scope, and it is designed to work with the Universal Commerce Protocol (UCP). It is instrument agnostic: cards first, with e-wallets, push payments such as UPI and PIX, and digital currencies on the roadmap. It also does not decide which agent is trustworthy; it is designed "to constrain Agent behaviors without them having to be inherently trustworthy".

Mandates in v0.1 and v0.2: intent, cart, checkout and payment

If you read about AP2 in 2025, you met Intent Mandates and Cart Mandates. If you read the current spec, you meet Checkout and Payment Mandates in open and closed states. They are the same idea, refined.

v0.1: Intent Mandate, Cart Mandate, Payment Mandate

The v0.1 specification described three verifiable credentials:

  • Cart Mandate. Generated by the merchant and signed by the user, "typically using a hardware-backed key". It bound payer and payee, a tokenised payment method, a risk payload, the exact products, amount and currency.
  • Intent Mandate. Generated by the shopping agent and signed by the user for purchases made while they are away. It carried allowed payment methods, shopping intent (categories or SKUs), a "prompt playback" of the request in natural language, and a time to live.
  • Payment Mandate. Shared with the network and issuer to signal agent involvement and whether the human was present.

Google's launch post put it simply: approve a cart and you sign a Cart Mandate; delegate a task and you sign an Intent Mandate with price limits and timing, from which the agent can later generate a Cart Mandate.

v0.2: open and closed Checkout and Payment Mandates

Version 0.2 keeps two mandate types and gives each two states:

Mandatevct value (open)vct value (closed)Verified byWhat it proves
Checkout Mandatemandate.checkout.open.1mandate.checkout.1MerchantThe agent is authorised to complete this exact merchant-signed checkout
Payment Mandatemandate.payment.open.1mandate.payment.1Credential Provider, Network, Merchant Payment ProcessorThe agent is authorised to pay this amount, to this payee, with this instrument, for this checkout

An open mandate is not yet bound to a transaction. It carries constraints and the agent's public key in a cnf claim, so only that agent can later close it. A closed mandate is bound to one transaction, either signed directly by the user (human present) or signed by the agent's key on top of the user's open mandate (human not present).

Roughly, the v0.1 Intent Mandate became open Checkout and Payment Mandates, and the Cart Mandate became a closed Checkout Mandate. The v0.2 Payment Mandate now carries the approved amount, payee and instrument plus an optional risk_data map. Note that sample READMEs on the main branch still mention IntentMandate and CartMandate in places, so check which vocabulary a file uses.

The checkout mandate fields

A closed Checkout Mandate contains:

  • vct: the type string, mandate.checkout.1.
  • checkout_jwt: the merchant-signed JWT of the checkout. With UCP, this must be the UCP Checkout object.
  • checkout_hash: the base64url hash of the checkout_jwt string, using the SD-JWT's _sd_alg or SHA-256 by default.
  • optional iat and exp timestamps.

Open Checkout Mandates can use checkout.allowed_merchants and checkout.line_items (the right quantity drawn from each revealed acceptable_items list, no item used twice; the spec suggests evaluating it as a maximum flow problem). The merchant's Checkout Receipt carries status, iss, iat, a reference hash of the closed mandate, and an order_id on success.

The payment mandate fields

A closed Payment Mandate contains:

  • vct: mandate.payment.1.
  • transaction_id: the base64url hash of the checkout_jwt, which links this payment to exactly one checkout.
  • payee: the merchant being paid.
  • payment_amount: ISO 4217 currency and an integer in minor units (27999 means 279.99 dollars).
  • payment_instrument, plus optional pisp, execution_date, risk_data, iat and exp.

Eight constraint types are defined for open Payment Mandates:

Constraint typeWhat it limitsHow it is evaluated
payment.amount_rangeAmount within min and max, in one currencyAmount between min and max; currency must match
payment.budgetTotal spend across recurring usesRequested amount plus all previous closed amounts must not exceed max
payment.agent_recurrenceHow often the open mandate can be reusedFrequency (ON_DEMAND to ANNUALLY) and optional max_occurrences
payment.allowed_payeesWhich merchants can be paidPayee must be in the revealed list
payment.allowed_payment_instrumentsWhich instruments can be usedInstrument must be in the revealed list
payment.allowed_pispsWhich initiation providers may facilitatePISP must be in the list
payment.referenceTies the payment to an open Checkout MandateHash of that open Checkout Mandate must be in the checkout chain
payment.execution_dateWhen payment may executenot_before and not_after window

Budget and recurrence are stateful: the verifier must remember what was already spent.

Worked example 1: does this payment pass its constraints?

A user signs an open Payment Mandate with payment.amount_range of USD, min 0, max 20000 (200.00 dollars, as in the spec's own example) and one allowed payee. The agent closes it for trainers at 199.00 dollars: amount 19900. The currency matches and 19900 is within 0 to 20000, so it passes. Had the merchant added 7.50 dollars of shipping, the amount would be 20650, which fails with an error receipt and sends the agent back to the user.

Worked example 2: a budget across recurring purchases

A user asks an agent to top up a coffee subscription. The open Payment Mandate carries payment.agent_recurrence with frequency MONTHLY and max_occurrences 12, and payment.budget with max 1000.00 USD.

MonthRequestedPrevious totalTotal if approvedResult
1300.000.00300.00Pass
2450.00300.00750.00Pass
3300.00750.001,050.00Fail: budget exceeded
3 (retry)250.00750.001,000.00Pass: "less than or equal to max"

Amounts are added to the total only after approval, so a rejected attempt consumes no budget, and the recurrence check must also confirm month 3 is a new monthly period.

Watch the units. The spec's budget example writes 1000.00 and its payment.amount_range example writes 100.50, while the schema says range limits are integers in minor units and payment_amount is always minor units. If one service reads 1000.00 as dollars and another as cents, a constraint is a hundred times looser than intended. Pin the convention in integration tests.

How verifiable credentials bind the user's approval to a purchase

VDCs, SD-JWT and where W3C credentials fit

AP2 uses the term verifiable digital credentials (VDCs): "tamper-evident, cryptographically signed digital objects". The v0.2 specification says AP2 "specifies the use of SD-JWTs" for securing mandates, and that other VDC formats such as ISO mobile documents could fill the same role.

"Verifiable credentials" often suggests the W3C Verifiable Credentials Data Model 2.0, a W3C Recommendation since 15 May 2025, with its issuer, holder and verifier roles and JSON-LD data model. AP2 v0.2 uses the same three party idea but the IETF format family:

  • SD-JWT (RFC 9901, November 2025). A JWT whose claims can be hidden behind salted hashes and revealed one at a time through "disclosures". AP2 uses this so an agent can show a merchant only the constraint entries that apply to this checkout.
  • SD-JWT VC (IETF draft, revision 19 at the time of writing). Adds the vct type claim that AP2 uses to name each mandate type and version.
  • Key binding and cnf (RFC 7800). A cnf claim names a public key; only the holder of the matching private key can produce a valid key binding JWT. AP2 uses this to name the agent key that may close an open mandate.
  • Delegate SD-JWT (individual Internet-Draft draft-gco-oauth-delegate-sd-jwt-00). Chains SD-JWTs so each hop is signed by the key named in the previous hop's cnf. The IETF datatracker lists this draft as no longer active, so expect the chaining format to change as it moves through FIDO.

The chain, hop by hop

The AP2 Python SDK documentation describes the wire format as SD-JWTs joined by ~~:

<root SD-JWT>~<disclosures>~~<intermediate KB-SD-JWT>~<disclosures>~~<closed KB-SD-JWT>~<disclosures>~
  • The root, issued by the bank or agent provider, contains cnf naming the next key.
  • Intermediate hops (typ of kb+sd-jwt+kb) are signed by the previous cnf key and carry their own cnf.
  • The closed leaf (typ of kb+sd-jwt) carries the final mandate, no cnf, plus sd_hash, aud, nonce and iat.

The verifier trusts only the root key; each other signature is checked with the key the previous hop named. sd_hash binds the leaf to the chain, and the receipt's reference, the SHA-256 of the leaf, binds the receipt to the authorised mandate.

Two ways to establish trust in the user's signature

The Agent Authorization Framework in v0.2 defines two delegation models:

  1. User Credential. An issuer such as a bank or wallet gives a credential to a Trusted Surface the user controls. It is presented with OpenID4VP, with the mandate content in transaction_data (type of delegate), so the user's key binding signature covers the mandate. One credential can then delegate to many agents.
  2. Trusted Agent Provider. The agent's operator is trusted directly: its deterministic Trusted Surface gets consent and a backend key signs. The provider "MUST ensure that the Agent is not able to access the Agent Provider signing key". Simpler, but every verifier must trust every provider.

How AP2 relates to A2A, MCP, UCP and HTTP 402 payments

AP2 is described on its home page as "available as an extension for the open-source Agent2Agent (A2A) protocol and Universal Commerce Protocol", and its principles call it an open extension for A2A and MCP.

  • A2A. Extensions are identified by URI in the agent card, can be marked required, and are activated with an A2A-Extensions HTTP header. The sample merchant agent card declares https://github.com/google-agentic-commerce/ap2/v1 with required: true on A2A protocol version 0.3.0. Mandates travel in message data parts.
  • MCP. The repository includes MCP server variants of the merchant and credentials provider roles, passing mandates as tool arguments and results. MCP itself defines no payment authorisation.
  • UCP. UCP calls AP2 the "trust layer": the business returns a checkoutSignature (a detached JWT over the checkout) and the platform supplies payment authorisations tied to it.
  • HTTP 402 and x402. RFC 9110 says status 402 "is reserved for future use". x402 uses it: the server answers 402 with a PAYMENT-REQUIRED header, the client retries with a signed payload in PAYMENT-SIGNATURE, and a facilitator offers /verify and /settle. In the EVM exact scheme the payload is an EIP-3009 authorisation with a 32 byte nonce and a validBefore time. AP2 ships x402 samples for both modes: x402 moves value, AP2 proves authorisation.

Comparison: AP2, HTTP 402 style payments and card network agent programs

Each row is described from that project's own documentation.

AP2 (v0.2)x402 (v2)Card network agent programs (example: Visa Trusted Agent Protocol)
LayerAuthorisation and evidence layer inside a commerce protocolPayment request and settlement over HTTP, MCP or A2AAgent identification and request signing toward merchants
What is signedUser or agent signed SD-JWT mandates over a merchant-signed checkout and a paymentPayer-signed payment authorisation (for example EIP-3009)HTTP message signature (RFC 9421) by the agent over request attributes
Proof of user authorisationClosed mandate signed by the user, or by an agent key the user's open mandate namedPayer signature over a payment; user intent is out of scopeSignature bound to the merchant domain and the operation (browsing or payment)
Trust rootCredential issuer or trusted agent provider keysPayer's wallet key; facilitator for verification and settlementThe network's register of approved agents and their public keys
Replay defencesd_hash, nonce, aud, receipts, and a rule against presenting a new open mandate without a rejection receipt32 byte nonce, validity window, on-chain nonce reuse checksTimestamps, session identifier and key identifier in the signature
Dispute evidenceCheckout and Payment Mandates plus receipts, hash linkedOn-chain settlement recordExisting card dispute processes
StatusOpen source, donated to FIDO Alliance (April 2026)Open source, version 2Published developer specification and sample code

The FIDO announcement adds that Mastercard contributed its "Verifiable Intent" framework, co-developed with Google to work with AP2. These layers stack rather than compete: a network signature identifies the agent, AP2 proves what the user approved, and a rail moves the money.

Roles in an AP2 flow and who holds which keys

The v0.2 specification defines five roles. One company can play several, and every role "MAY always delegate" its responsibilities, for example a merchant asking its processor to verify mandates.

RoleAgentic?ResponsibilitiesKeys it holds or checks
Shopping Agent (SA)Expected to be agenticDiscovery, building the checkout, assembling mandate content, presenting mandates, tracking receiptsHolds the agent key named in open mandates' cnf; signs closed mandates in autonomous mode
Trusted Surface (TS)MUST be non-agenticShows mandate content, gets informed consent, produces user-signed mandatesHolds or reaches the user credential key or the agent provider's signing key
Merchant (M)May be eitherSigns the checkout JWT, verifies the Checkout Mandate, returns a signed Checkout ReceiptMerchant checkout signing key; verifies user, provider and agent keys
Credential Provider (CP)May be eitherSupplies payment instruments, verifies the Payment Mandate, releases a scoped payment credential or tokenVerifies mandate chain; holds or obtains tokens
Merchant Payment Processor (MPP)May be eitherVerifies the payment credential is scoped to this checkout, processes payment, signs the Payment ReceiptReceipt signing key; verifies the Payment Mandate

The overview adds the network and issuer, which may issue agent specific tokens and see "AI agent presence signals". The key rule: when a role is agentic, "the Agent itself is a potential attacker", so validation "MUST happen in deterministic code". The model proposes; plain code checks.

Human present and human not present flows

AP2 calls these the direct and autonomous modes. In both, verifiers receive a closed Checkout Mandate and a closed Payment Mandate. The difference is who signed the closed mandates and how verifiers decide to trust that signature.

Human present (direct)

  1. The agent and merchant build a checkout; the merchant returns a signed checkout JWT.
  2. The agent passes closed Checkout and Payment Mandate content to the Trusted Surface.
  3. The user sees the exact checkout and payment there and approves, for example with a biometric.
  4. The Credential Provider (and possibly the network) verifies the Payment Mandate and returns a payment credential.
  5. The merchant receives the credential and Checkout Mandate, checks checkout_hash against the checkout it signed, and starts payment.
  6. Any party may challenge with existing mechanisms such as 3-D Secure on a trusted surface.
  7. The merchant returns a Checkout Receipt; the processor returns a Payment Receipt.

Human not present (autonomous)

  1. The agent repeats back what it will buy; the user approves open Checkout and Payment Mandates on the Trusted Surface with in-session authentication.
  2. The open mandates "MUST include the agent's public key as a cnf claim", with exp as short as the task allows.
  3. When conditions are met (a price drop, a ticket release), the agent signs closed mandates with its key and presents them with the user-signed open mandates, disclosing only what this checkout needs.
  4. Verifiers check signatures, sd_hash chaining and every constraint; unknown constraints "MUST be treated as failing".
  5. The agent "MUST NOT present any subsequent open Payment or Checkout Mandates without receiving a rejection receipt from the previous one".

A merchant unsure it can meet the request, for example when no SKU is named, can force the user back to confirm.

Human presentHuman not present
Who signs closed mandatesThe user, through the Trusted SurfaceThe agent key named in the open mandate
What the user approvesThe exact checkout and paymentConstraints: merchants, items, amounts, dates, recurrence
Main residual riskUser approves the wrong thing on a misleading screenConstraints too loose; agent key misuse; double spend
Typical extra controlsStep-up challenge on a trusted surfaceShort exp, tight constraints, deterministic signer, notifications
Dispute evidenceUser-signed closed mandates and receiptsUser-signed open mandates, agent-signed closed mandates and receipts

Security and fraud risks

AP2's security considerations open with an unusually candid line: "AP2 assumes that preventing prompt injection attacks is infeasible." It therefore puts every LLM and agent inside the threat model. That is the right starting point. It also means the protocol's guarantees are exactly as strong as the deterministic code and key custody around the model.

Prompt injection leading to purchases

OWASP's LLM01 describes indirect prompt injection as instructions hidden in external content, such as product pages or reviews, that change a model's behaviour. A shopping agent reads a lot of external content. The AP2 spec lists "Manipulated Discovery" as a threat and says the merchant's signature guarantees the integrity of the offer, while "constraint enforcement during closed Mandate verification ensures that the worst-case financial and logical impacts are strictly bounded."

AP2 does not stop an injected agent from choosing a worse product; it bounds the damage to what the open mandate allows. "Any merchant, up to 1,000 dollars" means a 1,000 dollar bound anywhere. With the human present, injection can still shape the recommendation, so the Trusted Surface must render the merchant-signed checkout, not the agent's summary.

Mandate scope creep

OWASP's LLM06, Excessive Agency, splits the problem into excessive functionality, excessive permissions and excessive autonomy. Open mandates are permissions. Common ways they grow too wide:

  • No checkout.allowed_merchants or payment.allowed_payees constraint, so any merchant qualifies.
  • Long exp values, even though the spec recommends the smallest workable value.
  • payment.agent_recurrence with ON_DEMAND frequency and no max_occurrences, paired with a large budget.
  • Broad acceptable_items lists that turn "these trainers" into "anything in footwear".

The implementation notes ask agents to let users manage active mandates, limit their duration and send notifications.

Replay and double spend

The spec's threat list covers several replay shapes:

  • Stolen Payment Mandate reused with another checkout. Mitigated because the closed Payment Mandate's transaction_id is the hash of one checkout JWT, and open ones carry a payment.reference constraint.
  • Open mandate reused to approve a different closed mandate. Mitigated by sd_hash binding and by the agent key in cnf.
  • Closed Checkout Mandate replayed against another session. The merchant must check checkout_hash against the latest checkout JWT.
  • Double spend. A prompt-injected agent tries to approve several valid checkouts from one open mandate. The spec says the non-deterministic part of the agent must not sign overlapping closed mandates without rejection receipts, and that those receipts "MUST be integrity protected from the Shopping Agent's LLM". Verifiers "MAY" reject overlapping mandates or invalidate earlier tokens.

Rejection by verifiers is only a "MAY", and a verifier that does not track presentations cannot detect double spend alone. If several providers each see a slice of the spending, none sees the total.

One cryptographic detail: the checkout JWT must use a randomised signature such as ECDSA, not a deterministic one such as Ed25519, or include a salt, so a checkout_hash cannot be matched against guessed checkouts. SD-JWT disclosure salts need enough entropy too, per RFC 9901.

Agent impersonation and key custody

In autonomous mode, whoever holds the agent private key can close open mandates within their constraints. If that key sits in the same process as the model, or in an environment variable the model's tools can read, a prompt injection that reaches a code execution tool can sign. The implementation notes suggest a pattern: deterministic code, reached through tool calling, "verifies the closed Mandate being created before being signed". In practice that means a separate signing service with its own policy, an HSM or platform keystore, and no model access to raw key material.

In the trusted agent provider model, the provider's key can mint mandates for every user, which makes it a prime target. Impersonating an agent toward merchants is left to the commerce protocol, where network agent signatures and UCP identification apply.

Dispute and liability gaps

AP2 produces strong evidence: the spec describes how to verify Checkout and Payment Mandates and their receipts at dispute time so they show "what the user, and each role saw". The v0.1 specification even included a table of scenarios, from first-party misuse to merchant non-fulfilment, with the evidence each mandate provides. But it was explicit that "every payment network will define its own liability contracts" and the table was "only a helpful guide". Version 0.2 says dispute details, retention and retrieval are outside its scope.

So the gaps are partly commercial: who retains mandates and receipts, for how long and in what form (the notes say store compact SD-JWTs with disclosures); what happens when the agent stayed within vague constraints but the user says "that is not what I meant"; and how agent signals affect chargeback rights, which each network decides.

Implementation risks that come from the spec itself

  • Unknown constraints must fail closed. Skipping unrecognised types turns every new constraint into a bypass.
  • Schema strings differ. The checkout schema table says vct "MUST be 'mandate.checkout'", while the versioning rules require the exact string mandate.checkout.1. Follow the versioning rule.
  • Moving drafts. Chaining rests on an expired individual draft and SD-JWT VC is still a draft. Pin versions and test for format changes.
  • Hash canonicalisation. Hash the exact base64url compact form. Re-serialising JSON first breaks verification or, worse, binds the wrong data.

Step by step: run the reference sample and inspect each signed artefact

This uses the official human present card sample: a stub card, a mock OTP (123) and local agents. No real money moves. You need a Gemini API key because the samples use Google's Agent Development Kit, though AP2 requires neither. Use a disposable VM and read the run script first.

1. Get the code at a known version

git clone https://github.com/google-agentic-commerce/AP2.git
cd AP2
git checkout v0.2.0          # or the commit you reviewed
git log -1 --format='%H %cd'

2. Read the run script before running it

less code/samples/python/scenarios/a2a/human-present/cards/run.sh

At the time of writing the script creates a virtual environment with uv, syncs the samples package, clears a .logs directory and a .temp-db directory used for keys and state, exports AGENT_PROVIDER_PUBLIC_KEY_PATH pointing at .temp-db/agent_provider_signing_key.pub, and starts the merchant agent on port 8001, the credentials provider on 8002 and the card processor on 8003, each logging to .logs/. Note where the agent provider signing key lives: on disk in a temp directory that every sample agent can read. That is fine for a demo and exactly what you must not copy into production.

3. Inventory the dependencies

find . -name pyproject.toml -not -path './.venv/*' | xargs grep -n -A30 'dependencies'

The JOSE and SD-JWT libraries, cryptography and the A2A SDK decide whether a forged mandate is accepted.

4. Set the key and start the sample

export GOOGLE_API_KEY='your_key'      # or use a .env file at the repo root
bash code/samples/python/scenarios/a2a/human-present/cards/run.sh

Open the ADK web UI the README points to, choose shopping_agent, and ask for something specific, adding that you want verbose output: "I want to buy a coffee maker. Be verbose and show all data payloads." The README notes that a follow-up reminder is sometimes needed before the agent prints JSON.

The flow runs through merchant-signed carts, linking the credential provider, choosing a payment method, signing the payment mandate, the mock OTP and the receipt.

5. Read the wire log

ls .logs/
grep -n 'Mandate' .logs/watch.log | head -50

watch.log records each request's method, URL and JSON bodies, A2A message parts and any mandate objects: what actually crossed between agents, not what the shopping agent told you.

6. Decode an SD-JWT chain without trusting it

Copy a compact token from the log into a file and decode it. Decoding is not verification; it only shows what the token claims.

# decode_chain.py: print headers, payloads and disclosures of an AP2 SD-JWT chain
import base64, json, sys

def b64d(s):
    return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))

token = open(sys.argv[1]).read().strip()
for hop_no, hop in enumerate(token.split("~~")):
    parts = [p for p in hop.split("~") if p]
    jwt, disclosures = parts[0], parts[1:]
    header, payload, _sig = jwt.split(".")
    print(f"hop {hop_no} header:", json.loads(b64d(header)))
    print(f"hop {hop_no} payload:", json.dumps(json.loads(b64d(payload)), indent=2))
    for d in disclosures:
        if d.count(".") == 2:      # a trailing key binding JWT
            print("  key binding JWT payload:", json.loads(b64d(d.split(".")[1])))
        else:
            print("  disclosure:", json.loads(b64d(d)))
python3 decode_chain.py mandate.txt

What to look for in each artefact:

ArtefactCheck
Merchant checkout JWTMerchant identity, line items, total, currency; signed by the merchant key
Open Checkout Mandatevct of mandate.checkout.open.1; cnf with the agent key; exp; constraints with hidden items
Closed Checkout Mandatetyp of kb+sd-jwt; aud, nonce, sd_hash; checkout_hash
Open Payment Mandatevct of mandate.payment.open.1; amount range, payees, payment.reference
Closed Payment Mandatetransaction_id equal to the checkout hash; payment_amount in minor units; payee; instrument
Checkout and Payment Receiptsstatus, iss, reference equal to the hash of the closed mandate

7. Recompute the checkout hash yourself

Take the checkout_jwt string exactly as it appears in the closed Checkout Mandate and hash it:

printf '%s' "$CHECKOUT_JWT" \
  | openssl dgst -sha256 -binary \
  | openssl base64 -A | tr '+/' '-_' | tr -d '='

The output must equal the Checkout Mandate's checkout_hash and the Payment Mandate's transaction_id. A mismatch usually means you copied re-serialised JSON instead of the compact string.

8. Build and verify a mandate chain offline with the SDK

The SDK README has an offline example: create issuer and agent keys, issue an open Payment Mandate with an amount range, an allowed payee and the agent key in cnf, present a closed mandate on top, then verify with expected_aud and expected_nonce and check constraints with PaymentMandateChain.parse(...).verify(...). There is no PyPI package yet:

uv venv && source .venv/bin/activate
uv pip install "git+https://github.com/google-agentic-commerce/AP2.git@v0.2.0"

Run the example as published, then write the negative tests where implementations fail:

  • Change the closed mandate's amount to exceed the open mandate's max and confirm verify reports a violation.
  • Present the chain with the wrong expected_aud or expected_nonce and confirm it is rejected.
  • Sign the closed mandate with a key other than the one in cnf and confirm it is rejected.
  • Add a constraint with an unknown type and confirm evaluation fails, as the spec requires.

9. Clean up

pkill -f 'roles\.' || true
rm -rf .temp-db .logs

Check the process list before pkill, and rotate the demo API key.

Common mistakes

  • Treating the agent's summary as consent. The user must approve the merchant-signed checkout on a Trusted Surface.
  • Letting the model hold the agent key. Any tool that reads files or environment variables can then sign.
  • Open mandates without payee limits. "Up to 500 dollars" with no payee list means anywhere.
  • Ignoring unknown constraint types. The spec says they must fail. Skipping them silently turns every future constraint into a no-op.
  • Mixing units. Treating 100.50 as dollars in one service and cents in another.
  • Re-serialising JSON before hashing. Hash the exact compact string you received.
  • No double spend ledger. Each verifier sees only its slice; without a shared record, one open mandate can fund several checkouts.
  • Copying sample key handling into production. The sample keeps a signing key in a temp directory readable by every agent.
  • Assuming AP2 settles liability. It produces evidence. Networks and contracts decide who pays.

FAQ

What is the Agent Payments Protocol (AP2)?

An open protocol, first published by Google on 16 September 2025 and donated to the FIDO Alliance on 28 April 2026, that lets AI agents prove a user authorised a purchase. It uses signed mandates, secured as SD-JWT credentials, that verifiers check against the actual checkout and payment.

What is the difference between an intent mandate and a cart mandate?

In AP2 v0.1, an Intent Mandate captured the user's goals and limits (and a playback of their request) for purchases made while they were away, and a Cart Mandate captured the user's approval of an exact cart and price. In v0.2 these became open and closed forms of Checkout and Payment Mandates.

Does AP2 use W3C Verifiable Credentials?

Not in its current form. AP2 v0.2 specifies SD-JWT (RFC 9901) and SD-JWT VC for mandates, uses OpenID4VP for presenting user credentials, and says other formats such as ISO mobile documents could fill the same role. The issuer, holder and verifier model is similar to the W3C data model, but the encoding is different.

How is AP2 different from x402?

x402 uses HTTP 402 to request payment and carries a signed payment authorisation that a facilitator verifies and settles. AP2 proves what the user authorised. AP2's samples use x402 as a payment method, so they work together.

Can prompt injection make an AP2 agent buy something?

It can make an agent choose badly; the spec assumes injection cannot be prevented. AP2 limits the impact, because verifiers reject closed mandates that break the open mandate's constraints. Tight constraints are the defence.

Who is liable if an AI agent makes a wrong purchase under AP2?

AP2 does not decide that. It supplies signed mandates and receipts as evidence. The v0.1 spec said each payment network defines its own liability rules, and v0.2 leaves dispute handling outside its scope.

What does human not present mean in AP2?

The user approves open mandates with constraints in advance, and the agent later signs the closed mandates for a specific checkout with a key the user's open mandate named. Verifiers check the whole chain and every constraint.

How do I try AP2 without spending money?

Run a sample scenario from the official repository at a release tag, such as the human present card flow, which uses a stub card and a mock OTP on local agents.

Is AP2 a finished standard?

No. The current version is 0.2, and the FIDO Alliance's working groups are developing agent commerce specifications from it. Parts of the underlying formats are still Internet-Drafts, so expect changes.

Where Safeguard fits

Safeguard does not verify mandates, sign payments, detect prompt injection or judge agents, and it is not a fraud tool. The overlap is the software that does those jobs: the AP2 SDK, JOSE and SD-JWT libraries, cryptography, the A2A SDK, an agent framework and container base images. A flaw in the library that checks a signature is a flaw in your payment authorisation. Safeguard can scan those repositories and images (safeguard scan --dir ., safeguard scan --image ap2-merchant), match components against vulnerability databases, apply reachability analysis to rank what your code actually calls, show which projects carry a given library version, and gate builds with policies. The Safeguard CLI's assistant can also edit code and run commands with your approval, which suits upgrading a pinned SDK and rerunning the negative tests above.

Software supply chain hygiene matters here because mandate verification lives in a few small libraries that every role depends on, and the reference implementation is still young and changing between versions. The fit is indirect: it covers the code you build and ship around AP2, not the protocol's design or anyone's payment decisions.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

None of these demos shows an AP2 payment; they show Safeguard's agent surfaces handling tool access and approvals. You can download Safeguard and follow the CLI docs to try them.

This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. It mirrors the principle behind open mandates: give an agent a short, named list of what it may do, decided by a person, rather than broad access.

Click through it at your own pace, or open it full screen.

This is a real CLI session: asked to fix a lodash CVE, the CLI reads the finding and advisory, asks before each command, edits package.json, runs npm install and npm test with approval, and pushes nothing. The same flow applies when a JOSE or SD-JWT library under your AP2 verifier needs an upgrade: change the pin, rerun the negative mandate tests, and approve each step.

Click through it at your own pace, or open it full screen.

This demo sets up the runner on your own machine, approves it with its device code, and scans from the terminal. It suits the disposable machine you use for the AP2 samples: scan the cloned repository and its virtual environment locally before you run anything.

Click through it at your own pace, or open it full screen.

Quick check

An open Payment Mandate has an amount range of 0 to 20000 USD minor units and allows one payee. The agent closes it for a checkout totalling 203.99 dollars at that payee. Should the credential provider release a payment credential?

No. 203.99 dollars is 20399 minor units, which is above the maximum of 20000 (200.00 dollars). The credential provider must reject the Payment Mandate and return a Payment Receipt with an error, and the agent has to go back to the user or find a cheaper checkout.

In a human not present flow, a prompt-injected agent tries to use one open mandate to approve two different checkouts at once. Which AP2 rules stop it, and what must you build to make them work?

The spec says the agent must not present a new open mandate, or sign overlapping closed mandates, without a rejection receipt for the previous one, and that receipts must be integrity protected from the LLM. You need a deterministic signer outside the model that enforces this, plus verifiers that track presentations and budgets, because rejecting overlapping mandates is only a "MAY" for them.

Sources

Last reviewed: 23 October 2026. AP2 is at version 0.2 and is being developed further in FIDO Alliance working groups; check the linked specification and release notes for the current mandate formats before you build.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.