我们的合规检查器现已更新,支持欧盟人工智能法案的合规检查! 了解更多。

深入 Muse 的购买协议:你的 MCP 服务器必须暴露什么

2026/11/1

Tags: Muse, 购买协议, 智能体商务, MCP, 结账

Jules Kovac

Jules Kovac

Business Analyst, Founder

深入 Muse 的购买协议:你的 MCP 服务器必须暴露什么

 

深夜 11:47,Muse 拿到了夹克,却没有付款权限

一位买家告诉 Muse,自己想要一件两百美元以下的防雨外套。Muse 搜索、比较四件夹克、打开一个商品页、选好尺码、填好收货地址、走到订单复核页面,然后停了下来。总价就在屏幕上,卡也已经在档,什么都没发生。

Muse 并没有被拒绝。它撞上的是架构刻意划出的一条边界,而智能体商务中所有有意思的东西都落在这条边界的两侧。搜索是读取操作,答错不费一分钱。支付是写入操作,带着财务后果,因此需要自己的权限模型、自己的失败路径和自己的证据链。Meta 围绕这一区分构建了 Muse,Shopify 则把它的商家一侧写进了一个有版本、可测试、也相当不宽容的协议。

本文下面有两类来源。消费者流程、审批规则与钱包限额来自 Muse 内部智能体提示词语料的泄露副本,该副本以 asgeirtj/system_prompts_leaks 之名发布在 GitHub 上,并与 Meta 的工程文章、Stripe 的公告以及围绕二者的媒体报道做了交叉核对。商家侧的合约来自 Shopify 的智能体商务文档和 Universal Commerce Protocol 规范,我是逐页读完的,而不是看片段。两者冲突时,以协议为准,文中也会说明。

 

Muse 的五个步骤,以及第二步那堵墙

Meta 于 2026 年 9 月 8 日在美国推出 Muse,落地在 Muse 应用和 WhatsApp 之内。提供支付通道的 Stripe 三周后报告称,通过 Link 完成的智能体购买在一个月内增长了 38 倍。无论你怎么看待这款产品,这个体量都足以说明:支撑它的协议值得读一遍。

一笔购买由五个步骤承载。

查找与比较。 商品目录搜索不需要购买审批。Meta Catalog 有自己的搜索权限,默认设为允许,因此一个任务中的首次搜索可能询问一次,而这次批准覆盖该任务余下的部分。呈现结果不涉及任何资金流动。

结账。 后台浏览器任务驱动商家的结账流程,直到最终条款可供复核;对于支持智能体结账的目录商品,则通过 UCP 打开一个会话,不需要真实浏览器。创建结账同样不涉及资金流动。如果缺少尺码、颜色或型号,Muse 会询问。

复核。 最终商品、已选选项、配送与联系信息、总价和支付方式一起呈现。对于钱包支付,只有在钱包配置完成之后才会出现复核界面。

确认。 对于钱包支付,支付提供方的批准卡片就是确认。它授权的是那张已复核的订单,而 Muse 被明确要求不要在聊天中索取第二次确认。对于其他浏览器支付方式,买家在聊天中确认,一个简单的"是"即可接受。

完成。 获批之后,任务完成结账并提交订单。Shop Pay 返回一个一次性令牌。Stripe Link 发放一张为此笔购买注资的一次性虚拟卡。

墙就立在第二步。除了花钱,Muse 什么都能做;而花钱的权限稍后才到,从模型之外而来,绑定一笔交易和一个失效时间。

Shopper { # Shopper
  s1: circle label:"Ask for a jacket under 200 dollars"
  s2: rectangle label:"Approve one order one amount one method"
  s3: circle label:"Order confirmed"
  s4: circle label:"No order approval expired"
  s1.handle(right) -> Agent.a1.handle(left)
  a3.handle(bottom) -> s2.handle(top) [label="Approval card"]
  s2.handle(right) -> Agent.a4.handle(top) [label="Approved"]
  a4.handle(bottom) -> s4.handle(left) [label="Refused or late"]
}
Agent { # Agent
  a1: rectangle label:"Search and compare products"
  a2: rectangle label:"Prepare checkout and totals"
  a3: rectangle label:"Present reviewed order"
  a4: diamond label:"Approved within ten minutes"
  a5: rectangle label:"Pay with one-time credential"
  a6: circle label:"Submit order"
  a1.handle(right) -> a2.handle(left)
  a2.handle(right) -> a3.handle(left)
  a4.handle(right) -> a5.handle(left) [label="Yes"]
  a5.handle(right) -> a6.handle(left)
  a6.handle(bottom) -> Shopper.s3.handle(top) [label="Confirmation"]
}

 

