Goal:
Compositions shouldn’t blindly apply the same configuration to every device.
Instead, they adapt based on the capabilities of the target device.
Capabilities come from labels, facts, or discovered properties of the device.
Step 1: Devices expose capabilities
apiVersion: ...
kind: NetworkDevice
metadata:
name: router1
labels:
vendor: cisco
role: edge
region: warsaw
capability.bgp.addPath: "true"
capability.bgp.gracefulRestart: "true"
apiVersion: infra.network.io/v1
kind: NetworkDevice
metadata:
name: router2
labels:
vendor: juniper
role: edge
region: berlin
capability.bgp.gracefulRestart: "true"
Step 2: Compositions use conditional logic
composition YAML example with conditional patches or resources:
resources:
- name: bgpConfig
type: ManagedBGP
patches:
- fromFieldPath: "metadata.labels.capability.bgp.addPath"
toFieldPath: "spec.addPathEnabled"
when: "true"
- fromFieldPath: "metadata.labels.capability.bgp.gracefulRestart"
toFieldPath: "spec.gracefulRestartEnabled"
when: "true"
The composition reads the device’s capabilities
Only enables features that are supported
Avoids errors or unsupported configurations
Step 3: Dynamic resource creation - conditionally create resources
resources:
- name: addPathPolicy
type: CiscoAddPathPolicy
condition:
label.capability.bgp.addPath == "true"
If the device doesn’t support Add-Path → resource isn’t created
No manual intervention needed
Step 4: Benefit for agents and users
User/agent only declares intent:
spec:
devices:
- router1
- router2
profile: "standard"
Composition decides what actually applies to each device based on its capabilities
Result: agents stay vendor-agnostic, top-level XRD remains simple
Analogy:
Think of a profile like “high-availability BGP”, and each device has stickers showing which features it can do.
The composition reads the stickers and only enables the features that make sense on that device.
Capability-aware composition vs. Composition with profiles
They are related but not the same thing - they operate at different layers and solve different problems.
Profiles
- High-level intent choices exposed in the XRD.
- They simplify the user API: “pick one of a few meaningful options” instead of exposing dozens of knobs.
- Compositions map profiles → actual resource configurations.
Example:
spec:
profile: "low-latency"
The composition expands this profile into timers, policies, etc.
Same profile can apply to multiple devices, vendors.
Key point:
- Profiles are user-facing.
- They describe what you want, not what the device supports.
Capabilities
- Device-aware logic inside the composition.
- Adapts configuration dynamically based on device labels / discovered features.
- Ensures only supported features are applied.
Example:
router1 supports BGP Add-Path, router2 does not.
Composition applies Add-Path only on router1, even if the profile “low-latency” requests it.
resources:
- name: bgpConfig
type: ManagedBGP
patches:
- fromFieldPath: "metadata.labels.capability.bgp.addPath"
toFieldPath: "spec.addPathEnabled"
when: "true"
Key point:
- Capability-awareness is device-facing / internal.
- It adapts how a profile is realized per device.
They work together
| Layer |
Who interacts |
Role |
| XR |
user / agent |
Declares intent via profile |
| Composition |
system |
Maps profile → concrete resources |
| Capability logic |
system |
Adapts resources per device capabilities |
Flow:
- User says: profile = low-latency
- Composition expands it into desired timers, policies
- Capability-aware logic checks each device
- Router1 → apply Add-Path
- Router2 → skip Add-Path
- Provider executes vendor-specific config
Summary
| Feature |
Profile |
Capability-aware |
| Exposed to user? |
Yes |
No |
| Purpose |
Simplify intent, hide complexity |
Adapt config to device features |
| Layer |
XRD / claim |
Composition / implementation |
| Dynamic? |
Static choice by user |
Dynamic based on device |
| Problem solved |
Avoid “50 knobs” |
Avoid unsupported configs, enable multi-vendor support |
Analogy:
Profile = “I want a sports car”
Capability-awareness = “This track allows only AWD, so only cars with AWD can actually run here”
Goal:
Compositions shouldn’t blindly apply the same configuration to every device.
Instead, they adapt based on the capabilities of the target device.
Capabilities come from labels, facts, or discovered properties of the device.
Step 1: Devices expose capabilities
Step 2: Compositions use conditional logic
composition YAML example with conditional patches or resources:
The composition reads the device’s capabilities
Only enables features that are supported
Avoids errors or unsupported configurations
Step 3: Dynamic resource creation - conditionally create resources
If the device doesn’t support Add-Path → resource isn’t created
No manual intervention needed
Step 4: Benefit for agents and users
User/agent only declares intent:
Composition decides what actually applies to each device based on its capabilities
Result: agents stay vendor-agnostic, top-level XRD remains simple
Analogy:
Think of a profile like “high-availability BGP”, and each device has stickers showing which features it can do.
The composition reads the stickers and only enables the features that make sense on that device.
Capability-aware composition vs. Composition with profiles
They are related but not the same thing - they operate at different layers and solve different problems.
Profiles
Example:
The composition expands this profile into timers, policies, etc.
Same profile can apply to multiple devices, vendors.
Key point:
Capabilities
Example:
router1 supports BGP Add-Path, router2 does not.
Composition applies Add-Path only on router1, even if the profile “low-latency” requests it.
Key point:
They work together
Flow:
Summary
Analogy:
Profile = “I want a sports car”
Capability-awareness = “This track allows only AWD, so only cars with AWD can actually run here”