capabilities.json
capabilities.json is the contract between an asset and the skill registry. It declares, per-part, which of the 11 closed-set affordances the part offers — and optionally a synonym table so YAML task graphs can refer to parts by human-friendly names.
Schema
Two top-level keys, both required (aliases may be empty):
| Key | Type | Meaning |
|---|---|---|
parts | dict[str, list[str]] | Part name → list of affordances offered. Part names must match URDF link names. |
aliases | dict[str, str] | Friendly name → canonical part name. Lets task graphs refer to "cap" when the URDF link is "lid". |
The 11-affordance closed set
Every value in the parts list must come from this closed set — no free-form strings, no heuristics:
graspable, rotatable, slidable, pressable, openable,
liftable, insertable, flippable, placeable, stackable, drawable
Skills declare a required set of affordances; the matcher returns the skill as applicable to a part iff that required set is a subset of the part's offered set. Closed-set means an asset's compatibility is fully decidable at registry time.
Worked example
A kettle asset whose cap can be grasped, rotated open, and inserted (the spout into a port):
{
"parts": {
"cap": ["graspable", "rotatable", "openable"],
"body": ["graspable", "liftable"]
},
"aliases": {
"lid": "cap",
"handle": "cap"
}
}
Both grasp_part(part="cap") and grasp_part(part="lid") resolve to the same physical link. pure_rotate, which requires rotatable, is now applicable to the cap part automatically.
Validation
The schema is validated at load time. Common failure modes:
- Unknown affordance. Any value outside the 11-set raises a
SchemaError. - Part not in URDF. A part name without a matching URDF link raises a
LinkNotFound. - Cyclic alias. Aliases must point to canonical part names, not other aliases.
Run python -m utils.review_capabilities --asset <name> --check to validate without entering interactive mode.