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

# Recording Rules

> Automatic rules to flag and tag recordings matching conditions

Define rules that automatically evaluate recordings and take actions when conditions match. Rules run on incoming recording data and can tag recordings, create timeline events, flag items for human review, or trigger notifications -- without any manual intervention.

<Info>
  Fleet Management is in preview. APIs and features described on this page may change.
</Info>

## How Rules Work

1. You define a rule with a **condition** (what to look for) and one or more **actions** (what to do when found).
2. When a recording finishes processing, all active rules evaluate against its data.
3. If a rule's condition matches, its actions execute automatically.
4. Rule evaluation results are logged for auditing and debugging.

Rules evaluate against topic data, recording metadata, and event patterns within a recording. They can target specific devices, device groups, or apply fleet-wide.

## Rule Types

| Rule Type   | Description                                         | Example Use Case                                                        |
| ----------- | --------------------------------------------------- | ----------------------------------------------------------------------- |
| `threshold` | Numeric value exceeds or falls below a limit        | Motor temperature > 80C, latency > 100ms                                |
| `pattern`   | Regex match on topic data or metadata fields        | Error message contains "timeout", topic name matches `/sensors/*/error` |
| `frequency` | Event occurs more than N times within a time window | More than 5 errors in 1 minute, heartbeat rate drops below 1 Hz         |
| `absence`   | Expected data is missing for a specified duration   | No heartbeat for 30 seconds, missing camera frames for 5 seconds        |
| `composite` | Logical combination of other conditions (AND, OR)   | Temperature > 80C AND motor speed > 1000 RPM                            |

## Creating Rules

### Threshold Rule

The most common rule type. Monitor a numeric field on a topic and trigger when it crosses a boundary.

<CodeGroup>
  ```python Python theme={null}
  from avala import Client

  client = Client()

  rule = client.fleet.rules.create(
      name="High Latency Alert",
      description="Triggers when control loop latency exceeds 100ms for more than 1 minute",
      condition={
          "type": "threshold",
          "topic": "/diagnostics/latency",
          "field": "data.value",
          "operator": "gt",
          "value": 100,
          "window": "1m"
      },
      actions=[
          {"type": "tag", "value": "high-latency"},
          {"type": "create_event", "event_type": "warning", "label": "High latency detected"},
          {"type": "notify", "channel_id": "ch_abc123"}
      ]
  )

  print(f"Rule created: {rule.name} ({rule.uid})")
  ```

  ```typescript TypeScript theme={null}
  import Avala from "@avala-ai/sdk";

  const avala = new Avala();

  const rule = await avala.fleet.rules.create({
    name: "High Latency Alert",
    description: "Triggers when control loop latency exceeds 100ms for more than 1 minute",
    condition: {
      type: "threshold",
      topic: "/diagnostics/latency",
      field: "data.value",
      operator: "gt",
      value: 100,
      window: "1m",
    },
    actions: [
      { type: "tag", value: "high-latency" },
      { type: "create_event", eventType: "warning", label: "High latency detected" },
      { type: "notify", channelId: "ch_abc123" },
    ],
  });

  console.log(`Rule created: ${rule.name} (${rule.uid})`);
  ```

  ```bash CLI theme={null}
  avala fleet rules create \
    --name "High Latency Alert" \
    --condition '{"type": "threshold", "topic": "/diagnostics/latency", "field": "data.value", "operator": "gt", "value": 100, "window": "1m"}' \
    --action tag:high-latency \
    --action create_event:warning:"High latency detected" \
    --action notify:ch_abc123
  ```
</CodeGroup>

### Condition Operators

| Operator  | Description                | Valid For                       |
| --------- | -------------------------- | ------------------------------- |
| `gt`      | Greater than               | Numeric fields                  |
| `gte`     | Greater than or equal      | Numeric fields                  |
| `lt`      | Less than                  | Numeric fields                  |
| `lte`     | Less than or equal         | Numeric fields                  |
| `eq`      | Equal to                   | Numeric, string, boolean fields |
| `neq`     | Not equal to               | Numeric, string, boolean fields |
| `between` | Within a range (inclusive) | Numeric fields                  |
| `outside` | Outside a range            | Numeric fields                  |

