Skip to content

[Proposal]: Restrict IntentMandate Visibility to User ↔ Shopping Agent Boundary #180

@kukgini

Description

@kukgini

Background

The current AP2 specification (Section 5.2, Step 8) requires the Shopping Agent to forward the full IntentMandate to Merchant Agents during the discovery and negotiation phase. The reference implementation confirms this design — the Shopping Agent system prompt explicitly states: "Note that this information will be shared with the merchant."

This means merchants receive the user's natural_language_description, intent_expiry, requires_refundability, budget-related signals, and potentially SKU/merchant filters — all before any purchase commitment is made.

While this design provides merchants with context to construct a CartMandate, it conflates two distinct concerns: what the user wants (intent) and what the merchant offers (catalog response). This proposal argues that these should be separated at the protocol level.

Problem: Misaligned Responsibility Boundaries and Unnecessary Data Exposure

1. Verification Responsibility Leaks to Merchants

Under the current design, if a CartMandate deviates from the user's original intent, who is responsible for detecting the mismatch? The specification's threat model (Section 7) describes a scenario where:

"The Shopping Agent autonomously purchases an item that violates the user's signed Intent Mandate (e.g., exceeds budget or is the wrong item)."

The expected resolution relies on comparing the IntentMandate against the cart transaction details. However, if the merchant also holds the IntentMandate, the verification surface expands unnecessarily. The merchant could argue compliance with stated intent, introducing ambiguity into dispute resolution. Merchants should not be in a position to interpret — or misinterpret — user intent.

2. Dispute Isolation

In the current model, disputes arising from intent mismatches could involve three parties: User, Shopping Agent provider, and Merchant. If the IntentMandate remains exclusively within the User ↔ Shopping Agent boundary:

  • Intent-level disputes (agent didn't follow instructions) are cleanly isolated between the User and the Shopping Agent service provider.
  • Fulfillment-level disputes (merchant didn't deliver what was agreed) remain between the User/SA and the Merchant, grounded in the CartMandate — which the merchant did sign.

This creates a clearer liability structure: the Shopping Agent is accountable for faithfully translating user intent into shopping actions, and the Merchant is accountable for fulfilling the terms of the CartMandate it signed. Neither party needs visibility into the other's contractual boundary with the user.

3. Privacy — Data Minimization Beyond Linkability

Issue #120 correctly identifies cross-merchant linkability as a risk when IntentMandate signatures act as a "super-cookie." However, even if linkability is solved (e.g., via BBS+ anonymous credentials), the content of the IntentMandate itself remains exposed. This includes:

  • Natural language purchase intent — reveals user preferences, urgency, and context
  • Budget signals — if [Feat]: Standardized budget limitation field #133's standardized budget field is adopted and forwarded to merchants, it directly enables price discrimination
  • Refundability requirements — signals risk tolerance
  • TTL / expiry — reveals time pressure

These are not fields the merchant needs to construct a catalog response. The Shopping Agent can translate intent into structured queries (product search, price comparison) without revealing the underlying user mandate.

Proposed Solution: Intent as a Private Contract, Queries as the Public Interface

Core Principle

The IntentMandate should function as a private contract between the User and Shopping Agent — it defines the agent's authority and constraints. The Shopping Agent then independently interacts with merchants using standard discovery mechanisms (catalog search, price queries) without forwarding the mandate.

Suggested Flow Changes

Current flow (Section 5.2, Steps 7–9):

User → SA: IntentMandate (signed)
SA → MA: IntentMandate          ← merchant receives full intent
MA → SA: CartMandate (signed by merchant)

Proposed flow:

User → SA: IntentMandate (signed, retained by SA)
SA → MA: Product query / catalog search (derived from intent, minimal disclosure)
MA → SA: CartMandate (signed by merchant)
SA:       Validates CartMandate against IntentMandate locally

What Changes in the Protocol

  1. IntentMandate is no longer transmitted to Merchant Agents. It remains a credential between the User and Shopping Agent, used for:

    • SA's internal decision-making (what to search for, what constraints to enforce)
    • Post-transaction audit trail (proof that SA acted within authorized scope)
    • Dispute resolution between User and SA provider
  2. Shopping Agent → Merchant communication uses derived queries. The SA translates intent into merchant-facing requests (e.g., search_catalog skill calls, structured product queries). The merchant responds based on its catalog, not on user intent metadata.

  3. CartMandate validation becomes the SA's responsibility. The SA checks whether the merchant's CartMandate satisfies the IntentMandate constraints before presenting it to the user (HP flow) or proceeding autonomously (HNP flow). This is already implicitly the SA's role — this proposal makes it explicit.

  4. The cryptographic evidence chain adjusts. Instead of IntentMandate → CartMandate → PaymentMandate as a single forwarded chain, the structure becomes:

    • User ↔ SA boundary: IntentMandate (user-signed authority grant)
    • SA ↔ Merchant boundary: CartMandate (merchant-signed offer) + PaymentMandate (user-signed payment authorization)
    • The IntentMandate serves as SA-held evidence, not a merchant-facing credential.

Impact on Mandate Types in src/ap2/types/mandate.py

The IntentMandate class would gain a conceptual scope annotation (e.g., documentation or a visibility field) indicating it is not intended for merchant transmission. The CartMandate and PaymentMandate remain unchanged — they are already scoped to the SA ↔ Merchant and SA ↔ Payment boundaries respectively.

Trade-offs and Counterarguments

"Merchants need intent context to provide better offers."
The Shopping Agent can selectively convey relevant requirements (e.g., product category, price range, delivery timeline) through structured queries without exposing the full mandate. This is analogous to how a human shopper asks a store clerk for help without showing them their bank statement.

"The IntentMandate proves the agent has user authorization to shop."
This is a valid concern, especially for HNP flows where the merchant may want assurance that the agent isn't acting without authority. However, this can be addressed by a lightweight authorization proof — a derived token or zero-knowledge attestation proving that a valid mandate exists, without revealing its contents. Issue #120's BBS+ proposal could serve this exact purpose: prove authorization without exposing intent.

"This breaks the cryptographic evidence chain for dispute resolution."
The evidence chain becomes partitioned, not broken. The User can still prove what they authorized (IntentMandate), the SA can prove it acted within scope (IntentMandate + CartMandate comparison), and the Merchant can prove what it offered (CartMandate). The key insight is that the Merchant never needed the IntentMandate to fulfill its role in the chain — the CartMandate is the merchant's binding commitment.

Related Issues

Additional Context

This proposal is complementary to #120, not a replacement. #120 solves "who sent this intent?" (identity privacy). This proposal asks a more fundamental question: "should the merchant receive the intent at all?" (data minimization). Both can coexist — if partial exposure is preferred over full restriction, #120's anonymous credentials combined with #127's schema-driven selective disclosure could provide a middle ground.

The approach aligns with the protocol's own design principle stated in the specification: "responsibility is attributed to the real-world entities (users, merchants, issuers)" — not to intermediary agents. If the Shopping Agent is the user's delegate for intent execution, keeping the intent mandate within that delegation boundary is the natural consequence of this principle.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions