Developer Guide / Driver Integration

New Driver Integration Flow

To integrate a new robot, it is recommended to start with a minimal BaseDriver implementation and progressively complete Watchdog loading, action execution, and state writeback.

BaseDriver Interface Overview

After implementing the following methods, Watchdog can use your driver just like a built-in one. It is recommended to implement the minimal interface first and ensure Watchdog can load it properly.

class BaseDriver(ABC):
    def get_profile_path(self) -> Path: ...
    def load_scene(self, scene: dict[str, dict]) -> None: ...
    def execute_action(self, action_type: str, params: dict) -> str: ...
    def get_scene(self) -> dict[str, dict]: ...

    # Common optional methods
    def connect(self) -> bool: ...
    def disconnect(self) -> None: ...
    def is_connected(self) -> bool: ...
    def health_check(self) -> bool: ...
    def get_runtime_state(self) -> dict[str, Any]: ...
get_profile_path()

Returns the path to the EMBODIED.md profile

load_scene()

Initialize internal state from ENVIRONMENT.md

execute_action()

Execute an action and return a human-readable result

get_scene()

Return current environment state for writeback to ENVIRONMENT.md

Implement a Minimal Loadable Version First

It is recommended to first ensure that Watchdog can properly import and instantiate the Driver, and complete a full action consumption cycle, before gradually extending functionality.

from pathlib import Path
from hal.base_driver import BaseDriver

class MyRobotDriver(BaseDriver):
    def __init__(self, gui: bool = False, **kwargs):
        self._scene = {}

    def get_profile_path(self) -> Path:
        return Path(__file__).resolve().parent / "profiles" / "my_robot.md"

    def load_scene(self, scene: dict[str, dict]) -> None:
        self._scene = dict(scene)

    def execute_action(self, action_type: str, params: dict) -> str:
        return f"executed {action_type}"

    def get_scene(self) -> dict[str, dict]:
        return dict(self._scene)
The goal of this minimal implementation: confirm that the main repository can stably import the driver, install the profile, and successfully complete action consumption and state writeback. Add action mapping and real-robot logic later.

Supplement the Profile File

What Goes in the Profile

  • Identity: name, type, driver/profile
  • Sensors / Degrees of Freedom
  • Supported Actions
  • Physical Constraints
  • Connection & Runtime Protocol

Impact of Missing Profile

The Critic has no basis for action constraints, and ROBOTS.md can't provide reliable capability summaries. The Agent won't know what to assign to this robot.

Built-in Driver Registration Method

For built-in drivers (not external plugins), you also need to add a short-name mapping in the registry.

DRIVER_REGISTRY: dict[str, str] = {
    "simulation": "hal.drivers.simulation_driver.SimulationDriver",
    "go2_edu": "hal.drivers.go2_driver.Go2Driver",
    "my_robot": "hal.drivers.my_robot_driver.MyRobotDriver",
}

External plugins are discovered through their plugin manifest and registry — no need to modify this line.

Watchdog Actual Invocation Sequence

Load driver

Can import and instantiate

Install profile to EMBODIED.md

get_profile_path() returns a valid path

Establish connection, refresh health status

connect() / health_check() working

Read ACTION.md, call execute_action()

Action type and parameters can be handled

Write state back to ENVIRONMENT.md

get_scene() / get_runtime_state() serialize correctly

Debugging Sequence

First, make sure the driver can be imported and instantiated

In a Python shell: from hal.drivers.my_robot_driver import MyRobotDriver; d = MyRobotDriver() — no errors

Confirm profile can be installed as EMBODIED.md

Check startup logs or verify the correct EMBODIED.md was generated in the workspace

Confirm actions reach execute_action()

Add logging output to the method to confirm it is being called correctly

Confirm state can be written back to ENVIRONMENT.md

After executing an action, cat ENVIRONMENT.md to check if robot state was updated

Finally, use paos agent for natural language end-to-end testing

Trigger with a simple, clear instruction and observe ACTION.md generation and execution results

The core debugging approach is layered verification: first confirm "can load", then "can execute", then "can write back". It is recommended to avoid pursuing the full pipeline immediately.