### Pattern Rule

Match against string values in topic data or recording metadata using regular expressions.

<CodeGroup>
  ```python Python theme={null}
  rule = client.fleet.rules.create(
      name="Timeout Error Detector",
      description="Flags recordings containing timeout errors in diagnostics",
      condition={
          "type": "pattern",
          "topic": "/diagnostics/errors",
          "field": "message",
          "regex": "(?i)timeout|timed?\\s*out",
      },
      actions=[
          {"type": "tag", "value": "has-timeout-errors"},
          {"type": "flag_for_review"},
          {"type": "create_event", "event_type": "error", "label": "Timeout error detected"}
      ]
  )
  ```

  ```typescript TypeScript theme={null}
  const rule = await avala.fleet.rules.create({
    name: "Timeout Error Detector",
    description: "Flags recordings containing timeout errors in diagnostics",
    condition: {
      type: "pattern",
      topic: "/diagnostics/errors",
      field: "message",
      regex: "(?i)timeout|timed?\\s*out",
    },
    actions: [
      { type: "tag", value: "has-timeout-errors" },
      { type: "flag_for_review" },
      { type: "create_event", eventType: "error", label: "Timeout error detected" },
    ],
  });
  ```
</CodeGroup>

### Frequency Rule

Trigger when an event or condition occurs more (or fewer) than a specified number of times within a sliding time window.

<CodeGroup>
  ```python Python theme={null}
  rule = client.fleet.rules.create(
      name="Error Burst Detector",
      description="Triggers when more than 5 errors occur within any 1-minute window",
      condition={
          "type": "frequency",
          "topic": "/diagnostics/errors",
          "count_operator": "gt",
          "count": 5,
          "window": "1m"
      },
      actions=[
          {"type": "tag", "value": "error-burst"},
          {"type": "create_event", "event_type": "anomaly", "label": "Error burst detected"},
          {"type": "notify", "channel_id": "ch_abc123"}
      ]
  )
  ```

  ```typescript TypeScript theme={null}
  const rule = await avala.fleet.rules.create({
    name: "Error Burst Detector",
    description: "Triggers when more than 5 errors occur within any 1-minute window",
    condition: {
      type: "frequency",
      topic: "/diagnostics/errors",
      countOperator: "gt",
      count: 5,
      window: "1m",
    },
    actions: [
      { type: "tag", value: "error-burst" },
      { type: "create_event", eventType: "anomaly", label: "Error burst detected" },
      { type: "notify", channelId: "ch_abc123" },
    ],
  });
  ```
</CodeGroup>

### Absence Rule

Detect missing data -- useful for heartbeat monitoring, dropped sensor feeds, and connectivity issues.

<CodeGroup>
  ```python Python theme={null}
  rule = client.fleet.rules.create(
      name="Missing Heartbeat",
      description="Triggers when no heartbeat message appears for 30 seconds",
      condition={
          "type": "absence",
          "topic": "/system/heartbeat",
          "timeout": "30s"
      },
      actions=[
          {"type": "create_event", "event_type": "error", "label": "Heartbeat lost"},
          {"type": "notify", "channel_id": "ch_abc123"}
      ]
  )
  ```

  ```typescript TypeScript theme={null}
  const rule = await avala.fleet.rules.create({
    name: "Missing Heartbeat",
    description: "Triggers when no heartbeat message appears for 30 seconds",
    condition: {
      type: "absence",
      topic: "/system/heartbeat",
      timeout: "30s",
    },
    actions: [
      { type: "create_event", eventType: "error", label: "Heartbeat lost" },
      { type: "notify", channelId: "ch_abc123" },
    ],
  });
  ```
</CodeGroup>

### Composite Rule

Combine multiple conditions with logical operators for complex detection scenarios.

<CodeGroup>
  ```python Python theme={null}
  rule = client.fleet.rules.create(
      name="Thermal Overload Risk",
      description="Triggers when temperature is high AND motor is under heavy load",
      condition={
          "type": "composite",
          "operator": "and",
          "conditions": [
              {
                  "type": "threshold",
                  "topic": "/sensors/temperature",
                  "field": "temp_c",
                  "operator": "gt",
                  "value": 80
              },
              {
                  "type": "threshold",
                  "topic": "/motors/joint_3",
                  "field": "current_a",
                  "operator": "gt",
                  "value": 5.0
              }
          ]
      },
      actions=[
          {"type": "tag", "value": "thermal-overload-risk"},
          {"type": "create_event", "event_type": "warning", "label": "Thermal overload risk"},
          {"type": "flag_for_review"},
          {"type": "notify", "channel_id": "ch_abc123"}
      ]
  )
  ```

  ```typescript TypeScript theme={null}
  const rule = await avala.fleet.rules.create({
    name: "Thermal Overload Risk",
    description: "Triggers when temperature is high AND motor is under heavy load",
    condition: {
      type: "composite",
      operator: "and",
      conditions: [
        {
          type: "threshold",
          topic: "/sensors/temperature",
          field: "temp_c",
          operator: "gt",
          value: 80,
        },
        {
          type: "threshold",
          topic: "/motors/joint_3",
          field: "current_a",
          operator: "gt",
          value: 5.0,
        },
      ],
    },
    actions: [
      { type: "tag", value: "thermal-overload-risk" },
      { type: "create_event", eventType: "warning", label: "Thermal overload risk" },
      { type: "flag_for_review" },
      { type: "notify", channelId: "ch_abc123" },
    ],
  });
  ```
</CodeGroup>

## Rule Actions

Each rule can have one or more actions that execute when its condition matches.

| Action            | Description                                          | Parameters                                 |
| ----------------- | ---------------------------------------------------- | ------------------------------------------ |
| `tag`             | Add a tag to the recording                           | `value`: tag string                        |
| `create_event`    | Create a timeline event marker on the recording      | `event_type`, `label`, optional `severity` |
| `flag_for_review` | Mark the recording for human review in the dashboard | None                                       |
| `notify`          | Send a notification via a configured alert channel   | `channel_id`                               |
| `auto_label`      | Trigger an auto-labeling pipeline on the recording   | `pipeline_id`                              |

<Note>
  Actions execute in the order they are defined. If a `notify` action fails (e.g., Slack webhook returns an error), subsequent actions still execute. Failed actions are logged in the rule evaluation results.
</Note>

### Tag Action

Tags are searchable strings attached to recordings. Use tags to categorize recordings for downstream filtering in the recording browser or SDK queries.

```python theme={null}
{"type": "tag", "value": "high-latency"}
```

### Create Event Action

Creates a timestamped [event marker](/docs/visualization/fleet/events-and-markers) on the recording at the point where the condition matched.

```python theme={null}
{"type": "create_event", "event_type": "warning", "label": "High latency detected", "severity": "warning"}
```

### Flag for Review Action

Marks the recording in the dashboard with a review flag. Flagged recordings appear in the "Needs Review" filter in the recording browser.

```python theme={null}
{"type": "flag_for_review"}
```

### Notify Action

Sends a notification to a configured [alert channel](/docs/visualization/fleet/alerts-and-notifications). The notification includes the rule name, recording ID, device name, and a link to the recording in the viewer.

```python theme={null}
{"type": "notify", "channel_id": "ch_abc123"}
```

### Auto-Label Action

Triggers an auto-labeling pipeline on the recording. Useful for running ML inference on recordings that match specific patterns -- for example, auto-labeling all recordings tagged with "near-miss" events.

```python theme={null}
{"type": "auto_label", "pipeline_id": "pipe_abc123"}
```

## Rule Scope

By default, rules apply to all recordings across the fleet. You can narrow a rule's scope to specific devices or device groups.

