Skip to content
目录

能力发现与协商机制

概述

UCP 的核心创新之一是动态能力发现和协商机制。这个机制使得平台可以自主发现商家支持的能力,并通过协商确定双方共同支持的能力集合,从而实现无许可集成(Permissionless Onboarding)。

能力发现流程

1. 商家 Profile 发布

商家在 /.well-known/ucp 端点发布自己的 Profile,声明支持的能力、服务和支付处理器。

Profile 结构

json
{
  "ucp": {
    "version": "2026-01-23",
    "services": {
      "dev.ucp.shopping": [
        {
          "version": "2026-01-23",
          "spec": "https://ucp.dev/.../specification/overview",
          "transport": "rest",
          "endpoint": "https://business.example.com/api/v2",
          "schema": "https://ucp.dev/.../rest.openapi.json"
        }
      ]
    },
    "capabilities": {
      "dev.ucp.shopping.checkout": [
        {
          "version": "2026-01-23",
          "spec": "https://ucp.dev/.../specification/checkout",
          "schema": "https://ucp.dev/.../schemas/shopping/checkout.json"
        }
      ],
      "dev.ucp.shopping.fulfillment": [
        {
          "version": "2026-01-23",
          "spec": "https://ucp.dev/.../specification/fulfillment",
          "schema": "https://ucp.dev/.../schemas/shopping/fulfillment.json",
          "extends": "dev.ucp.shopping.checkout"
        }
      ]
    },
    "payment_handlers": { ... }
  },
  "signing_keys": [ ... ]
}

关键字段

  • version:协议版本(日期格式 YYYY-MM-DD)
  • services:支持的服务和传输绑定
  • capabilities:支持的能力和扩展
  • payment_handlers:支付处理器配置
  • signing_keys:用于验证签名的公钥

2. 平台 Profile 声明

平台在每次请求中通过 UCP-Agent header 声明自己的 Profile URI。

REST 传输

http
POST /checkout-sessions HTTP/1.1
UCP-Agent: profile="https://platform.example/profiles/shopping-agent.json"
Content-Type: application/json

MCP 传输

json
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "create_checkout",
    "arguments": {
      "meta": {
        "ucp-agent": {
          "profile": "https://platform.example/profiles/shopping-agent.json"
        }
      },
      "checkout": { ... }
    }
  }
}

3. Profile 获取和验证

商家收到请求后:

  1. 获取 Platform Profile

    • UCP-Agent header 提取 Profile URI
    • 如果未缓存,则获取 Platform Profile
    • 验证 Profile 格式和签名
  2. 验证要求

    • Profile URL 必须使用 HTTPS
    • 不允许重定向(3xx)
    • 必须包含有效的 JSON Schema
    • 签名密钥必须有效
  3. 缓存策略

    • 最小 TTL 60 秒
    • 支持 stale-while-revalidate
    • 固定大小的 LRU 缓存

能力协商算法

协商流程

能力协商遵循 server-selects 架构,即商家(服务器)决定激活的能力集合。

┌─────────────┐                    ┌─────────────┐
│   Platform  │                    │   Business  │
└──────┬──────┘                    └──────┬──────┘
       │                                   │
       │ 1. 请求 + Platform Profile URI    │
       ├──────────────────────────────────>│
       │                                   │
       │                   2. 获取 Platform Profile
       │                                   │
       │                   3. 计算能力交集
       │                                   │
       │                   4. 版本选择
       │                                   │
       │                   5. 修剪孤立扩展
       │                                   │
       │ 6. 响应 + 激活的能力列表            │
       │<──────────────────────────────────┤

交集算法详解

能力交集算法确定哪些能力在会话中激活:

步骤 1:计算交集

对于商家的每个能力,如果平台也声明了同名能力,则包含在结果中。

python
def compute_intersection(business_capabilities, platform_capabilities):
    intersection = {}
    for name, business_versions in business_capabilities.items():
        if name in platform_capabilities:
            intersection[name] = {
                'business': business_versions,
                'platform': platform_capabilities[name]
            }
    return intersection

示例

  • 商家支持:checkout, fulfillment, discount
  • 平台支持:checkout, cart, discount
  • 交集:checkout, discount

步骤 2:版本选择

对于交集中的每个能力,计算双方都支持的版本集合,选择最高版本。

python
def select_version(business_versions, platform_versions):
    # 计算共同版本
    common_versions = set(business_versions) & set(platform_versions)
    
    if not common_versions:
        return None  # 无共同版本,排除该能力
    
    # 选择最高版本(日期格式,最新日期)
    return max(common_versions)

版本格式YYYY-MM-DD(日期格式)

