> For the complete documentation index, see [llms.txt](https://docs.autopilotmonitor.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.autopilotmonitor.com/rules/gather-rules.md).

# Gather Rules

Gather rules define **what extra data the agent collects** from the device during enrollment. Each rule specifies a **collector type** (how to collect), a **target** (what to collect), optional **parameters**, and a **trigger** (when to collect). Results arrive as events in the session timeline — where [analyze rules](/rules/analyze-rules.md) can grade them automatically.

A set of maintained built-in and community gather rules ships with the product; your own rules are created on the **Gather Rules** page.

## Collector types

| Collector                 | Collects                                                                                                                                                       | Target example                                                                       |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **Registry**              | Values of a key (or subkey names with `listSubkeys`) — reads the 64-bit view by default, with `emitOnlyIfExists` to only emit when the key is actually present | `HKLM\SOFTWARE\Microsoft\PolicyManager\current\device`                               |
| **Event Log**             | Entries from classic or operational Windows event logs, filterable by event ID, source, and message                                                            | `Microsoft-Windows-Shell-Core/Operational`, event ID `62407`, filter `*ESPProgress*` |
| **WMI Query**             | Results of a full WQL `SELECT` statement against allow-listed classes                                                                                          | `SELECT * FROM Win32_NetworkAdapterConfiguration`                                    |
| **File**                  | File/directory existence, size, and optionally content (last 4,000 characters, files < 50 KB)                                                                  | `C:\Windows\Panther\setuperr.log` with `readContent: true`                           |
| **Command (Allowlisted)** | Output of a **pre-approved** PowerShell/CLI command — exact allow-list match only                                                                              | `Get-Tpm`                                                                            |
| **Log Parser**            | Regex matches (named capture groups) from log files — CMTrace or plain-text format, with position tracking and filename wildcards                              | `%ProgramData%\...\IntuneManagementExtension\Logs\AppWorkload*.log`                  |
| **JSON (JSONPath)**       | Values extracted from a JSON file via JSONPath (file < 200 KB)                                                                                                 | `$..DetectionScript`                                                                 |
| **XML (XPath)**           | Elements/attributes extracted from an XML file via XPath, with namespace support                                                                               | `//ns:setting[@name='ComputerName']/@value`                                          |

{% hint style="info" %}
**Targeting the user profile:** the agent runs as SYSTEM, so `%USERPROFILE%` resolves to the SYSTEM profile. Use the special token `%LOGGED_ON_USER_PROFILE%` to reach the signed-in user's profile (only `AppData\Local` and `AppData\Roaming` are allowed). Rules using the token are skipped automatically until a user session exists.
{% endhint %}

## Triggers

| Trigger          | Runs                                                                                                                                                                         | Use for                                                |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| **Startup**      | Once, when the agent starts monitoring                                                                                                                                       | Initial device state (BIOS, TPM, OS info)              |
| **Interval**     | Every 5–3600 seconds                                                                                                                                                         | Continuous monitoring (network status, policy changes) |
| **Phase Change** | When enrollment enters a specific ESP phase (`Start`, `DevicePreparation`, `DeviceSetup`, `AppsDevice`, `AccountSetup`, `AppsUser`, `FinalizingSetup`, `Complete`, `Failed`) | State checks at a defined point of enrollment          |
| **On Event**     | When a specific event type is emitted (e.g. `enrollment_complete`, `enrollment_failed`, `app_install_failed`)                                                                | Collecting "at the end" or in reaction to a failure    |

{% hint style="warning" %}
**Mind the ingestion rate limit.** Event ingestion is rate-limited **per device at 100 requests per minute** — a budget shared by *everything* the agent sends: its built-in telemetry, IME-derived events, *and* your gather rules. Noisy gather rules — several **Interval** rules firing every 60 seconds, or one rule producing many events per run (log parsers, broad registry reads) — can exhaust that budget. Uploads beyond the limit are rejected until the window clears, so telemetry arrives delayed or gaps appear in the timeline.

Rules of thumb: prefer **Startup**, **Phase Change**, or **On Event** triggers over intervals; when you do poll, use the widest interval that still answers your question (an enrollment rarely needs anything sampled more often than every few minutes); and cap what each run returns (`maxEntries`, `maxLines`, `maxResults`).
{% endhint %}

## What the data looks like

Each execution emits one event with the rule's configured **output event type** and severity. The collected values live in the event's `data` field — and that's exactly what analyze rules reference via `dataField`:

| Collector  | Data fields produced                                                                                                                   |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Registry   | Value names as keys, or `subkey_count` + `subkey_0`, `subkey_1`, …                                                                     |
| Event Log  | Event properties as key-value pairs                                                                                                    |
| WMI Query  | The WMI object's properties as keys                                                                                                    |
| File       | `exists`, `path`, `size_bytes`, `content` (if `readContent`)                                                                           |
| Command    | `output` (stdout, max 32 KB), `error_output` (stderr), `exit_code`, `command` — **raw text**, graded with `contains`/`regex` operators |
| Log Parser | Your regex's named capture groups as keys                                                                                              |
| JSON / XML | The matched values as key-value pairs                                                                                                  |

See [Cookbook recipe 7](/rules/analyze-rules/cookbook.md#recipe-7-collect-your-own-data-and-grade-it-end-to-end) for the full gather → analyze pattern in action.

## Security guardrails

Custom collection on managed devices is a sensitive capability, so every collector enforces **allow-lists on the agent itself** — not just in the portal:

* **Registry** paths must fall under approved `HKLM\`/`HKCU\` prefixes (segment-bounded: subkeys of an allowed prefix are fine, sibling keys are not).
* **File / JSON / XML / Log Parser** paths must be within approved directories.
* **WMI** queries must target approved classes; **commands** must match the allow-list *exactly* — arbitrary commands are impossible.
* A rule targeting anything outside the allow-lists doesn't fail silently: the agent emits a **`security_warning` event** into the timeline instead, so misconfigurations are visible.

The current allow-lists are shown inline on the Gather Rules page in the portal (expandable under each collector type).

{% hint style="warning" %}
**Unrestricted Mode** relaxes the registry/WMI/command guardrails for environments that need broader collection. It is not generally available: the capability has to be **unlocked for your tenant by the platform operators on request** — only then does the toggle appear under Settings → Agent. Hard limits remain even with it enabled: `C:\Users` stays blocked and dangerous operations stay impossible. Leave it off unless a specific rule requires it.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.autopilotmonitor.com/rules/gather-rules.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