<CodeGroup>
  ```python Python theme={null}
  # Rule scoped to a specific device group
  rule = client.fleet.rules.create(
      name="Warehouse B Temperature Monitor",
      scope={
          "group_ids": ["grp_abc123"]
      },
      condition={
          "type": "threshold",
          "topic": "/sensors/temperature",
          "field": "temp_c",
          "operator": "gt",
          "value": 45
      },
      actions=[
          {"type": "tag", "value": "high-temp"},
          {"type": "create_event", "event_type": "warning", "label": "High ambient temperature"}
      ]
  )

  # Rule scoped to specific devices
  rule = client.fleet.rules.create(
      name="Robot Arm 01 Force Monitor",
      scope={
          "device_ids": ["dev_abc123", "dev_def456"]
      },
      condition={
          "type": "threshold",
          "topic": "/sensors/force",
          "field": "force_n",
          "operator": "gt",
          "value": 50
      },
      actions=[
          {"type": "create_event", "event_type": "anomaly", "label": "Force spike"}
      ]
  )
  ```

  ```typescript TypeScript theme={null}
  // Rule scoped to a specific device group
  const rule = await avala.fleet.rules.create({
    name: "Warehouse B Temperature Monitor",
    scope: {
      groupIds: ["grp_abc123"],
    },
    condition: {
      type: "threshold",
      topic: "/sensors/temperature",
      field: "temp_c",
      operator: "gt",
      value: 45,
    },
    actions: [
      { type: "tag", value: "high-temp" },
      { type: "create_event", eventType: "warning", label: "High ambient temperature" },
    ],
  });
  ```
</CodeGroup>

## Rule Management

### List Rules

<CodeGroup>
  ```python Python theme={null}
  # List all enabled rules
  rules = client.fleet.rules.list(enabled=True)
  for rule in rules:
      print(f"{rule.name} ({rule.uid}) -- enabled={rule.enabled}")
      print(f"  Hits: {rule.hit_count} | Last hit: {rule.last_hit_at}")

  # Filter by condition type
  threshold_rules = client.fleet.rules.list(condition_type="threshold")
  ```

  ```typescript TypeScript theme={null}
  const rules = await avala.fleet.rules.list({ enabled: true });
  for (const rule of rules.items) {
    console.log(`${rule.name} (${rule.uid}) -- enabled=${rule.enabled}`);
    console.log(`  Hits: ${rule.hitCount} | Last hit: ${rule.lastHitAt}`);
  }
  ```

  ```bash CLI theme={null}
  avala fleet rules list --enabled
  avala fleet rules list --type threshold
  ```
</CodeGroup>

### Enable and Disable Rules

Pause a rule without deleting it. Disabled rules are preserved with their configuration and hit history.

<CodeGroup>
  ```python Python theme={null}
  # Disable a rule
  client.fleet.rules.update(rule_id="rul_abc123", enabled=False)

  # Re-enable a rule
  client.fleet.rules.update(rule_id="rul_abc123", enabled=True)
  ```

  ```typescript TypeScript theme={null}
  await avala.fleet.rules.update({ ruleId: "rul_abc123", enabled: false });
  await avala.fleet.rules.update({ ruleId: "rul_abc123", enabled: true });
  ```

  ```bash CLI theme={null}
  avala fleet rules disable rul_abc123
  avala fleet rules enable rul_abc123
  ```
</CodeGroup>

### Delete a Rule

<CodeGroup>
  ```python Python theme={null}
  client.fleet.rules.delete(rule_id="rul_abc123")
  ```

  ```typescript TypeScript theme={null}
  await avala.fleet.rules.delete({ ruleId: "rul_abc123" });
  ```

  ```bash CLI theme={null}
  avala fleet rules delete rul_abc123
  ```
</CodeGroup>

<Warning>
  Deleting a rule is permanent. Events and tags previously created by the rule are not removed -- only future evaluation stops. If you want to temporarily stop a rule, disable it instead.
</Warning>

## Rule Statistics

