Himalaya Robotics Hack

Himalaya Robotics Hack

Build robots for extreme conditions with LiveKit. Presented by Iterate with Robot Everest, in San Francisco, on August 29–30, 2026. The four challenges are onboard autonomy (inference on Jetson Thor, no cloud), movement across ice and broken terrain, hardware durability, and dependable satellite comms.

LiveKit is the transport layer for the parts of that stack that have to cross a network: teleop, remote inference, live video off the robot, and a voice interface for the operator. WebRTC underneath means no VPN, no port forwarding, and congestion control that degrades gracefully instead of stalling when the link gets thin — which is what you want behind a satellite hop.

Start here: docs.livekit.io/robotics — the robotics docs cover teleop, observability, remote inference, and voice interactions, plus the hardware platforms you'll be on this weekend: embedded Linux, Nvidia Jetson (with hardware-accelerated video encoding), and ESP32. And if you already have a ROS 2 graph running, ROS Portal bridges it over LiveKit — see step 3.


1. Install the LiveKit Docs MCP server

Keeps your coding agent on the rails. It pulls live docs, code examples, and changelogs straight into Cursor / Claude Code / VS Code so you stop fighting hallucinations.

Claude Code

claude mcp add --transport http livekit-docs https://docs.livekit.io/mcp

Cursorone-click install

VS Code

code --add-mcp '{"name":"livekit-docs","type":"http","url":"https://docs.livekit.io/mcp"}'

Codex

codex mcp add --url https://docs.livekit.io/mcp livekit-docs

Full reference and other clients: docs.livekit.io/mcp.

Or use the LiveKit Agents skill

If you'd rather use a Claude Code skill instead of (or alongside) the MCP server:

npx skills add https://github.com/livekit/agent-skills --skill livekit-agents

Activates automatically for relevant tasks, or invoke with /livekit-agents.


2. Teleop and remote inference with LiveKit Portal

LiveKit Portal synchronizes cameras, joint state, and actions between a robot and whoever — or whatever — is driving it. Robot, policies, and human operators all join one room, and you hand control between them with set_active_operator().

pip install livekit-portal

Run the two-process example to see the loop end to end:

cd examples/python/basic
uv sync
uv run robot.py              # terminal 1 — the robot side
uv run teleoperator.py       # terminal 2 — the operator side

Already on LeRobot:

pip install lerobot-robot-livekit

What matters for this hackathon:

  • Observations arrive fused — frames and state land together with matching timestamps, so your policy isn't guessing at alignment
  • Lossless video modes — RAW, PNG, or MJPEG when your model needs pixel-exact input; WebRTC video when you'd rather have the bandwidth
  • Human-in-the-loop — a policy drives while a human demonstrates corrections, with one continuous action stream
  • Rust core, Python bindings over UniFFI — the same transport onboard the Jetson and on the operator's laptop

Read the docs alongside it: Teleoperation for the control-loop patterns, Realtime media & data for codecs and Jetson hardware encoding, and Integrations for ROS and LeRobot.

Building outside Python? The SDKs are all here: Rust · Python · C++


3. Already on ROS 2? Bridge the graph with ROS Portal

ROS Portal connects a ROS 2 graph to any other LiveKit participant — another ROS 2 graph, a browser, a cloud policy — without exposing DDS across networks. It forwards the topics you list as schema-described DataTracks, forwards service calls over RPC, and publishes sensor_msgs/msg/Image topics as real LiveKit video tracks. Supported distros: Humble, Jazzy, Kilted, Lyrical. It's in Developer Preview — expect rough edges.

Step 1 — mint a token

ROS Portal reads two environment variables. Point LIVEKIT_URL at your Cloud project, then mint a JWT with the LiveKit CLI. The token carries the room name and the participant identity, and it needs --allow-update-metadata so Portal can advertise itself with the lk.robot attribute:

export LIVEKIT_URL=wss://<your-project>.livekit.cloud
export LIVEKIT_API_KEY=<api-key>
export LIVEKIT_API_SECRET=<api-secret>

export LIVEKIT_TOKEN="$(lk token create \
  --join \
  --room himalaya \
  --identity robot \
  --allow-update-metadata \
  --valid-for 24h \
  --token-only \
  --yes)"

For a local livekit-server --dev instead, use ws://127.0.0.1:7880 and add --dev to the token command.

Step 2 — declare your routes

Credentials live in the environment; the YAML only describes what crosses the link and in which direction. Save this as ros_portal.yaml on the robot:

