数据截至 (上游 commit 9ed9049a14d9)
UCP — 能力、扩展与命名治理
本章讲 UCP 的“名词与动词系统”:怎么命名、怎么把功能切成能力(capability)和扩展(extension),以及扩展如何在 schema 层面拼到父能力上。
1. 反向域名命名:把治理写进名字
所有能力/服务名都用反向域名格式:
{reverse-domain}.{service}.{capability}
例:dev.ucp.shopping.checkout
这一招很关键——它消灭了中央注册中心。谁拥有域名,谁就掌管自己的命名空间:
| 名字 | 权威域名 | 谁治理 |
|---|---|---|
dev.ucp.shopping.checkout | ucp.dev | UCP 治理机构 |
dev.shopify.catalog | shopify.dev | Shopify |
com.example.payments.installments | example.com | example.com 自己 |
dev.ucp.* 是保留给 UCP Tech Council 的; 任何厂商都能在自己的域名下定义能力(org.acme.*),无需 UCP 批准。来源:docs/documentation/core-concepts.md:341-344、docs/specification/overview/index.md:955-966。
安全绑定(必记): 能力声明里的 schema URL 必须来自命名权威域名——dev.ucp.* 的 schema 必须挂在 https://ucp.dev/...(按标签对齐的派生算法校验,禁止子串匹配)。平台 MUST 校验这层绑定,否则会被伪造能力攻击。注意:新规范已把 spec(人读文档)URL 移出绑定——它只要求 https、可挂在任意主机;绑定只保「出处(provenance)」,不保「可信」。来源:docs/specification/overview/index.md:831-853、docs/documentation/core-concepts.md:326-340。
2. 三件套:Capability / Extension / Service
别把这三个搞混——它们职责不同:
- Capability(能力) = 协议的“动词”:可独立发现、协商、调用的功能单元,可独立版本化。如 checkout、cart、order。
- Extension(扩展) = 可选增强:用
extends声明父能力,靠 JSON SchemaallOf组合到父 schema 上。如 discount、fulfillment、ap2_mandate。 - Service(服务) = 一个垂直域(如
dev.ucp.shopping)的操作集合,声明有什么功能;而怎么访问由传输绑定决定。
来源:docs/documentation/core-concepts.md:128-217。
一个服务可挂多种传输绑定,平台按场景挑:
| 传输 | 描述格式 | 适合谁 |
|---|---|---|
| REST | OpenAPI 3.1.0 | 标准服务端对接 |
| MCP | OpenRPC | AI agent(Model Context Protocol) |
| A2A | Agent Card | Agent-to-Agent 集成 |
| Embedded | OpenRPC | 嵌入式集成 |
来源:docs/documentation/core-concepts.md:200-207。注意传输绑定 MUST 是“薄”的——只声明方法名、只引用基础 schema,不得内联枚举字段。docs/specification/overview/index.md:991-992、:1089-1091。
3. 扩展怎么拼到能力上(核心机制)
这是本章最该学的一点。一个扩展 schema 要在它的 $defs 里,为每个父能力建一个键,键名就是父能力全名,值用 allOf 把“父能力基础 schema”和“本扩展新增字段”拼起来。
真实实现:discount 扩展
看折扣扩展怎么挂到 checkout 和 cart 上(source/schemas/shopping/discount.json:124-145):
{
"name": "dev.ucp.shopping.discount",
"$defs": {
"discounts_object": { "...": "折扣码输入 + 已应用折扣输出" },
"dev.ucp.shopping.checkout": {
"title": "Checkout with Discount",
"allOf": [
{ "$ref": "checkout.json" },
{ "type": "object", "properties": { "discounts": { "$ref": "#/$defs/discounts_object" } } }
]
}
}
}
注意:$defs 里的键 "dev.ucp.shopping.checkout" 恰好等于它要扩展的父能力全名。这不是巧合,是确定性解析的约定:
- 扩展 schema MUST 为
extends里声明的每个父,都有一个同名$defs键。 - 平台解析时:确定根能力(如 checkout 操作 →
dev.ucp.shopping.checkout)→ 对每个生效扩展,取<扩展>.json#/$defs/<根能力全名>→ 用allOf链合成最终 schema。
来源:docs/specification/overview/index.md:1082-1138、docs/specification/overview/index.md:1200-1229。
直觉演示(示意,非源码)
# 示意,非源码:演示平台如何为一次 checkout 合成校验 schema
def compose_schema(root_cap: str, active_extensions: list[dict]) -> dict:
schemas = [load(f"{root_cap}.json")] # 先放基础能力 schema
for ext in active_extensions:
# 关键:用“根能力全名”当键去扩展 schema 的 $defs 里取那一支
branch = ext["$defs"].get(root_cap)
if branch: # 该扩展确实扩展了这个根能力
schemas.append(branch)
return {"allOf": schemas} # allOf 只能“叠加约束”,永远是收紧
重点看:合成永远是 allOf 叠加——只能加约束、不能放松。这条性质决定了下面的“单向门”陷阱。
4. 巧妙之处 / 坑
- 巧:自描述 schema。 每个能力 schema 顶层带
name+version,平台拿到 schema 不用查别处就知道它是什么、哪个版本;构建期还能交叉校验“声明里的 schema URL 指向的 schema,其内嵌 name/version 是否对得上”。来源:docs/documentation/schema-authoring.md:39-59。 - 巧:
requires声明版本依赖。 扩展可声明它需要的协议/能力最低版本(min/可选max), 由 schema 作者而非 profile 发布者声明;不满足的扩展在解析时被排除并触发重新剪枝。来源:docs/specification/overview/index.md:1139-1198、source/schemas/ucp.json:31-47。 - 坑(单向门):闭集枚举不可扩展。 因为扩展只能
allOf叠加,而两个enum/oneOf做allOf是取交集,永远加不进新值/新分支。所以规范强烈建议用开放字符串词表(文档化“well-known values”+ 容忍未知值)而非闭enum;oneOf、additionalProperties: false同理是单向门。只有“天生封闭”的集合(如status: open|completed|expired)才用enum。来源:docs/documentation/schema-authoring.md:335-508。
这个“开放词表 vs 闭枚举”的取舍贯穿整个 UCP,是它面向分布式演进的核心工程判断——值得带走。
5. 代码地图
| 主题 | 文件 | 符号 / 锚点 |
|---|---|---|
| 命名治理 / schema URL 权威绑定 | docs/specification/overview/index.md | “Namespace Governance” §803-830、“Authority Binding” §831-853 |
| 能力/扩展 schema 定义 | source/schemas/capability.json | $defs.base、platform_schema |
| 扩展组合范例 | source/schemas/shopping/discount.json | $defs["dev.ucp.shopping.checkout"]、$defs["dev.ucp.shopping.cart"] |
| 三件套概念 | docs/documentation/core-concepts.md | “Capabilities/Extensions/Services” §128-212 |
| 版本依赖 requires | source/schemas/ucp.json | $defs.requires、$defs.version_constraint |
| 开放词表 vs 枚举 | docs/documentation/schema-authoring.md | “String Vocabularies vs Enums”、“Extensibility and Forward Compatibility” |