Start with skills, agents, additional inputs, the simulator, or the ROS reference.
Tip
Don't have a robot? Try MARS live in your browser or run the simulator locally.
![]() Web app |
![]() Mobile app |
![]() Live simulator |
Innate OS is developed for MARS; if you want to port it to your robot, we are happy to feature it.
With the Innate web app, you can run agents, inspect what MARS sees, and control the robot in real time. The Agent page below is connected to a physical MARS.
It is available at https://<robot-address> which can either be its IP or hostname.
The Innate mobile app is available on both iOS and Android. It allows you to control the robot in real time, just like the web app, but with a more convenient interface.
![]() Innate Controller app |
Download the Innate Controller app Connect to MARS, drive the robot, run agents and skills, record training data, and manage maps from your phone. Android APK (1.4.0) Direct APK download. iOS TestFlight Join the iOS beta. Controller app docs |
Skills are the core unit of action on Innate robots.
A skill can be digital, like calling a tool, a service or another agent; or physical, like navigating, waving, grasping, recording a demonstration, or executing a learned manipulation policy.

Two standalone skill examples, shown sequentially: moving a chess piece, then opening a door.
- Execute manually — Run skills from the
innateCLI. - Operate from apps — Trigger skills through the web app or Innate mobile apps.
- Run autonomously — Let agents select and interrupt skills as the world changes.
On the robot, skills can be inspected and called through the CLI:
innate skill type innate-os/arm_zero_position
innate skill run innate-os/arm_zero_position @duration=3Custom skills use the same @name=value input syntax.
Some physical skills can be learned from demonstrations.
- Record episodes from the phone app or web app.
- Train a policy with one of the models available on Innate Cloud or locally.
- Deploy the trained model as a skill.
Start here: Training overview. To ship a trained model back to the robot, see Deploy a trained skill.
You will find skills in two different directories:
- Built-in skills — Located in
workspace/innate_skills/. - Your custom skills — Stored in
workspace/custom_skills/. Gitignored and yours to play with. - Skill packs — Any other folder dropped into
workspace/loads as its own package (ids<folder>/<name>). A pack that lives elsewhere on disk is symlinked in (ln -s /opt/team/skills workspace/team_skills) and works the same, hot reload included.
Helpers work like normal Python: any .py in your skills folder that doesn't define a Skill is just a module — import it, use relative imports inside subfolders, share across packages by bare name (from innate_skills import arm_utils). Device helpers are methods on the interfaces (self.manipulation.move_to(...), self.mobility.rotate_by(...)); camera math and Gemini live under innate (from innate import geometry, vision, gemini).
|
Replay skill — replay a recorded motion file. Saved as workspace/custom_skills/greet/metadata.json:
{
"name": "greet",
"type": "replay",
"guidelines": "Greet the user with a friendly arm wave.",
"inputs": {},
"wheeled": false,
"downloads": {
"episode_0.h5": "https://your-cdn.com/greet/episode_0.h5"
},
"execution": {
"model_type": "replay",
"replay_file": "episode_0.h5",
"replay_frequency": 50.0,
"start_pose": [1.57693225, -0.6, 1.4772235, -0.73784476, 0.0, 0.0],
"end_pose": [1.57693225, -0.6, 1.4772235, -0.73784476, 0.0, 0.0]
}
} |
Code skill — call the mobility interface to move forward. Saved as workspace/custom_skills/move_forward.py:
from innate import Mobility, Skill, SkillReturn
class MoveForward(Skill):
"""Move the robot forward by a given distance in meters."""
mobility: Mobility # declare what you use; the runtime injects it
def execute(self, distance_m: float = 0.5) -> SkillReturn:
speed = 0.2 # m/s
duration = distance_m / speed
self.mobility.send_cmd_vel(linear_x=speed, duration=duration)
self.sleep(duration) # like time.sleep, but a Stop unwinds it
return f"Moved forward {distance_m} m"self.fail(message) to end the run as a failure.
Cancellation is the framework's job: self.sleep (and every
blocking framework call) raises the moment a Stop lands, the base is
braked automatically, and the run reports CANCELLED — skills carry no
cancel code.
|
Agents allow Innate robots to run autonomously following your instructions.
They make the robot think in a high-frequency loop using a multimodal model, for example a VLM that is constantly observing the world.
An agent consists of:
- A set of skills the robot is allowed to use
- A system prompt that defines the robot's behavior
- An agent loop that connects the model to observations, memory, tools, and robot actions

