fleetlessfleetlessdocs
Reference/fleetless.yaml/Actions & Services

🛠️ Actions & Services

Both are something the robot does on request. An action takes time and reports progress; a service is one request and one reply with nothing in between.

yaml
actions:
  navigate_to:
    ros_name: /navigate_to_pose
    type: nav2_msgs/action/NavigateToPose
    description: Drives to a target pose on the map.
    message:
      pose:
        header: { frame_id: map }
        pose:
          position: { x: "${target_x}", y: "${target_y}", z: 0.0 }
    parameters:
      target_x: { type: float64, min_value: -50.0, max_value: 50.0 }
      target_y: { type: float64, min_value: -50.0, max_value: 50.0 }
yaml
services:
  reset_odom:
    ros_name: /reset_odometry
    type: std_srvs/srv/Trigger
    description: Resets odometry to the origin.
    # Trigger has no request fields, so neither message nor parameters
field type bounds absent means
ros_name ROS graph name absolute, at most 255 characters required
type ROS type name the middle segment is action or srv, at most 255 characters required
message message template null refused at any depth an empty goal or request
parameters map of names at most 50 per entry the message has no holes
description text 1 to 2000 characters offered as description: null

ros_name and type are required and nothing else is. The type carries its middle segment the way ROS 2 spells it: nav2_msgs/action/NavigateToPose, std_srvs/srv/Trigger, never the two-segment short form.

Clients never see ros_name. They address the entry by its slug, so a server can be renamed on the robot without a single app changing.

One job per slug

At most one job runs per slug, for a service exactly as for an action. A second call is refused with busy and a 409 that carries the running job, and every observer of that slug sees the same job.

The checks run in a fixed order: parameters first, then whether the robot is online, then whether the slug is busy. Parameters are a property of the request and connectivity is a property of the world, so a developer testing against an offline robot still learns their parameters were wrong.

Actions report progress, services do not

An action’s job is something to watch. It moves through its states, carries feedback while it runs, and can be cancelled.

A service call returns with its result already on the job, so there is nothing left to observe. Whatever the service does has to finish inside that one reply, and anything long-running belongs in actions.

Every exposure the caller’s role grants is listed by robot_describe. Skip the description and the tool still works, listed with description: null.

What is lost is the only thing that says what the call means — the difference between a tool a model uses correctly and one it guesses at. The same holds for datapoints, publishers and cameras. Omission is the only way to say nothing, because an empty string is refused.

The message template and the parameter constraints are shared with publishers and have their own page.