让 Muse 的闸门成立的四条规则

一道 Muse 能靠话术绕过去的批准,就不算闸门。四条规则关上了这扇门,其中三条在对话之外强制执行。

每一次购买都要重新弹出确认。 批准绑定到那一笔具体的结账:同一商家、同一金额、同一支付选择。三者中任何一项改变,都会触发一张新的批准卡片。唯一的例外在卡片本身:买家可以另选一张已保存的钱包卡,此时批准即覆盖该选择。

批准不能被预先授予、批量授予或自动化。 对话中的一句友好同意不算批准,系统会拒绝任何被存储或可复用的消费授权。一个计划任务可以一路走到待批准的卡片,然后它就在那里等待。这就是无人值守故事的全部内容,而商家侧现在用自己的语言说了同一件事:一个没有买家在场的智能体发起令牌层调用会失败,因为 Shopify 没有买家 IP 地址的占位值,也不会退而使用智能体自己的地址。

批准的有效期很短。 一个待处理的结账大约十分钟后过期,过期后流程从搜索重新开始。另外,在浏览器任务中到达结账页面本身可能触发一次同意卡片;一旦它被批准,同一任务中、同一商家下后续的结账页面在约三小时内不会再询问。

浏览与消费是两套机制。 一个站点可以为浏览赢得按站点永久允许。消费永远不能。Meta 自己的文档把这一点说得很直白,协议也照此镜像:让智能体能准备购买的这项能力,并不是让它能完成购买的那项能力。

闸门之后是钱包限额。Link 通过 wallet.get_user_info 提供单笔限额以及日窗口和三十天窗口的限额,Muse 在每次购买时都重新读取,而不是引用一个更早的数字。Link 的购买保护适用于符合条件的订单:损坏、失窃或丢失最高 500 美元,降价最高 500 美元,退货运费与重新上架最高 250 美元,退款保障下最高 1,000 美元。这些计划属于 Stripe 而不属于 Meta,并且 Muse 被禁止告诉买家某笔具体购买受到保障。

 

商家一侧:四个能力族,五个端点

消费者协议只有在商家发布机器可读接口时才成立。这个接口就是 Universal Commerce Protocol,由 Google、Shopify、Etsy、Wayfair、Target、Walmart、Amazon、Microsoft、Meta 和 Stripe 为购物场景共同开发,运行在 MCP 之上的 JSON-RPC 2.0 上,REST 是另一种被认可的传输方式。

Shopify 用四个能力族实现它,由五个端点提供服务。如果你想看序列层面的同一套握手,本博客早前那份 UCP 流程地图 仍然成立;它早于的是购物车这部分接口,而大部分运营风险如今正落在这里。这个区分比数量更重要,因为中间两个能力族做的是不同的工作,带着不同的限额。

能力族 端点 工具 是否涉及资金
全球目录(Global Catalog)catalog.shopify.com/api/ucp/mcpsearch_catalog、get_product、lookup_catalog否
店铺目录(Storefront Catalog){shop}/api/ucp/mcp同样三个工具名,范围限定在单个商家否
购物车(Cart)商家 MCP 端点create_cart、get_cart、update_cart、cancel_cart否
结账(Checkout)商家 UCP 端点,/api/ucp/mcpcreate_checkout、get_checkout、update_checkout、complete_checkout、cancel_checkout仅 complete_checkout
订单(Order)商家 MCP 端点,外加 webhooksget_order否

这张表直接引出两个后果,而多数集成在第一次就把两个都做错了。

购物车用于思考,结账用于承诺。 购物车是长期存在、对未认证请求友好的容器:添加行项目、设置国家、估算总额、把购物车的 continue_url 分享给买家,并在多轮对话中持续迭代。结账则短暂、对新鲜度和幂等性更严格,限流也更狠。数字是公开的:全球目录流量为每个 API 客户端每秒 5 次请求,店铺目录流量按店铺限制。Shopify 在结账页上用一句话说清了:用 Cart MCP 迭代,把 Checkout MCP 留给已经准备购买的买家。一个一冲动就调用 create_checkout 的智能体,会把限流额度消耗在一个还在比较颜色的买家身上,而它损失的转化永远不会以错误的形式出现。

两者之间的转换是一个字段,而不是一次重建。 create_checkout 接受一个可选的 cart_id,把用 Cart MCP 建好的购物车变成一个结账会话。行项目不会被重建,总额也不由智能体重算。

