> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zeroruntime.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Running a policy

> Drive a robot from a model instead of a person, and watch a session without taking control.

A Leader is whatever decides how the Follower should move. Nothing in it assumes
a person, so a model drives an arm the same way an operator does: return the
next pose from `read_joints()`.

```python theme={null}
from zeroruntime.teleops import Leader, single_group_descriptor

from joints import JOINTS          # the same module the follower imports


class PolicyLeader(Leader):
    def __init__(self, policy, **kw):
        self.robot_id = "policy"
        self._policy = policy
        self.action = {j: 0.0 for j in JOINTS}
        super().__init__(**kw)                    # LAST

    def descriptor(self):
        return single_group_descriptor(self.robot_id, "my-arm", JOINTS,
                                       control_hz=30)

    def read_joints(self):
        return dict(self.action)


leader = PolicyLeader(my_policy, sync_buffer_ms=120.0)
leader.start()

if not leader.claim_control(timeout_s=10):
    raise SystemExit("no control")

leader.hold_deadman(True)

for i in leader.ticks(hz=30):
    obs = leader.observation()                    # what the robot sees now
    if obs.images:
        leader.action.update(my_policy(obs.images, obs.joints))
```

`observation()` gives the model the same thing a person looks at: a frame per
camera and the joint values from that frame's own capture instant. Reading it
also stamps the next command with that observation's id, so the recorded action
is paired with what caused it.

<Warning>
  Set `max_misalignment` and use
  [`arm_when_aligned()`](/robotics/api-reference/python/leader#starting-to-drive) here
  too. A model whose first output is far from where the arm is standing makes
  the follower travel to meet it.
</Warning>

## The safety envelope still applies

Everything a human operator passes through, the model passes through. The
follower clamps to `limits()`, caps the per tick step at `slew`, and holds if
commands stop arriving.

That matters for training: `action` in a recording is the clamped value, so a
policy trained on it learns the envelope rather than learning to command through
one it will not have. See
[Exporting datasets](/robotics/guides/exporting-datasets#what-a-row-holds).

<Note>
  Release the deadman to stop the model. The command stream stops, the
  follower's watchdog runs out, and the arm holds where it is. That is the same
  stop a person gets, and it does not depend on the model cooperating.
</Note>

## Watching without driving

A third peer can join and see everything without ever taking control. Give the
LeRobot leader adapter the joint names and no arm:

```python theme={null}
from zeroruntime.teleops.adapters.lerobot import SO101LeaderAdapter

watcher = SO101LeaderAdapter(
    MEETING_ID,
    motors=("shoulder_pan", "shoulder_lift", "elbow_flex",
            "wrist_flex", "wrist_roll", "gripper"),
    record="./sessions")

watcher.start()

for i in watcher.ticks(hz=30):
    obs = watcher.observation()
```

With no arm to read, `read_joints()` returns `{}` and the base refuses to send
anything at all. Do not call `claim_control()` on it. It is there to observe and
to record, which is useful when the person driving is not on the machine you
want the dataset on.

<Note>
  A leader recording is indexed by video frame rather than by observation, so it
  samples the session differently from the follower's copy. See
  [Recording](/robotics/concepts/recording).
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Leader" icon="gamepad" href="/robotics/api-reference/python/leader">
    Every argument, method and event on this side.
  </Card>

  <Card title="Exporting datasets" icon="table" href="/robotics/guides/exporting-datasets">
    Turn recorded sessions into training data.
  </Card>

  <Card title="Safety" icon="shield-halved" href="/robotics/concepts/safety">
    The checks every command passes, whoever sent it.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.