Concepts
- Entry point: the module:Class Provider reference in capability.yaml.
- Provider layer: SDK lifecycle hooks and Action logic.
- Adapter layer: vendor SDK, device, ROS client, or HTTP client code.
- Schema layer: JSON schemas for input, output, and progress.
- Configuration layer: public defaults; secrets arrive through context.
Recommended layout
my-capability/├── capability.yaml├── pyproject.toml├── config/default.yaml├── schemas/├── src/my_capability/│ ├── provider.py│ ├── adapter.py│ └── validation.py└── tests/├── test_provider.py└── test_adapter.py
Components
Use stable package, Provider, and Action IDs. The current validator requires provider.runtime: python and a module:Class entrypoint. Keep import-time code free of device connection; connect in on_initialize.
Store public defaults in the manifest-referenced configuration file. Read them through context.configuration. Declare secret names in the manifest and use context.secrets; never put values in YAML, tests, or logs.
Put SDK dependencies in project metadata and hardware/vendor dependencies in Capability-owned optional groups or requirements files. Declare shared or exclusive resources in the manifest; the Runtime arbitrates them.
Example
The Unitree speech Capability separates provider.py from speech backend and audio-bridge adapters. Its manifest declares an exclusive speaker resource, while the Runtime — not the Provider — coordinates access to that resource.

