Skills & Market

Skills are reusable, named behaviors that run on any robot. They register with a decorator and are discovered via the ohho market CLI. A skill's tools are gated by the robot's capabilities — a skill that needs manipulation won't run on a robot without an arm.

Built-in skills

Skill Requires Description
patrol base.drive Drive a square patrol pattern
wave manipulation Wave the arm gripper
stop — Emergency stop the robot
status — Print telemetry and connection status

List and run skills

These two commands exited 0. ohho market run omnibot patrol did not exit in the check, so it is not listed.

ohho market list
ohho market run omnibot status

Use skills in Python

from ohho.market import run_skill, list_skills, get_skill

# List all registered skills
for s in list_skills():
    print(f"{s.name}: {s.description}")

# Run a skill
result = run_skill("patrol", bot, side=2.0, speed=0.15)

# Check if a skill can run on a robot
skill = get_skill("wave")
if skill.can_run(bot):
    skill.run(bot, reps=5)

Write your own skill

Use the @skill decorator to register a reusable behavior:

from ohho.market import skill

@skill("dance", "Make the robot dance in a circle", requires=["base.drive"])
def dance(robot, speed=0.2, turns=4):
    import time
    for _ in range(turns):
        robot.drive(vx=speed, w=0.8)
        time.sleep(3.14)
    robot.stop()
    return f"danced {turns} turns at {speed} m/s"

Then use it:

A custom skill was not part of the checked run. ohho market list and ohho market run omnibot status are in Install.

Or in Python:

from ohho.market import run_skill
run_skill("dance", bot, speed=0.3, turns=2)

Capability gating

Skills declare which capabilities they requires. When you run a skill on a robot that lacks those capabilities, you get a clear error:

from ohho.market import run_skill, SkillRequirementsNotMet

try:
    run_skill("wave", dog)  # Go2 has no manipulation
except SkillRequirementsNotMet as e:
    print(e)
    # skill 'wave' requires capabilities: ['manipulation'].
    # Robot 'unitree-go2' has: ['base.drive', 'base.holonomic_drive', ...]

The Skill dataclass

from ohho.market import Skill, register_skill

custom = Skill(
    name="inspect",
    description="Drive forward and report obstacles",
    handler=lambda robot: robot.drive(vx=0.1),
    requires=["base.drive"],
    author="your-name",
    version="1.0.0",
    tags=["inspection", "safety"],
)
register_skill(custom)

Next