Manifest Schema Reference
This document describes the complete YAML schema for SOVD system manifests.
Top-Level Structure
A manifest file has the following top-level structure:
manifest_version: "1.0" # Required - manifest schema version
metadata: # Optional - document metadata
name: string
version: string
description: string
config: # Optional - discovery behavior settings
unmanifested_nodes: string
inherit_runtime_resources: boolean
allow_manifest_override: boolean
areas: [] # Optional - area definitions
components: [] # Optional - component definitions
apps: [] # Optional - app definitions
functions: [] # Optional - function definitions
scripts: [] # Optional - pre-defined script entries
manifest_version (Required)
The manifest schema version. Currently must be "1.0".
manifest_version: "1.0"
metadata (Optional)
Document metadata for identification and documentation.
Field |
Type |
Description |
|---|---|---|
|
string |
System/robot name (e.g., “turtlebot3-nav2”) |
|
string |
Manifest version (e.g., “1.0.0”) |
|
string |
Human-readable description |
metadata:
name: "my-robot"
version: "2.0.0"
description: "Mobile robot with Nav2 navigation stack"
config (Optional)
Discovery behavior configuration.
Field |
Type |
Description |
|---|---|---|
|
string |
Policy for ROS nodes not in manifest |
|
boolean |
Copy topics/services from runtime nodes (default: true) |
|
boolean |
Manifest values can override runtime (default: true) |
unmanifested_nodes options:
ignore- Don’t expose unmanifested nodeswarn- Log warning, include as orphans (default)error- Fail startup if orphan nodes detectedinclude_as_orphan- Include withsource: "orphan"
config:
unmanifested_nodes: warn
inherit_runtime_resources: true
allow_manifest_override: true
Areas
Areas represent logical or physical groupings (subsystems, locations, etc.). In runtime-only mode, areas are derived from ROS 2 namespaces.
Note
The areas: section is optional. For simple robots without subsystem hierarchy,
you can omit areas entirely and use components as the top-level entities. See
Flat Entity Tree below.
Schema
areas:
- id: string # Required - unique identifier
name: string # Required - human-readable name
namespace: string # Optional - ROS 2 namespace path
category: string # Optional - classification
description: string # Optional - detailed description
tags: [string] # Optional - tags for filtering
translation_id: string # Optional - i18n key
parent_area_id: string # Optional - parent area reference
subareas: [] # Optional - nested area definitions
Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Unique identifier (alphanumeric, hyphens allowed) |
|
string |
Yes |
Human-readable name |
|
string |
No |
ROS 2 namespace path (e.g., “/perception”) |
|
string |
No |
Classification for filtering |
|
string |
No |
Detailed description |
|
[string] |
No |
Tags for filtering and grouping |
|
string |
No |
Internationalization key |
|
string |
No |
Parent area ID (for flat hierarchy definition) |
|
[Area] |
No |
Nested area definitions |
Example
areas:
- id: perception
name: "Perception Subsystem"
category: "sensor-processing"
description: "Sensor data acquisition and processing"
tags:
- sensors
- realtime
subareas:
- id: lidar-processing
name: "LiDAR Processing"
description: "Point cloud processing pipeline"
- id: camera-processing
name: "Camera Processing"
description: "Image processing pipeline"
- id: navigation
name: "Navigation Subsystem"
category: "motion-planning"
Components
Components represent hardware or virtual entities (ECUs, sensors, controllers). In runtime-only mode, synthetic components are created per namespace to group Apps (nodes). In manifest mode, components are explicitly defined and Apps are linked to them.
Schema
components:
- id: string # Required - unique identifier
name: string # Required - human-readable name
type: string # Optional - component type
category: string # Optional - classification
area: string # Optional - reference to area.id
namespace: string # Optional - ROS 2 namespace
fqn: string # Optional - fully qualified name
variant: string # Optional - hardware variant
description: string # Optional - detailed description
tags: [string] # Optional - tags for filtering
translation_id: string # Optional - i18n key
parent_component_id: string # Optional - parent component
depends_on: [string] # Optional - component IDs this depends on
subcomponents: [] # Optional - nested definitions
lock: # Optional - per-entity lock configuration
required_scopes: [string] # Collections requiring a lock before mutation
breakable: boolean # Whether locks can be broken (default: true)
max_expiration: integer # Max lock TTL in seconds (0 = global default)
Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Unique identifier |
|
string |
Yes |
Human-readable name |
|
string |
No |
Component type (sensor, actuator, controller, etc.) |
|
string |
No |
Classification for filtering |
|
string |
No |
Parent area ID |
|
string |
No |
ROS 2 namespace path |
|
string |
No |
Fully qualified name (namespace + id) |
|
string |
No |
Hardware variant identifier |
|
string |
No |
Detailed description |
|
[string] |
No |
Tags for filtering |
|
string |
No |
Internationalization key |
|
string |
No |
Parent component ID |
|
[string] |
No |
List of component IDs this component depends on |
|
[Component] |
No |
Nested component definitions |
Common Component Types
sensor- Sensors (LiDAR, camera, IMU)actuator- Actuators (motors, grippers)controller- Controllers (main computer, ECU)accelerator- Compute accelerators (GPU, TPU)communication- Communication interfacespower- Power management
Example
components:
- id: main-computer
name: "Main Computer"
type: "controller"
area: control
description: "Raspberry Pi 4 running ROS 2"
variant: "rpi4-8gb"
subcomponents:
- id: gpu-unit
name: "GPU Processing Unit"
type: "accelerator"
- id: lidar-sensor
name: "LiDAR Sensor"
type: "sensor"
area: perception
description: "360° laser range finder"
tags:
- safety-critical
- realtime
- id: imu-sensor
name: "IMU Sensor"
type: "sensor"
area: perception
Apps
Apps represent software applications, typically mapping 1:1 to ROS 2 nodes. Apps exist only in manifest and hybrid modes.
Schema
apps:
- id: string # Required - unique identifier
name: string # Required - human-readable name
category: string # Optional - classification
is_located_on: string # Optional - component ID
depends_on: [string] # Optional - app IDs this app depends on
description: string # Optional - detailed description
tags: [string] # Optional - tags for filtering
translation_id: string # Optional - i18n key
external: boolean # Optional - not a ROS node (default: false)
ros_binding: # Required for hybrid mode linking
node_name: string # Required - ROS node name
namespace: string # Optional - namespace (default: /)
topic_namespace: string # Optional - match by topic prefix
lock: # Optional - per-entity lock configuration
required_scopes: [string] # Collections requiring a lock before mutation
breakable: boolean # Whether locks can be broken (default: true)
max_expiration: integer # Max lock TTL in seconds (0 = global default)
Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Unique identifier |
|
string |
Yes |
Human-readable name |
|
string |
No |
Classification for filtering |
|
string |
No |
Component ID where app runs |
|
[string] |
No |
List of app IDs this app depends on |
|
string |
No |
Detailed description |
|
[string] |
No |
Tags for filtering |
|
string |
No |
Internationalization key |
|
boolean |
No |
True if not a ROS node (default: false) |
ros_binding Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes* |
ROS 2 node name to bind to |
|
string |
No |
Namespace (“*” for wildcard) |
|
string |
Yes* |
Alternative: match by topic prefix |
* Either node_name or topic_namespace is required.
Matching behavior:
Name and namespace match (default):
node_namemust match exactly.namespaceuses path-segment-boundary matching:/navmatches/navand/nav/subbut NOT/navigation.Wildcard namespace: Set
namespace: "*"to match node in any namespaceTopic namespace: Match nodes by their published topic prefix
Example
apps:
# Match by exact node name and namespace
- id: lidar-driver
name: "LiDAR Driver"
is_located_on: lidar-sensor
ros_binding:
node_name: velodyne_driver
namespace: /sensors
# Match node in any namespace
- id: camera-driver
name: "Camera Driver"
ros_binding:
node_name: usb_cam
namespace: "*"
# Match by topic namespace
- id: perception-pipeline
name: "Perception Pipeline"
ros_binding:
topic_namespace: /perception
# App with dependencies
- id: slam-node
name: "SLAM Node"
category: "localization"
is_located_on: main-computer
depends_on:
- lidar-driver
- imu-driver
ros_binding:
node_name: slam_toolbox
namespace: /mapping
# External app (not a ROS node)
- id: cloud-connector
name: "Cloud Connector"
external: true
description: "External cloud service integration"
Functions
Functions represent high-level capabilities spanning multiple apps. Functions are always manifest-defined and aggregate data from their host apps.
Schema
functions:
- id: string # Required - unique identifier
name: string # Required - human-readable name
category: string # Optional - classification
hosted_by: [string] # Required - list of app IDs
depends_on: [string] # Optional - function IDs
description: string # Optional - detailed description
tags: [string] # Optional - tags for filtering
translation_id: string # Optional - i18n key
Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Unique identifier |
|
string |
Yes |
Human-readable name |
|
[string] |
Yes |
List of app IDs that implement this function |
|
string |
No |
Classification for filtering |
|
[string] |
No |
List of function IDs this function depends on |
|
string |
No |
Detailed description |
|
[string] |
No |
Tags for filtering |
|
string |
No |
Internationalization key |
Function Capabilities
Functions aggregate capabilities from their host apps:
Data: Combined topics from all host apps
Operations: Combined services/actions from all host apps
Faults: Faults from all host apps
Example
functions:
- id: autonomous-navigation
name: "Autonomous Navigation"
category: "mobility"
description: "Complete autonomous navigation capability"
tags:
- safety-critical
- autonomous
hosted_by:
- amcl-node
- planner-server
- controller-server
- bt-navigator
- id: localization
name: "Localization"
category: "state-estimation"
hosted_by:
- amcl-node
- map-server
- id: perception
name: "Environment Perception"
category: "sensing"
hosted_by:
- lidar-driver
- camera-driver
- point-cloud-processor
Scripts
Scripts define pre-deployed diagnostic scripts that are available on entities.
Scripts defined in the manifest are managed - they cannot be deleted via the REST API.
Note
Manifest scripts are only loaded when scripts.scripts_dir is configured in the
gateway parameters. Without it, the scripts: block is parsed but scripts are
not exposed via the REST API.
Schema
scripts:
- id: string # Required - unique identifier
name: string # Optional - human-readable name (defaults to id)
description: string # Optional - detailed description
path: string # Required - filesystem path to script file
format: string # Required - execution format (bash, python, sh)
timeout_sec: integer # Optional - execution timeout (default: 300)
entity_filter: [string] # Optional - glob patterns for entity matching
env: # Optional - environment variables
KEY: "value"
args: # Optional - argument definitions
- name: string
type: string
flag: string
parameters_schema: # Optional - JSON Schema for parameters
Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Unique script identifier |
|
string |
No |
Human-readable name (defaults to id) |
|
string |
No |
Detailed description |
|
string |
Yes |
Filesystem path to the script file |
|
string |
Yes |
Execution format: |
|
integer |
No |
Max execution time in seconds (default: 300) |
|
[string] |
No |
Glob patterns for entity matching (e.g., |
|
map |
No |
Environment variables passed to the script |
|
[object] |
No |
Argument definitions with |
|
object |
No |
JSON Schema for execution parameters validation. Nested objects and arrays are fully supported. |
Example
scripts:
- id: run-diagnostics
name: "Run Diagnostics"
description: "Check health of all sensors"
path: "/opt/scripts/run-diagnostics.sh"
format: "bash"
timeout_sec: 30
entity_filter:
- "components/*"
env:
GATEWAY_URL: "http://localhost:8080"
- id: calibrate-sensor
name: "Calibrate Sensor"
path: "/opt/scripts/calibrate.py"
format: "python"
timeout_sec: 60
args:
- name: threshold
type: float
flag: "--threshold"
See also
See the Scripts section in REST API Reference for API endpoints.
Flat Entity Tree
For simple robots where the entire system is a single unit, you can omit the
areas: section and use a flat component tree instead. The top-level component
represents the robot itself, with subcomponents for hardware modules:
manifest_version: "1.0"
metadata:
name: "flat-turtlebot"
version: "1.0.0"
description: "TurtleBot3 without area hierarchy"
# No areas section - components are top-level entities
components:
- id: turtlebot3
name: "TurtleBot3 Burger"
type: "mobile-robot"
- id: raspberry-pi
name: "Raspberry Pi 4"
type: "controller"
parent_component_id: turtlebot3
- id: lds-sensor
name: "LDS-02 LiDAR"
type: "sensor"
parent_component_id: turtlebot3
apps:
- id: lidar-driver
name: "LiDAR Driver"
is_located_on: lds-sensor
ros_binding:
node_name: ld08_driver
namespace: /
For manifest-based discovery (manifest_only or hybrid), simply omit the
areas: section as shown above - no additional configuration is needed.
For runtime-only discovery, set create_synthetic_areas: false in
gateway_params.yaml to prevent automatic area creation from namespaces (see
Discovery Options Reference). A complete example is available at
config/examples/flat_robot_manifest.yaml in the gateway package.
Note
In hybrid mode, the runtime gap-fill layer may create synthetic areas
from namespaces even when the manifest omits areas:. Set
merge_pipeline.gap_fill.allow_heuristic_areas: false to prevent
this and maintain a fully flat tree. See Discovery Options Reference
for gap-fill configuration details.
Complete Example
Here’s a complete manifest for a TurtleBot3 robot:
manifest_version: "1.0"
metadata:
name: "turtlebot3-nav2"
version: "2.0.0"
description: "TurtleBot3 with Nav2 navigation stack"
config:
unmanifested_nodes: warn
inherit_runtime_resources: true
areas:
- id: perception
name: "Perception"
category: "sensor-processing"
- id: navigation
name: "Navigation"
category: "motion-planning"
- id: control
name: "Control"
category: "motion-control"
components:
- id: lidar-sensor
name: "LiDAR Sensor"
type: "sensor"
area: perception
- id: main-computer
name: "Main Computer"
type: "controller"
area: control
apps:
- id: lidar-driver
name: "LiDAR Driver"
is_located_on: lidar-sensor
ros_binding:
node_name: ld08_driver
- id: amcl-node
name: "AMCL Localization"
category: "localization"
is_located_on: main-computer
ros_binding:
node_name: amcl
- id: planner-server
name: "Planner Server"
category: "navigation"
is_located_on: main-computer
depends_on:
- amcl-node
ros_binding:
node_name: planner_server
functions:
- id: autonomous-navigation
name: "Autonomous Navigation"
category: "mobility"
hosted_by:
- amcl-node
- planner-server
scripts:
- id: run-diagnostics
name: "Run Diagnostics"
path: "/opt/scripts/diagnostics.sh"
format: "bash"
timeout_sec: 30
entity_filter:
- "components/*"
Validation
Manifests are validated during loading. The validator checks:
Required fields:
manifest_versionmust be present and equal to “1.0”All entities must have
idandnameApps with
ros_bindingmust havenode_nameortopic_namespaceFunctions must have at least one entry in
hosted_byScripts must have
id,path, andformatformatmust be one of:bash,python,sh
References:
areareferences must point to valid area IDsis_located_onmust point to valid component IDsdepends_onmust point to valid app/function IDshosted_bymust point to valid app IDs
Uniqueness:
All entity IDs must be unique within their type
IDs must be unique across all entity types (areas, components, apps, functions, scripts)
Format:
IDs should contain only alphanumeric characters and hyphens
IDs should not start with numbers
Validation errors are reported with the path to the invalid field:
Validation error at apps[2].ros_binding: 'node_name' or 'topic_namespace' required
Validation error at functions[0].hosted_by[1]: App 'unknown-app' not found
See also
Manifest-Based Discovery - User guide for manifest-based discovery
Migration Guide: Runtime to Hybrid Mode - Migration guide