Agent { # Agent
  b1: circle label:"Buyer starts shopping"
  b2: rectangle label:"Iterate lines and context on cart"
  b3: rectangle label:"Buyer commits to the order"
  b4: rectangle label:"Open a checkout from the cart"
  b5: rectangle label:"Complete once with the same key"
  b6: circle label:"Order placed"
  b1.handle(right) -> b2.handle(left)
  b2.handle(right) -> b3.handle(left)
  b3.handle(right) -> b4.handle(left)
  b4.handle(right) -> b5.handle(left)
  b5.handle(right) -> b6.handle(left)
  b2.handle(bottom) -> Business.c1.handle(top) [label="update_cart"]
  c1.handle(bottom) -> b3.handle(bottom) [label="Live totals"]
  b4.handle(bottom) -> Business.c2.handle(top) [label="create_checkout"]
  c2.handle(bottom) -> b5.handle(bottom) [label="ready_for_complete"]
}
Business { # Merchant API
  c1: rectangle label:"Cart tools answer at the highest rate limit"
  c2: rectangle label:"Checkout tools answer once then throttle"
}

 

协商、层级,以及谁才有权真正完成交易

下一个意外之处是:商家并不提供一份固定菜单。它进行协商。

你在一个 HTTPS URL 上发布平台档案,并在每个请求中通过 meta.ucp-agent.profile 引用它。商家在 /.well-known/ucp 发布自己的业务档案,声明协议版本、能力、支付处理器和签名密钥。Shopify 随后抓取并校验你的档案,检查版本是否对齐,把你声明的能力与店铺支持的能力求交集,并剪除任何父能力未能在交集中存活的扩展。协商由服务器选定。你暴露的是一份会被协商的合约,而不是一份会被列出的商品目录。

接下来是层级,它决定唯一在商业上重要的问题:这个智能体可以完成交易,还是必须把买家交还回去。Shopify 记录了三个层级,差别完全在于商家对调用者的身份了解多少。

层级 目录、购物车、结账工具 complete_checkout 订单工具
令牌(Token),具备购买权限可用,且与买家关联的令牌会个性化搜索并应用自动折扣可用可用,需 read_global_api_orders,范围限于你的智能体下的订单
已签名(Signed)可用不可用不可用
匿名(Anonymous)可用不可用不可用

这张表里藏着两个运营细节。令牌层请求必须在每一次 tools/call 上携带 Shopify-Buyer-IP 头,包括只读调用;IP 缺失或无效会返回 HTTP 422,没有回退,也没有占位。已签名和匿名流量保留读取与准备的权利,但完全失去完成能力,还失去大部分限流额度。一个说不出自己是谁的智能体仍然可以浏览目录、构建购物车,而这正是商家愿意给出的信任水平。

Agent { # Agent
  n1: circle label:"Call create_checkout with profile URI"
  n2: rectangle label:"Publish platform profile over HTTPS"
  n3: rectangle label:"Declare checkout and extensions"
  n4: diamond label:"Negotiated set includes checkout"
  n5: circle label:"Muse completes the order"
  n6: circle label:"Prepare only and hand back"
  n1.handle(right) -> n2.handle(left)
  n2.handle(right) -> n3.handle(left)
  n3.handle(bottom) -> Shopify.m1.handle(top) [label="meta.ucp-agent.profile"]
  m4.handle(bottom) -> n4.handle(top) [label="Active capability set"]
  n4.handle(bottom) -> n5.handle(top) [label="Token with permission"]
  n4.handle(right) -> n6.handle(left) [label="Read only"]
}
Shopify { # Shopify business
  m1: rectangle label:"Fetch and validate the profile"
  m2: diamond label:"Protocol versions align"
  m3: rectangle label:"Intersect capabilities"
  m4: rectangle label:"Prune orphan extensions"
  m5: circle label:"Return an error path"
  m1.handle(right) -> m2.handle(left)
  m2.handle(bottom) -> m3.handle(top) [label="Yes"]
  m2.handle(right) -> m5.handle(left) [label="No"]
  m3.handle(right) -> m4.handle(left)
}

 

你的接口必须满足的六项要求

语法是最容易的部分。下面六项决定这套集成能否活过第一个月,而每一项都是明文记录的,而不是推断出来的。

两个破坏性动词上的幂等性。 complete_checkout 与 cancel_checkout 要求在 meta["idempotency-key"] 中提供一个 UUID。一个遭遇网络超时的智能体并不知道订单是否存在,于是它重试;没有这个键,一次重试就变成第二笔订单。把该键当作意图的身份标识,而不是请求的标识:由结账会话加上意图推导它,在会话存续期间保留它,并在 429 之后重试时原样复用。