ros_portal:
  version: "0.0.1"
  ros_threads: 4          # keep > 1 so remote ros2 CLI calls get a free thread

  topics:
    # Front camera out as a real LiveKit video track.
    - topic: "/camera/front/image_raw"
      direction: "out"
      video_options:
        bitrate_kbps: 1500

    # Telemetry out, throttled — the operator doesn't need 100 Hz IMU.
    - topic: "/imu"
      direction: "out"
      max_rate_hz: 10
    - topic: "/diagnostics"
      direction: "out"
      max_rate_hz: 2

    # Static transforms are latched: routed over reliable RPC so a
    # late-joining operator still gets them.
    - topic: "/tf_static"
      direction: "out"
      latched: true

    # Drive commands in.
    - topic: "/cmd_vel"
      direction: "in"

Omit config_path entirely and you get the builtin default — every topic, both directions. Fine for a first smoke test, wasteful over a satellite link.

The operator side is the same file with the directions flipped (/cmd_vel out, camera and telemetry in). To call a robot service from the operator graph, add a route naming who answers it:

  services:
    - service: "/estop"
      direction: "out"
      participant: "robot"
      msg_type: "std_srvs/srv/SetBool"

Add $schema: https://raw.githubusercontent.com/livekit/ros-portal/main/src/ros_portal_config/schema/ros_portal_config.schema.json at the top of the file for editor autocomplete and validation.

Step 3 — run it

Fastest path for a hackathon is the Docker image — no install, one command per side:

export ROS_DISTRO=jazzy
docker run --rm \
  --network host \
  -e LIVEKIT_URL \
  -e LIVEKIT_TOKEN \
  --volume $(pwd)/ros_portal.yaml:/config/ros_portal.yaml:ro \
  livekit/ros-portal:$ROS_DISTRO \
  ros2 launch ros_portal ros_portal.launch.py \
  config_path:=/config/ros_portal.yaml

Running natively on the Jetson instead? Grab the .deb for your distro and arch from releases:

sudo apt update
sudo apt install ./ros-$ROS_DISTRO-livekit-portal*.deb
source /opt/livekit/ros/$ROS_DISTRO/setup.bash
ros2 pkg prefix ros_portal        # sanity check

Start the operator side with its own token (--identity operator, same --room) and config, and the two graphs are talking. ros2 topic list on the operator only shows a bridged topic once something publishes it — Portal creates endpoints lazily, so an empty list early on is expected, not broken.

Poke at the remote graph

Portal forwards a subset of the ros2 CLI over RPC as local services, each taking the remote identity:

ros2 service call /ros_portal/ros2_topic_list \
  ros_portal_msgs/srv/Ros2TopicList \
  "{participant_id: 'robot', show_types: true}"

The output field is the same text you'd get running ros2 topic list on the robot itself — useful when the robot is a hundred meters up a slope and you are not.

Worth reading before you build

  • Turtlesim over LiveKit — two ROS graphs on one machine, isolated by ROS_DOMAIN_ID, connected only by a LiveKit room. Best 15 minutes you can spend on this.
  • Configuration referencemax_rate_hz is lossy on aggregate topics like /tf; read that section before you throttle anything load-bearing.
  • Working robot stacks: cobra_flex_ros (Waveshare Cobra Flex teleop) and waver_ros (WAVE ROVER teleop + autonomous nav on a Raspberry Pi).

4. Give it a voice

An operator with gloves on at altitude is not going to use a keyboard. LiveKit Agents gets you a real-time voice interface in four commands:

brew install livekit-cli     # or: curl -sSL https://get.livekit.io/cli | bash
lk cloud auth
lk app create                # clone the agent starter
cd your_agent_directory && uv sync && uv run src/agent.py download-files && uv run src/agent.py console

You're now talking to your agent. All of the agent code lives in src/agent.py — wire your robot's commands in as function tools and you have voice control over the same LiveKit room the teleop stream is on.

For a web or mobile frontend, lk app create again and pick a template (e.g. agent-starter-react), then pnpm install && pnpm dev. Or skip the frontend entirely and use a prebuilt sandbox.


5. Redeem your $50 in inference credits

All attendees get a 7-day free trial — $50 in inference credits, no credit card required.

  1. Create a project at cloud.livekit.io
  2. Redeem at cloud.livekit.io/projects/p_/redeem
  3. Code: HACK-HIMALAYA-ROBOTICS

6. Ship it

When your agent works locally, deploy from inside the agent directory:

lk agent create

Then test against the frontend you cloned, or a sandbox.

CLI reference: docs.livekit.io/intro/basics/cli.


Ideas, by challenge track

  • Onboard autonomy — run the policy on the Jetson, use Portal only for the operator's eyes and the takeover path. Nothing critical depends on the link being up.
  • Terrain — stream synchronized camera + joint state off the robot while it walks, and let a human demonstrate corrections on the surfaces the policy fails on. That's a labeled dataset by the end of the weekend.
  • Durability — every sensor you have, published as a data track. Build the dashboard that catches a bearing going bad before it seizes.
  • Satellite comms — lean on adaptive bitrate: drop video resolution to keep the control channel alive, and see how thin a link you can still drive over.

Reference