示例

  • 商家支持:["2026-01-11", "2026-01-23"]
  • 平台支持:["2026-01-11", "2026-01-23", "2026-02-01"]
  • 共同版本:["2026-01-11", "2026-01-23"]
  • 选择版本:2026-01-23

步骤 3:修剪孤立扩展

移除任何 extends 字段存在但父能力不在交集中的扩展。

python
def prune_orphaned_extensions(intersection):
    active_capabilities = set(intersection.keys())
    pruned = {}
    
    for name, data in intersection.items():
        capability = data['business'][0]  # 假设选择第一个版本
        
        # 检查扩展依赖
        if 'extends' in capability:
            parents = capability['extends']
            if isinstance(parents, str):
                parents = [parents]
            
            # 检查是否至少有一个父能力在交集中
            if any(parent in active_capabilities for parent in parents):
                pruned[name] = data
        else:
            # 根能力,直接包含
            pruned[name] = data
    
    return pruned

扩展依赖规则

  • 单父扩展:extends: "dev.ucp.shopping.checkout" → 父能力必须在交集中
  • 多父扩展:extends: ["checkout", "cart"] → 至少一个父能力必须在交集中

步骤 4:重复修剪

重复步骤 3,直到没有更多能力被移除(处理传递性扩展链)。

传递性示例

  • extension_a 扩展 checkout
  • extension_b 扩展 extension_a
  • 如果 checkout 不在交集中,则 extension_aextension_b 都需要移除

完整算法实现

python
def negotiate_capabilities(business_profile, platform_profile):
    """
    能力协商算法
    
    Args:
        business_profile: 商家 Profile
        platform_profile: 平台 Profile
    
    Returns:
        激活的能力集合
    """
    business_caps = business_profile['ucp']['capabilities']
    platform_caps = platform_profile['ucp']['capabilities']
    
    # 步骤 1:计算交集
    intersection = {}
    for name, business_versions in business_caps.items():
        if name in platform_caps:
            intersection[name] = {
                'business': business_versions,
                'platform': platform_caps[name]
            }
    
    # 步骤 2:版本选择
    active_capabilities = {}
    for name, data in intersection.items():
        business_versions = [v['version'] for v in data['business']]
        platform_versions = [v['version'] for v in data['platform']]
        
        common_versions = set(business_versions) & set(platform_versions)
        if common_versions:
            selected_version = max(common_versions)
            # 选择对应的能力定义
            business_def = next(v for v in data['business'] 
                              if v['version'] == selected_version)
            active_capabilities[name] = business_def
    
    # 步骤 3-4:修剪孤立扩展(重复直到稳定)
    changed = True
    while changed:
        changed = False
        active_names = set(active_capabilities.keys())
        
        to_remove = []
        for name, capability in active_capabilities.items():
            if 'extends' in capability:
                parents = capability['extends']
                if isinstance(parents, str):
                    parents = [parents]
                
                if not any(p in active_names for p in parents):
                    to_remove.append(name)
                    changed = True
        
        for name in to_remove:
            del active_capabilities[name]
    
    return active_capabilities

命名空间治理

反向域名命名

UCP 使用反向域名命名将治理权限直接编码到能力标识符中,无需中央注册表。

命名格式

{reverse-domain}.{service}.{capability}