Each rule tracks evaluation statistics to help you tune conditions and reduce false positives.

| Metric              | Description                                                             |
| ------------------- | ----------------------------------------------------------------------- |
| `evaluation_count`  | Total number of recordings evaluated against this rule                  |
| `hit_count`         | Number of recordings that matched the rule's condition                  |
| `hit_rate`          | Percentage of evaluations that matched (hit\_count / evaluation\_count) |
| `last_hit_at`       | Timestamp of the most recent match                                      |
| `avg_evaluation_ms` | Average time to evaluate the rule against a recording                   |

<CodeGroup>
  ```python Python theme={null}
  rule = client.fleet.rules.get(rule_id="rul_abc123")

  print(f"Rule: {rule.name}")
  print(f"Evaluations: {rule.stats.evaluation_count}")
  print(f"Hits: {rule.stats.hit_count} ({rule.stats.hit_rate:.1%})")
  print(f"Last hit: {rule.stats.last_hit_at}")
  print(f"Avg evaluation time: {rule.stats.avg_evaluation_ms:.0f}ms")
  ```

  ```typescript TypeScript theme={null}
  const rule = await avala.fleet.rules.get({ ruleId: "rul_abc123" });

  console.log(`Rule: ${rule.name}`);
  console.log(`Evaluations: ${rule.stats.evaluationCount}`);
  console.log(`Hits: ${rule.stats.hitCount} (${(rule.stats.hitRate * 100).toFixed(1)}%)`);
  console.log(`Last hit: ${rule.stats.lastHitAt}`);
  console.log(`Avg evaluation time: ${rule.stats.avgEvaluationMs.toFixed(0)}ms`);
  ```
</CodeGroup>

## Rule Dashboard

The rule dashboard in Mission Control displays all rules with their hit rates, recent matches, and status. From the dashboard you can:

* View rule hit rate trends over time
* Inspect recent matches with links to the matched recordings
* Toggle rules on and off
* Duplicate rules as templates for new variations
* View evaluation logs for debugging conditions that match unexpectedly (or fail to match)

<Tip>
  If a rule has a high hit rate (above 80%), the condition may be too broad. If it has a very low hit rate (below 1%) over a meaningful sample, the condition may be too strict or targeting the wrong topic/field. Use the evaluation logs to inspect individual matches and near-misses.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="" icon="bell" href="/docs/visualization/fleet/alerts-and-notifications">
    <p style={{fontWeight: 600, fontSize: '18px', marginBottom: '4px', marginTop: '8px', color: 'inherit'}}>Alerts & Notifications</p>
    <p style={{fontSize: '14px', marginTop: '0px', opacity: 0.6}}>Route notifications to Slack, email, and webhooks when rules trigger.</p>
  </Card>

  <Card title="" icon="flag" href="/docs/visualization/fleet/events-and-markers">
    <p style={{fontWeight: 600, fontSize: '18px', marginBottom: '4px', marginTop: '8px', color: 'inherit'}}>Events & Markers</p>
    <p style={{fontSize: '14px', marginTop: '0px', opacity: 0.6}}>Understand the timeline events that rules can create automatically.</p>
  </Card>

  <Card title="" icon="gauge-high" href="/docs/visualization/fleet/fleet-dashboard">
    <p style={{fontWeight: 600, fontSize: '18px', marginBottom: '4px', marginTop: '8px', color: 'inherit'}}>Fleet Dashboard</p>
    <p style={{fontSize: '14px', marginTop: '0px', opacity: 0.6}}>Manage devices, recordings, and fleet metrics from the central dashboard.</p>
  </Card>

  <Card title="" icon="magnifying-glass" href="/docs/visualization/guides/data-exploration">
    <p style={{fontWeight: 600, fontSize: '18px', marginBottom: '4px', marginTop: '8px', color: 'inherit'}}>Data Exploration</p>
    <p style={{fontSize: '14px', marginTop: '0px', opacity: 0.6}}>Explore recording data interactively before defining rules.</p>
  </Card>
</CardGroup>
