> ## 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.

# Action

> What the leader asked for, what the follower wrote, and anything held back in between.

**Everything on this page travels leader to follower.** The leader sends a
`Command`, the follower writes an `AppliedAction`, and a `LimitEvent` records
any joint it had to hold back on the way.

```mermaid theme={null}
sequenceDiagram
    participant L as Leader
    participant F as Follower
    L->>F: Command, where to move
    F->>F: checks your limits, writes AppliedAction
    F->>L: Observation, which frames go together
    F->>L: RobotState, joints and safe state
    F-->>L: camera video
    L->>L: pairs them into SyncedObservation
```

`on_applied` hands you the `AppliedAction`, and `on_limited` hands you one
`LimitEvent` per joint that was held back. What comes back the other way is an
[Observation](/robotics/api-reference/python/observation).

## Command

One tick of the leader's pose, on its way to the follower. The SDK packs it
from your `read_joints()` and sends it.

<ParamField path="command_id" type="int">
  Identifies this command for the whole session. Safe to use as a key when
  matching a dataset row back to its command.
</ParamField>

<ParamField path="observation_id" type="int">
  The newest observation the leader had when it asked, so you can tell what it
  was looking at.
</ParamField>

<ParamField path="groups" type="dict">
  The values asked for, in the order the descriptor declares them.
</ParamField>

## AppliedAction

What the follower actually wrote to the motors, and how far that was from what
was asked.

<ParamField path="action" type="dict[str, float]">
  The values written, after limits and the speed cap.
</ParamField>

<ParamField path="target" type="dict[str, float]">
  The values asked for, before either. Kept so the difference stays visible.
</ParamField>

<ParamField path="was_limited" type="bool">
  `True` when anything was held back on this tick.
</ParamField>

<ParamField path="limits" type="tuple[LimitEvent, ...]">
  One entry per joint that was held back. Empty when nothing was.
</ParamField>

<ParamField path="command_id" type="int">
  Which command this came from.
</ParamField>

<ParamField path="observation_id" type="int">
  Which observation that command was acting on.
</ParamField>

<ParamField path="obs_to_applied_ms" type="float">
  Milliseconds from that observation to this write. Both ends are timed on the
  follower, so it is exact.
</ParamField>

<ParamField path="write_ok" type="bool">
  `False` means your `write_joints()` raised, and the follower stopped the arm.
</ParamField>

```python theme={null}
@follower.on_applied
def _(action):
    if action.was_limited:
        print("held back", [e.joint for e in action.limits])
```

<Note>
  Keeping both is what lets you tell smooth driving from a limit doing the work.
  Train on `action`, since that is what the arm really did.
</Note>

## LimitEvent

One joint that was held back on one tick.

<ParamField path="joint" type="str">
  Which joint.
</ParamField>

<ParamField path="requested" type="float">
  What was asked for.
</ParamField>

<ParamField path="applied" type="float">
  What was written instead.
</ParamField>

<ParamField path="excess" type="float">
  The difference between the two.
</ParamField>

<ParamField path="rule" type="LimitRule">
  `POSITION` if it hit a joint limit, `SLEW` if it was moving too fast.
</ParamField>

<Tip>
  Watch `excess`, not just the count. A joint held back by `0.2` is rounding.
  The same joint held back by `40` means something is wrong with your limits or
  your calibration.
</Tip>

## Related

<CardGroup cols={2}>
  <Card title="Observation" icon="eye" href="/robotics/api-reference/python/observation">
    What the leader was looking at when it asked.
  </Card>

  <Card title="SafetyConfig" icon="sliders" href="/robotics/api-reference/python/safety-config">
    The limits that turn a command into an applied action.
  </Card>
</CardGroup>


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