购物车用于迭代,结账用于承诺。 限流设计本身就是一条设计指令。购物车工具接受未认证请求,并以最高限额应答。结账工具在每个层级都被更狠地限流。把购物这一轮建立在购物车工具上,只有买家做出决定后才打开结账。

把升级当作一等答案。 一个结账携带 status 和一个 messages 数组,每条消息携带一个 severity。recoverable 意味着调用 update_checkout 并修正数据。requires_buyer_input 或 requires_buyer_review 意味着把 continue_url 交给买家。围绕这些严重级别写十二行代码,就替代了一个支持队列,而且其中没有一条是失败路径:3-D Secure、账户创建、年龄验证和会员门槛都以同样的方式到达,这是设计使然。

把价格、库存、运费和税费当作数据。 智能体无法谈判。每个响应都应当携带结账状态、版本或 updated-at 标记、币种,以及拆分为商品、运费和税费的总价。如果可售性或配送成本只存在于渲染后的页面里,结账会在最后一屏失败,而那时买家已经批准了一个总价。

诚实的身份,以及一个你能守住的层级。 说明调用者是谁,接受买家 IP 的要求,并按照你实际够格的层级来设计,而不是按路演材料里的那个层级。另一种结局是被封禁,Muse 在 Amazon 遇到的就是这件事。

一次扣款,有上限。 钱包路径发放一次性凭证,商家只扣一次。绝不存储智能体提供的凭证,也绝不授权买家没有看见过的金额。

状态生命周期值得单独一段,因为正是在这里,闸门从一个提示词里的段落变成了一种协议状态。

Agent { # Agent
  d1: circle label:"Checkout session opened"
  d2: rectangle label:"Fix missing data"
  d3: diamond label:"Buyer review required"
  d4: rectangle label:"Complete with the same key"
  d5: circle label:"Order completed"
  d6: circle label:"Session expired"
  d1.handle(right) -> d2.handle(left)
  d2.handle(right) -> d3.handle(left)
  d3.handle(bottom) -> Buyer.f1.handle(top) [label="requires_buyer_review"]
  f1.handle(right) -> f2.handle(left)
  f2.handle(bottom) -> d4.handle(top) [label="Yes"]
  f2.handle(right) -> f4.handle(left) [label="No"]
  f4.handle(bottom) -> d6.handle(top) [label="Abandoned"]
  d4.handle(right) -> d5.handle(left)
}
Buyer { # Buyer
  f1: rectangle label:"Open continue_url and review"
  f2: diamond label:"Buyer approves"
  f4: rectangle label:"Buyer closes the page"
}

五个状态是 incomplete、requires_escalation、ready_for_complete、completed 和 canceled。只有 ready_for_complete 允许 complete_checkout。其他任何状态要么通过 update_checkout 修正,要么通过 continue_url 交给买家,而一个没人完成的会话会过期。在你写下第一行提示词之前,先用一个 switch 语句处理这五个词,因为我见过的这个领域每一宗生产事故,都是落进 default 分支的第六种情况。

continue_url 也有一些读起来像安全建议的规则,因为它确实就是。解析它,拒绝任何不是 HTTPS 的地址;不要要求主机名与你调用的端点一致,因为它完全可以合法地落在店铺的 myshopify.com 域名、其结账域名或 shop.app 上。只与那位买家分享,并且不要把它写进日志。

 

商品目录是不可信输入

一个智能体店铺读取的是别人写的文本:标题、描述、评论正文、配送备注,在市场平台上还有第三方卖家想输入的任何内容。这些文本进入模型的上下文,于是它成了一个挂着支付的注入面。

规则无聊且绝对。目录内容是数据,永远不是指令。在它进入模型之前标记为不可信,对它跑一遍分类器,剔除任何读起来像指令的内容,并在任何写入之前检查出站。Muse 分层实施这一点:外部数据标记为不可信,一组独立训练的注入分类器集成,以及即使模型被说服越界也依然成立的确定性边界。注意这套设计为何有效:这些层在模型之外。一句"忽略目录中的指令"的提示词指令,是攻击者同样能控制的第四层。

 

智能体付款的三种方式

支付通道决定了商家和智能体各自能看到什么,而每一套商家集成都应该知道自己站在哪条通道上。Muse 跑在 Link 上;Agentic Commerce Protocol 是 OpenAI 一侧的对应物,同一套闸门逻辑在那里以不同的名字重新出现。

钱包令牌。 Shop Pay 返回一个安全的一次性令牌。商家只扣一次,智能体始终看不到卡号。支持的币种包括 USD、CAD、MXN 和 EUR。