组件

  • {reverse-domain}:从域名所有权派生的权限标识符
  • {service}:服务/垂直类别(如 shoppingcommon
  • {capability}:具体能力名称

示例

  • dev.ucp.shopping.checkout:UCP 官方结账能力
  • dev.ucp.shopping.fulfillment:UCP 官方履约能力
  • com.example.payments.installments:供应商自定义分期付款能力

Spec URL 绑定

能力的 specschema 字段的 URL 源必须匹配命名空间权限。

规则

  • dev.ucp.*https://ucp.dev/...
  • com.example.*https://example.com/...

验证

  • 平台必须验证此绑定
  • 如果源不匹配,应拒绝该能力

治理模型

命名空间模式权限治理
dev.ucp.*ucp.devUCP 治理机构
com.{vendor}.*{vendor}.com供应商组织
org.{org}.*{org}.org组织

dev.ucp.* 命名空间保留给 UCP 治理机构批准的能力。供应商必须使用自己的反向域名命名空间定义自定义能力。

Schema 解析流程

解析步骤

平台必须按照以下顺序解析 Schema:

  1. 发现:从 /.well-known/ucp 获取商家 Profile
  2. 协商:计算能力交集
  3. 获取 Schema:获取基础 Schema 和所有激活的扩展 Schema
  4. 版本兼容性:验证扩展 Schema 的 requires 约束
  5. 组合:通过 allOf 链合并 Schema
  6. 验证:根据组合后的 Schema 验证请求和响应

Schema 组合规则

扩展 Schema 模式

扩展 Schema 使用 allOf 定义组合类型,$defs 键必须使用完整的父能力名称:

json
{
  "$defs": {
    "discounts_object": { ... },
    "dev.ucp.shopping.checkout": {
      "title": "Checkout with Discount",
      "allOf": [
        {"$ref": "checkout.json"},
        {
          "type": "object",
          "properties": {
            "discounts": {
              "$ref": "#/$defs/discounts_object"
            }
          }
        }
      ]
    }
  }
}

要求

  • 扩展 Schema 必须为 extends 中声明的每个父能力提供 $defs 条目
  • $defs 键必须与父能力的完整名称完全匹配

解析约定

要验证 payload,实现按以下方式解析扩展 Schema:

  1. 从操作确定根能力(如结账操作使用 dev.ucp.shopping.checkout
  2. 对于每个激活的扩展,解析并应用其 $defs[{root_capability}]

示例:结账响应包含折扣扩展

  • 根能力:dev.ucp.shopping.checkout
  • 扩展 Schema:discount.json
  • 解析:discount.json#/$defs/dev.ucp.shopping.checkout

版本依赖

扩展 Schema 可以声明 requires 对象来指示所需的协议和能力版本:

json
{
  "name": "com.acme.shopping.loyalty",
  "requires": {
    "protocol": { "min": "2026-01-23" },
    "capabilities": {
      "dev.ucp.shopping.checkout": { "min": "2026-06-01" }
    }
  }
}

约束格式

  • min:最小版本(必需,包含)
  • max:最大版本(可选,包含)

验证

  • 如果 requires 存在,平台和商家必须验证协商的协议版本和能力版本满足声明的约束
  • 不兼容的扩展从激活能力集中排除

响应中的能力声明

能力选择规则

商家必须在响应的 ucp.capabilities 中仅包含:

  1. 在此会话的协商交集中的能力,
  2. 与此响应的操作类型相关的能力

根能力相关性

根能力如果匹配操作类型,则相关:

  • create_checkout / update_checkout / complete_checkoutdev.ucp.shopping.checkout
  • create_cart / update_cartdev.ucp.shopping.cart
  • Order webhooks → dev.ucp.shopping.order

扩展相关性

如果扩展的 extends 值中任何一个匹配相关根能力,则扩展相关。

选择示例

响应类型包含不包含
Checkoutcheckout, discount, fulfillmentcart, order
Cartcart, discountcheckout, fulfillment, order
Orderordercheckout, cart, discount

错误处理

协商错误类型

1. 发现失败

商家无法获取或解析平台的 Profile。

错误代码

  • invalid_profile_url:Profile URL 格式错误、缺失或无法解析
  • profile_unreachable:URL 可解析但获取失败(超时、非 2xx)
  • profile_malformed:获取的内容不是有效的 JSON 或违反 Schema

HTTP 状态码

  • REST:400, 424, 422
  • MCP:-32001

2. 协商失败

提供的 Profile 有效但能力交集为空或版本不兼容。

错误代码

  • version_unsupported:平台的协议版本不受支持
  • capabilities_incompatible:交集中没有兼容的能力

HTTP 状态码

  • REST:422(版本不支持)或 200(能力不兼容)
  • MCP:-32001(版本不支持)或 result(能力不兼容)

continue_url 字段

当 UCP 协商失败时,continue_url 提供回退 Web 体验。

使用场景

  • 结账操作:链接到购物车或结账页面
  • 目录操作:链接到产品或搜索结果
  • 回退:链接到店面首页

这实现了优雅降级——代理可以将买家重定向到标准 Web 界面完成任务。

性能优化

Profile 缓存

商家端

  • 维护预批准平台的注册表
  • 使用固定大小的 LRU 缓存
  • 最小 TTL 60 秒
  • 支持 stale-while-revalidate

平台端

  • 缓存商家 Profile
  • 遵循 HTTP Cache-Control 指令
  • 最小 TTL 60 秒

异步发现

商家可以实现异步 Profile 发现:

  1. 收到未知平台的请求
  2. 返回 503 状态码和 Retry-After header
  3. 在后台解析 Profile
  4. 平台重试时,已验证的 Profile 已缓存

这限制了资源消耗,同时保持响应性。

总结

能力发现与协商机制是 UCP 的核心创新,它实现了:

  1. 无许可集成:无需预先注册即可集成
  2. 动态适配:通过协商自动确定共同支持的能力
  3. 版本管理:支持独立的能力版本控制
  4. 扩展支持:通过依赖修剪确保扩展正确激活
  5. 性能优化:通过缓存和异步发现提高效率

这种设计使得 UCP 能够支持快速集成和灵活的功能组合,同时保持安全性和可扩展性。

MIT License.