Actions are commands that platform sends to the client. The JSON format for Actions would look like :

{
    "name": "toggle_board_led",
    "id": "101",
    "kind": "process",
    "payload": {
        "status": "ON",
    },
}

NOTE: payload is optional, so it may or mayn’t be there

To handle an incoming action, you need to define and register an action handler. An action handle must take Action and &ByteBeamClient as arguments :

let bytebeam_client = ByteBeamClient::init()?;

// You can pass a closure
bytebeam_client.register_action_handle(
    "example_action".into(),
    &|action: Action, bytebeam_client: &ByteBeamClient| {
        // handler body
    },
);

// or you can also pass down a function
bytebeam_client.register_action_handle("toggle".into(), &toggle);

// Function signature
fn toggle(action: Action, bytebeam_client: &ByteBeamClient) {
    // function body
}

We can also send the progress updates for actions using publish_action_status :

pub fn publish_action_status(
        &self,
        action_id: &str,
        percentage: u32,
        status: &str,
        error_messages: Option<&[&str]>,
    ) -> anyhow::Result<u32> {

For example :

fn toggle(action: Action, bytebeam_client: &ByteBeamClient) {
    let mut onboard_led = ONBOARD_LED.lock().unwrap();
    let onboard_led = onboard_led.get_mut().as_mut().unwrap();

    match onboard_led.toggle() {
        Ok(_) => bytebeam_client.publish_action_status(&action.id, 100, "Toggled", None),
        Err(_) => bytebeam_client.publish_action_status(
            &action.id,
            0,
            "Failed",
            Some(&["Failed to toggle LED"]),
        ),
    }
    .ok(); // just to satisfy clippy for now!
}

Check out examples for more details