钱包虚拟卡。 Stripe Link 发放一张为获批购买注资的一次性虚拟卡,智能体把它输入商家普通的卡片表单,所以商家不需要任何专门的按钮。Link 为该卡注资到不超过精确总价五个单位之上的最大整数,这部分余量永远不会被扣。这就是为什么商家不必是 Link 商家也能被购买。

浏览器接管。 如果两条钱包路径都失败,或者买家有已存档的卡片,智能体交出浏览器,买家在商家页面上输入支付信息。扣款是真实的。流程依然受限:智能体转述商品、运费、总价和已保存的支付方式,然后等待明确的确认。

Agent { # Agent
  p1: circle label:"Approval covers one purchase"
  p2: diamond label:"Wallet rail available"
  p3: rectangle label:"Mint a single-use credential"
  p4: circle label:"Buyer types the card in the browser"
  p1.handle(right) -> p2.handle(left)
  p2.handle(bottom) -> p3.handle(top) [label="Yes"]
  p3.handle(bottom) -> Merchant.q1.handle(top) [label="Credential"]
  p2.handle(top) -> p4.handle(bottom) [label="No"]
}
Merchant { # Merchant
  q1: rectangle label:"Verify merchant amount and method"
  q2: rectangle label:"Charge once and issue receipt"
  q3: circle label:"Payment settled"
  q1.handle(right) -> q2.handle(left)
  q2.handle(right) -> q3.handle(left)
}

 

什么先击倒了 Muse,以及什么会击倒你

有四类失败反复出现,没有一类是通常意义上的缺陷。

Muse 因身份被封。 亚马逊从 9 月 20 日那个星期日开始在其站点封禁 Muse,那是在发布十二天之后,也是 Patrick Wardle 的零日漏洞公开的同一个周末;Meta 在披露十二个多小时之后才发出热修复。亚马逊封禁的明面理由并不是这个漏洞。该智能体在浏览时没有表明自己的身份,而亚马逊事先也没有被告知 Muse 会访问其商店。亚马逊的原则是:代表客户购物的第三方应用应当公开运作,并尊重提供方是否愿意参与。如果你的接口说不出调用者是谁,就等着同样的回答,而且要快。

批准在买家行动之前就过期了。 十分钟对一次卡片点击很宽裕,对新设备上的一次 3-D Secure 挑战则偏紧。正确的做法是从复核重新开始,而不是复用那张过期的批准,并告诉买家原因。

协商会悄悄移除结账能力。 能力求交在剪掉你依赖的那项能力之前,一直是个好特性。对你实际收到的协商范围做埋点,与发布说明里的承诺做对比,并对差异告警。

浏览器路径会弹出一张没人预料到的同意卡片。 当智能体驱动真实浏览器并落到结账页面时,客户端可以发起自己的同意请求,独立于支付批准。有些团队把它读成双重确认,于是砍掉两者之一。两者都保留:一个属于客户端、覆盖站点,另一个属于支付、覆盖金额。

 

上线顺序

如果你这个季度要做商家侧,能扛住截止日期的那套顺序是这样的。

  1. 先发布业务档案和只读接口:先目录,再购物车。
  2. 让 complete_checkout 和 cancel_checkout 幂等,并用同一个键对沙盒订单重放来证明它。
  3. 在你接受第一笔真实支付之前,返回带有可用 continue_url 的 requires_escalation。
  4. 对协商范围和实际收到的工具调用做埋点,然后与发布说明核对。
  5. 只有到那时才暴露结账完成能力,并且只在你守得住的层级上。

对 Shopify 商家来说,决定有一半已经替你做完了:通过 Meta 直接结账对符合条件的店铺默认开启,可以关闭,关闭之后买家只是被重定向到你的店铺页面。资格取决于你销售所覆盖的国家,加拿大在名单上。没有替你做的是那场内部对话:当买家从不访问你的站点时,你的退货政策、库存数据和履约承诺是否还站得住。

 

小结

  • Muse 的闸门就是协议。 五个步骤,只有最后两步涉及资金,而花钱的权限绑定到一个商家、一个金额、一种支付方式,限期约十分钟。
  • 商家侧是一份经过协商的合约,含四个能力族。 目录用于发现,购物车用于迭代,结账用于承诺,订单用于凭证。多数团队把中间两个搞反了,然后去怪模型。
  • 大多数生产故障都是合约故障。 缺失的幂等、过期的批准、静默的能力剪除、说不出自己是谁的智能体,以及一个把 requires_escalation 吞掉的 default 分支。

 

资料来源

返回所有博客文章