Pick up and put away skills chained in an agent to clean a room.
Multimodal agents have different constraints than purely digital agents: they need to observe continuously, run at a high frequency to react, and to be able to interrupt a running skill when the world has changed.
You can find agents in two different directories:
workspace/innate_agents/— Built-in agents shipped with Innate OS.workspace/custom_agents/— Your local agents. Gitignored and yours to play with.
Here is an example of a simple agent to navigate:
A minimal agent file, saved as workspace/custom_agents/navigate_agent.py:
from brain_client.agents.types import Agent
class NavigateAgent(Agent):
"""An agent that can navigate to requested positions."""
@property
def id(self):
return "navigate_agent"
@property
def display_name(self):
return "Navigate"
def get_skills(self):
return ["innate-os/navigate_to_position"]
def get_inputs(self):
return ["micro"]
def get_prompt(self):
return "You are a helpful robot. When asked, navigate to the requested location using the navigate_to_position skill."Use the simulator to test custom agents before running them on a physical robot.
Try MARS now at sim-demo.innate.bot -- no install or robot required.
Innate OS includes a MuJoCo digital twin of MARS that runs the real robot software -- the same navigation stack, skills, brain client, and webapp as the physical robot, with only the hardware drivers swapped for a simulated equivalent. Use it to build and test skills, agents, and input devices before you have a robot on your desk.
curl -fsSL https://link.innate.bot/sim | shOne command on macOS, Linux and WSL2. It asks before installing anything missing (Docker, uv, git), clones this repository into innate-os/ in the directory you run it from, asks how the agent should reach a cloud LLM, and downloads everything the simulator needs (simulation assets, the 3D viewer bundle, the Docker image). Already have a checkout? ./innate-sim setup does the same from inside it.
cd innate-os && ./innate-sim upThe terminal opens a live dashboard, and the robot webapp at https://localhost is the sim UI -- drive and operate the simulated MARS exactly like a real one, with a live 3D view instead of camera streams.
./innate-sim status # show current runtime state
./innate-sim sh # open a shell inside the ROS container
./innate-sim logs os-session # inspect runtime logs (see `logs --help` for targets)
./innate-sim down # stop the runtimeSee sim/README.md for everything else: the day-to-day workflow, the ROS-free VirtualMars Python API (with a walkthrough notebook), and the architecture.
Foxglove Studio gives you a live view of TF, /scan, camera images, point clouds, and /cmd_vel teleop for debugging. In the simulator the bridge is always on; on a physical robot it is opt-in:
innate foxglove start # start the bridge (ws://<robot-ip>:8765)
innate foxglove stop # stop it
innate foxglove # statusThen connect Foxglove Studio to the printed ws:// URL.
Over Wi-Fi, subscribe to the
/mars/main_camera/remote/*topics, not the raw ones. The raw camera images (~0.9 MB/frame) and point clouds (/mars/main_camera/points, ~10 MB/s) are far more than a Wi-Fi link can carry, so every panel — including/cmd_vel— falls seconds behind. Theremote/namespace carries the same topics throttled to ~2 Hz (and images already compressed), which fits comfortably. Prefer.../compressedimage topics and monoremote/pointsoverremote/points_color.
Innate OS provides an SDK for streaming new data into running agents. Innate robots are designed to be naturally expandable: add a new sensor, expose it as an input device, and let agents request it by name.
Input devices live in workspace/inputs/ and are pure Python. They should not import ROS directly.
Thermometer input example
# workspace/inputs/thermometer_input.py
import threading
import time
from brain_client.inputs.types import InputDevice
def read_thermometer_celsius() -> float:
# Replace this with your hardware, websocket, serial, or API read.
return 21.5
class ThermometerInput(InputDevice):
def __init__(self, logger=None):
super().__init__(logger)
self._stop_event = threading.Event()
self._thread = None
@property
def name(self) -> str:
return "thermometer"
def on_open(self):
self._stop_event.clear()
self._thread = threading.Thread(target=self._loop, daemon=True)
self._thread.start()
def on_close(self):
self._stop_event.set()
if self._thread:
self._thread.join(timeout=1.0)
def _loop(self):
while not self._stop_event.is_set():
self.send_data(
{"celsius": read_thermometer_celsius(), "timestamp": time.time()},
data_type="custom",
)
time.sleep(1.0)An agent or directive can then request the input by name:
def get_inputs(self):
return ["thermometer"]See docs/INPUT_DEVICES.md for the full input-device lifecycle.
Innate OS is currently based on ROS 2, the reference framework for robotics operating systems. Most builders should start with skills, agents, inputs, and the simulator. Changing the core OS is not recommended for normal usage, but it is possible.
| ros2_ws/ Robot runtime workspace. |
System Overview Architecture reference. |
Startup Robot node wiring. |
Updates Services and CLI commands. |
config/ DDS, systemd, udev, audio, Bluetooth, sounds, and shell setup. |
Main ROS 2 runtime packages
- mars_control - top-level robot app node, rosbridge websocket server for the mobile/web app, and low-latency UDP receiver for leader-arm teleop.
- mars_bringup - hardware bringup for motors, base, IMU, and LiDAR, plus
robot_state_publisherfor the TF tree. - mars_arm - arm and head servo driver and KDL-based IK solver.
- mars_cam - stereo main camera, arm camera, VPI stereo depth estimator, WebRTC streamer, and stereo calibration action server.
- mars_nav - Nav2-based navigation, SLAM mapping, and the mode manager that switches between
mapfree,mapping, andnavigation. - brain_client - bridge to the Innate cloud brain, websocket client, skills action server, and user input manager.
- manipulation - records and replays manipulation demonstrations and runs learned or scripted manipulation policies.
- innate_logger - uploads robot logs and telemetry to the Innate cloud.
- innate_training_node - collects training episodes and pushes them to the training cloud.
- innate_uninavid - UniNaVid vision-language navigation client.
- Innate documentation - canonical docs for setup, simulator, skills, agents, training, and robot operation.
We welcome contributions to Innate OS and will be happy to feature applications written on top of it here–and robots using it.
A huge thanks to all people in the community who helped by contributing, providing feedback, and building on Innate OS.
If you want to help, feel free to reach out on Discord.





