跳到主要内容

AP2 — 并存的两代数据模型(诚实章)

这一章解释一个会让初读者困惑的事实:同一个仓库里有两套 mandate 模型,名字都不一样。 不是 bug,是协议从 v0.1 走向 v0.2 的演进现场。读懂它你才能正确地把「文档说的」对到「代码做的」。

1. 两套模型,一眼对照

仓库里两条 import 路径,代表两代设计:

旧代:ap2/models/新代:ap2/sdk/generated/
mandate 类型IntentMandate / CartMandate / PaymentMandateOpenCheckoutMandate / CheckoutMandate / OpenPaymentMandate / PaymentMandate
怎么定义手写 Pydantic 模型由 JSON Schema 用 datamodel-codegen 生成
安全绑定方式字段里塞商家签的 JWT + 哈希(merchant_authorization / user_authorization)整条 SD-JWT-VC 委托链,跳间用 sd_hash
版本标记vctvct(如 mandate.payment.1)做 schema 版本
对应规范v0.1 时代的 Cart/Intent 概念规范 v0.2(specification.md 的 Checkout/Payment Mandate)
文件位置code/sdk/python/ap2/models/mandate.pycode/sdk/python/ap2/sdk/generated/*.py

旧代的 mandate(回顾)

PaymentMandate 是个两段式结构:payment_mandate_contents(明文数据)+ user_authorization(对 cart+payment 双哈希的可验证表述)(code/sdk/python/ap2/models/mandate.py:167-203)。CartMandate 则把商家担保塞进 merchant_authorization JWT,内含 cart_hash(mandate.py:107-136)。注意它复用了 W3C Payment Request API 的对象(PaymentRequest/PaymentResponse,code/sdk/python/ap2/models/payment_request.py:184,204)——这是它「贴着浏览器电商生态」的痕迹。

新代的 mandate(回顾)

PaymentMandate 是个干净的扁平模型,带 vct='mandate.payment.1'transaction_id(= checkout_jwt 的哈希)、payeepayment_amount(整数最小货币单位)、payment_instrument 等(code/sdk/python/ap2/sdk/generated/payment_mandate.py:16-55)。它不自带签名字段——签名和绑定全交给外层的 SD-JWT 链(第 02 章)。

2. 哪套用在哪(真实 grep 结果)

这不是猜测,是仓库里 import 的事实:

样例角色用哪套模型传输
shopping_agent(原始)ap2.models(Intent/Cart) + ap2.sdkA2A
merchant_agent(原始)ap2.models + ap2.sdkA2A
shopping_agent_v2ap2.sdk(SD-JWT 链)A2A
*_mcp 角色(merchant/credentials/mpp/x402)ap2.sdkMCP

原始 A2A 样例的子 agent(shopper / payment_method_collector / catalog_agent)仍 import ap2.models(code/samples/python/src/roles/shopping_agent/subagents/shopper/tools.py 等),而 shopping_agent_v2 和所有 MCP 角色走 ap2.sdk(code/samples/python/src/roles/shopping_agent_v2/shopping_agent/mandate_tools.pycode/samples/python/src/roles/*_mcp/server.py)。

给 agent 的实用判断: 看到 IntentMandate/CartMandate/PaymentRequest → 旧 A2A 路径;看到 OpenPaymentMandate/MandateClient/vct → 新 SD-JWT 路径。规范 v0.2(specification.md)描述的是新路径;旧路径是过渡期的参考实现。

3. 为什么会并存(推断)

规范头部写明是 v0.2(specification.md:1),并明确用 SD-JWT 承载 Checkout/Payment Mandate(specification.md:106-107,396-401),还引入了 vct schema 版本号(specification.md:137-143)。SDK README 也整体围绕 SD-JWT/dSD-JWT 重写(code/sdk/python/ap2/sdk/README.md:1-7)。

但仓库本质是 「code samples and demos」(README.md:11),原始 A2A 演示是较早写就、贴着 W3C Payment Request + 商家签 JWT 的那套;新的 SD-JWT 运行时和 shopping_agent_v2、MCP 角色是后来对齐 v0.2 加上的。两者没有互删,于是同仓共存。(此段为基于版本号、import 分布、README 重写迹象的合理推断 (inferred);仓库里没有一处明文写「我们正在迁移」。)

4. vct 版本控制:新代的演进保险

新代埋了一个面向未来的机制:每个 mandate 用 vct 声明 schema 版本,带数字后缀(mandate.payment.1mandate.checkout.open.1)。规范要求实现精确匹配整个 vct 串(含版本后缀),未来不兼容的修订会换新后缀(.2),让新旧版本无歧义区分(specification.md:137-143)。代码里 vct 就是个带默认值的 Literal 字段(code/sdk/python/ap2/sdk/generated/payment_mandate.py:21-24)。

这正是「文档随上游演进而能区分新旧」的协议级保险——和本库「引用带符号名以抗行号漂移」是同一种思路。

5. 横向对比(ai-protocol-reference shelf 内)

AP2 在协议库里的独特取舍:

  • 传输无关 vs 传输绑定。 AP2 刻意不绑传输——示例同时跑 A2A 和 MCP(code/samples/python/src/common/a2a_extension_utils.py:17 定义了 A2A 扩展 URI)。它是「叠加在 commerce 协议之上的安全层」,与 A2A / MCP 是正交关系:A2A/MCP 管「agent 怎么对话」,AP2 管「这笔钱凭什么算授权」。
  • 凭证密码学 vs 会话密码学。 不少协议靠 TLS / OAuth token 保会话;AP2 把信任做进可离线核验的凭证本身(SD-JWT 委托链),因为它假设中间的 LLP agent 就是攻击面,会话级信任不够。
  • 选择性披露作一等公民。 用 SD-JWT 让 agent 「只露验证必需字段」,把隐私最小化做进协议机制,而非靠各方自觉。

6. 边界与诚实

  • 本章「为什么并存」是推断,见 §3 标注。代码里没有迁移说明文档。
  • ap2/models 是否会被删、新旧是否长期共存,代码里看不出计划。
  • 两套模型的字段并非一一对应(旧 CartMandate 含完整 W3C PaymentRequest,新 CheckoutMandate 把 checkout 装进一个被 sd_hash 绑的 checkout_jwt),迁移不是机械改名。

7. 代码地图

主题文件符号名
旧代模型code/sdk/python/ap2/models/mandate.pyIntentMandate CartMandate PaymentMandate
旧代 W3C 对象code/sdk/python/ap2/models/payment_request.pyPaymentRequest PaymentResponse PaymentItem
新代闭支付模型code/sdk/python/ap2/sdk/generated/payment_mandate.pyPaymentMandate (vct='mandate.payment.1')
新代开支付模型code/sdk/python/ap2/sdk/generated/open_payment_mandate.pyOpenPaymentMandate AmountRange Budget
新代 checkout 模型code/sdk/python/ap2/sdk/generated/checkout_mandate.pyCheckoutMandate
新代开 checkout 模型code/sdk/python/ap2/sdk/generated/open_checkout_mandate.pyOpenCheckoutMandate LineItems
A2A 扩展标识code/samples/python/src/common/a2a_extension_utils.pyEXTENSION_URI
v2 样例 mandate 工具code/samples/python/src/roles/shopping_agent_v2/shopping_agent/mandate_tools.py(uses ap2.sdk)
规范 vct 版本控制docs/ap2/specification.md(Mandate Versioning)