UCP Capability Intersection Algorithm: How It Negotiates Compatible Features
The UCP capability intersection algorithm deterministically calculates a compatible capability set by intersecting business and platform profiles, selecting the highest mutual version, and pruning orphaned extensions until a stable hierarchy is reached.
The Universal Commerce Protocol (UCP) employs a server-select negotiation model where businesses determine active session capabilities by running this algorithm against declared profiles. Located in the /.well-known/ucp endpoint and transmitted via the UCP-Agent header, these profiles feed into a four-step process defined in the docs/specification/overview.md file that guarantees both parties support every activated feature at compatible versions.
How the UCP Capability Intersection Algorithm Works
The algorithm processes two JSON capability arrays—one from the business profile and one from the platform profile—to produce a deterministic result set that respects hierarchical dependencies.
Step 1: Compute Raw Intersection
The algorithm first filters capabilities by name, retaining only entries present in both input profiles. This creates the initial candidate set based on exact string matches of the name field defined in source/schemas/capability.json.
Step 2: Select Highest Mutual Version
For each intersected capability, the algorithm compares version strings from both profiles. It computes the set intersection of available versions and selects the lexicographically latest date string (highest version). If no common version exists between the business and platform declarations, that capability is dropped from the result set entirely.
Step 3 and 4: Prune Orphaned Extensions
Capabilities marked as extensions declare parent dependencies via the extends field. An extension survives only if at least one of its specified parents remains in the active set after version selection. Because extensions can chain (an extension may itself be a parent of another), this pruning step iterates in a loop until no further capabilities are removed, ensuring the final hierarchy contains no orphaned nodes.
Implementation Examples
These implementations mirror the logic found in the specification and can be integrated into UCP-aware services.
Python Implementation
def intersect_capabilities(business, platform):
# 1️⃣ raw name intersection
names = {c["name"] for c in business} & {c["name"] for c in platform}
# 2️⃣ version selection
result = {}
for name in names:
b_versions = {c["version"] for c in business if c["name"] == name}
p_versions = {c["version"] for c in platform if c["name"] == name}
common = b_versions & p_versions
if common:
result[name] = max(common) # highest version wins
# 3️⃣ & 4️⃣ prune extensions iteratively
changed = True
while changed:
changed = False
for name, cap in list(result.items()):
extends = cap.get("extends")
if not extends:
continue
parents = extends if isinstance(extends, list) else [extends]
if not any(parent in result for parent in parents):
del result[name]
changed = True
return result
TypeScript Implementation
interface Capability {
name: string;
version: string;
extends?: string | string[];
}
function intersect(
business: Capability[],
platform: Capability[]
): Record<string, string> {
// 1️⃣ name intersection
const names = new Set(
business.map(c => c.name).filter(n => platform.some(p => p.name === n))
);
// 2️⃣ version selection
const intersected: Record<string, string> = {};
for (const name of names) {
const bVers = new Set(
business.filter(c => c.name === name).map(c => c.version)
);
const pVers = new Set(
platform.filter(c => c.name === name).map(c => c.version)
);
const common = [...bVers].filter(v => pVers.has(v));
if (common.length) {
intersected[name] = common.sort().pop()!; // highest version
}
}
// 3️⃣ & 4️⃣ prune extensions
let changed = true;
while (changed) {
changed = false;
for (const [name, version] of Object.entries(intersected)) {
const cap = business.concat(platform).find(c => c.name === name)!;
const ext = cap.extends;
if (!ext) continue;
const parents = Array.isArray(ext) ? ext : [ext];
if (!parents.some(p => intersected[p])) {
delete intersected[name];
changed = true;
}
}
}
return intersected;
}
File Structure and Source References
The authoritative definitions and schemas reside in specific paths within the Universal-Commerce-Protocol/ucp repository:
docs/specification/overview.md— Contains the formal Negotiation Protocol section describing the intersection algorithm and its four-step flow.source/schemas/capability.json— Defines the JSON Schema for capability objects, including thename,version, and optionalextendsproperties.source/discovery/profile_schema.json— Specifies the structure for business and platform profiles, including the embeddedcapabilitiesarray used as algorithm input.main.py— Serves as the reference integration point where the algorithm consumes platform profiles and emits the negotiated capability set for response headers.
Summary
- The UCP capability intersection algorithm enables server-select negotiation by computing the exact overlap between business and platform capability declarations.
- It guarantees compatibility by selecting only the highest mutually supported version for each intersected capability name.
- Hierarchical integrity is enforced through iterative pruning of extensions whose parent capabilities were removed during version selection.
- All definitions are grounded in the JSON schemas located at
source/schemas/capability.jsonandsource/discovery/profile_schema.json, with the algorithm specification residing indocs/specification/overview.md.
Frequently Asked Questions
What happens if the business and platform share no common capability versions?
If the version intersection for a specific capability name is empty, the algorithm drops that capability from the final set. According to the specification in docs/specification/overview.md, a capability is activated only when both parties list at least one identical version string.
How does the algorithm handle circular extension dependencies?
The iterative pruning loop naturally handles chains of extensions, including circular references, because it continues until no changes occur (changed = false). If an extension's parent is removed in one iteration, the child is removed in the next, propagating the pruning effect through the dependency graph until stability is reached.
Where should the negotiated capability set be declared in the UCP response?
The final result of the intersection algorithm populates the ucp.capabilities field in the response object. As implemented in main.py, this set is derived from the business profile intersection with the platform profile and returned according to the Response Capability Selection protocol rules.
Can a capability extend multiple parents simultaneously?
Yes. The extends field in source/schemas/capability.json accepts either a single string or an array of strings. During the pruning phase, an extension is retained if at least one of its declared parents exists in the active set, allowing for flexible capability composition while maintaining strict hierarchical validation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →