> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/guardrails/llms.txt.
> For full documentation content, see https://docs.nvidia.com/nemo/guardrails/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/guardrails/_mcp/server.

# nemoguardrails.telemetry

## Module Contents

### Classes

| Name                                                                     | Description                              |
| ------------------------------------------------------------------------ | ---------------------------------------- |
| [`DeploymentTypeEnum`](#nemoguardrails-telemetry-DeploymentTypeEnum)     | How the NeMo product was invoked.        |
| [`EventTypeEnum`](#nemoguardrails-telemetry-EventTypeEnum)               | -                                        |
| [`GuardrailsUsageEvent`](#nemoguardrails-telemetry-GuardrailsUsageEvent) | Usage event for NeMo Guardrails.         |
| [`NemoSourceEnum`](#nemoguardrails-telemetry-NemoSourceEnum)             | The NeMo product that created the event. |
| [`RailsEngineEnum`](#nemoguardrails-telemetry-RailsEngineEnum)           | -                                        |
| [`TelemetryEvent`](#nemoguardrails-telemetry-TelemetryEvent)             | Abstract base for telemetry events.      |

### Functions

| Name                                                                                       | Description                                                                   |
| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- |
| [`_build_event`](#nemoguardrails-telemetry-_build_event)                                   | Wrap a `TelemetryEvent` in the inner event dict for the NVIDIA envelope.      |
| [`_build_nvidia_payload`](#nemoguardrails-telemetry-_build_nvidia_payload)                 | Build the outer NVIDIA telemetry envelope that wraps one or more events.      |
| [`_collect_usage_data`](#nemoguardrails-telemetry-_collect_usage_data)                     | Collect anonymous usage data into a `GuardrailsUsageEvent`.                   |
| [`_detect_builtin_features`](#nemoguardrails-telemetry-_detect_builtin_features)           | Detect which built-in NeMo Guardrails library features are active.            |
| [`_flow_file_name`](#nemoguardrails-telemetry-_flow_file_name)                             | -                                                                             |
| [`_get_audit_file`](#nemoguardrails-telemetry-_get_audit_file)                             | Return the local audit JSONL path, honoring test overrides.                   |
| [`_get_config_dir`](#nemoguardrails-telemetry-_get_config_dir)                             | Return the telemetry config directory, honoring test overrides.               |
| [`_get_do_not_track_file`](#nemoguardrails-telemetry-_get_do_not_track_file)               | Return the do-not-track marker path, honoring test overrides.                 |
| [`_get_heartbeat_interval_s`](#nemoguardrails-telemetry-_get_heartbeat_interval_s)         | Return the heartbeat interval, falling back safely on bad env values.         |
| [`_get_iso_timestamp`](#nemoguardrails-telemetry-_get_iso_timestamp)                       | Format a Unix timestamp as an ISO 8601 UTC string with millisecond precision. |
| [`_get_usage_stats_server_url`](#nemoguardrails-telemetry-_get_usage_stats_server_url)     | Return the telemetry server URL, honoring runtime env overrides.              |
| [`_get_version`](#nemoguardrails-telemetry-_get_version)                                   | -                                                                             |
| [`_heartbeat_loop`](#nemoguardrails-telemetry-_heartbeat_loop)                             | Run the heartbeat loop forever in a daemon thread.                            |
| [`_is_custom_flow`](#nemoguardrails-telemetry-_is_custom_flow)                             | -                                                                             |
| [`_is_usage_stats_enabled`](#nemoguardrails-telemetry-_is_usage_stats_enabled)             | Check whether usage reporting is enabled.                                     |
| [`_is_v2_library_flow`](#nemoguardrails-telemetry-_is_v2_library_flow)                     | -                                                                             |
| [`_normalize_builtin_feature_id`](#nemoguardrails-telemetry-_normalize_builtin_feature_id) | Return the documented feature id for a RailsConfigData field.                 |
| [`_reset_for_fork`](#nemoguardrails-telemetry-_reset_for_fork)                             | Clear module state in a forked child so it starts a fresh session.            |
| [`_rotate_audit_file`](#nemoguardrails-telemetry-_rotate_audit_file)                       | Rotate the local audit file when it exceeds the size cap.                     |
| [`_safe_home_dir`](#nemoguardrails-telemetry-_safe_home_dir)                               | Return the user's home directory without raising at import time.              |
| [`_send_one_event`](#nemoguardrails-telemetry-_send_one_event)                             | Write a single event to the audit file and POST it.                           |
| [`_send_report`](#nemoguardrails-telemetry-_send_report)                                   | POST a single telemetry event to the configured server.                       |
| [`_start_daemon_thread`](#nemoguardrails-telemetry-_start_daemon_thread)                   | Start a daemon thread and report whether startup succeeded.                   |
| [`_write_audit_file`](#nemoguardrails-telemetry-_write_audit_file)                         | Append a payload to the local audit file as a JSON line.                      |
| [`report_usage`](#nemoguardrails-telemetry-report_usage)                                   | Emit one anonymous usage event for the given config.                          |
| [`set_deployment_type`](#nemoguardrails-telemetry-set_deployment_type)                     | Set the deployment type that subsequent `report_usage` calls will use.        |

### Data

[`_AUDIT_FILE`](#nemoguardrails-telemetry-_AUDIT_FILE)

[`_AUDIT_FILE_MAX_BYTES`](#nemoguardrails-telemetry-_AUDIT_FILE_MAX_BYTES)

[`_COLANG_V2_LIBRARY_DIR`](#nemoguardrails-telemetry-_COLANG_V2_LIBRARY_DIR)

[`_CONFIG_BUILTIN_FEATURE_ALIASES`](#nemoguardrails-telemetry-_CONFIG_BUILTIN_FEATURE_ALIASES)

[`_CONFIG_DIR`](#nemoguardrails-telemetry-_CONFIG_DIR)

[`_DO_NOT_TRACK_FILE`](#nemoguardrails-telemetry-_DO_NOT_TRACK_FILE)

[`_HEARTBEAT_INTERVAL_S`](#nemoguardrails-telemetry-_HEARTBEAT_INTERVAL_S)

[`_KNOWN_BUILTIN_FLOWS`](#nemoguardrails-telemetry-_KNOWN_BUILTIN_FLOWS)

[`_NVIDIA_CLIENT_ID`](#nemoguardrails-telemetry-_NVIDIA_CLIENT_ID)

[`_NVIDIA_EVENT_PROTOCOL`](#nemoguardrails-telemetry-_NVIDIA_EVENT_PROTOCOL)

[`_NVIDIA_EVENT_SYS_VER`](#nemoguardrails-telemetry-_NVIDIA_EVENT_SYS_VER)

[`_USAGE_STATS_SERVER`](#nemoguardrails-telemetry-_USAGE_STATS_SERVER)

[`_deployment_type_override`](#nemoguardrails-telemetry-_deployment_type_override)

[`_heartbeat_started`](#nemoguardrails-telemetry-_heartbeat_started)

[`_lock`](#nemoguardrails-telemetry-_lock)

[`_session_uuid`](#nemoguardrails-telemetry-_session_uuid)

[`log`](#nemoguardrails-telemetry-log)

### API

```python
class nemoguardrails.telemetry.DeploymentTypeEnum
```

**Bases:** `enum.Enum`

How the NeMo product was invoked.

Mirrors the shared nemo-telemetry definition. `library` covers
direct `LLMRails` / `Guardrails` use in user code, `api` is
the FastAPI server, `cli` is the interactive chat command.
`sdk` and `nmp` are inherited from the shared enum and are
valid values guardrails does not produce itself.

```python
class nemoguardrails.telemetry.EventTypeEnum
```

**Bases:** `enum.Enum`

```python
class nemoguardrails.telemetry.GuardrailsUsageEvent()
```

**Bases:** [TelemetryEvent](#nemoguardrails-telemetry-TelemetryEvent)

Usage event for NeMo Guardrails.

Emitted at each `LLMRails` or `IORails` instantiation and as
periodic heartbeats from a single daemon thread per process. The
`Guardrails` wrapper emits through whichever runtime engine it
constructs. All events from one process share a session ID. Contains
no user content, model names, or request-level data.

```python
class nemoguardrails.telemetry.NemoSourceEnum
```

**Bases:** `enum.Enum`

The NeMo product that created the event.

Mirrors the shared nemo-telemetry definition so the guardrails event
plugs into the same `definitions/types` block other NeMo products
(DataDesigner, Safe Synthesizer, Agent Toolkit, etc.) already share.

```python
class nemoguardrails.telemetry.RailsEngineEnum
```

**Bases:** `enum.Enum`

```python
class nemoguardrails.telemetry.TelemetryEvent()
```

**Bases:** `BaseModel`

Abstract base for telemetry events.

Subclasses must define `_event_name` as a ClassVar. The optional
`_schema_version` ClassVar is used by the payload builder to set
`eventSchemaVer` in the NVIDIA telemetry envelope.

**Raises:**

* `TypeError`: If a subclass fails to define `_event_name`.

```python
nemoguardrails.telemetry.TelemetryEvent.__init_subclass__(
    kwargs: typing.Any = {}
) -> None
```

```python
nemoguardrails.telemetry._build_event(
    event: nemoguardrails.telemetry.TelemetryEvent,
    ts: typing.Optional[float] = None
) -> typing.Dict[str, typing.Any]
```

Wrap a `TelemetryEvent` in the inner event dict for the NVIDIA envelope.

Always injects `nemoSource="guardrails"` into the parameters so
the backend can route the event correctly.

**Parameters:**

The Pydantic event instance to serialize.

Optional Unix timestamp for the `ts` field; uses current
time if `None`.

**Returns:** `Dict[str, Any]`

A dict with `ts`, `name`, and `parameters` keys, ready to

```python
nemoguardrails.telemetry._build_nvidia_payload(
    events: typing.List[nemoguardrails.telemetry.TelemetryEvent],
    client_version: str,
    session_id: str,
    timestamps: typing.Optional[typing.List[typing.Optional[float]]] = None
) -> typing.Dict[str, typing.Any]
```

Build the outer NVIDIA telemetry envelope that wraps one or more events.

All envelope fields other than `clientVer`, `sessionId`,
`eventSchemaVer`, `sentTs`, `cpuArchitecture`, and `events`
are hardcoded to `"undefined"` or `"None"` per the NVIDIA
telemetry protocol spec. `eventSchemaVer` is read from the first
event's `_schema_version` ClassVar.

**Parameters:**

Non-empty list of telemetry events to include.

Version string of the calling product, set as
`clientVer` (typically the package version).

Session identifier set as `sessionId` in the envelope.

Optional per-event Unix timestamps. If `None`,
each event is timestamped with the current time.

**Returns:** `Dict[str, Any]`

The complete envelope as a dict, ready to be JSON-serialized

**Raises:**

* `ValueError`: If `events` is empty.

```python
nemoguardrails.telemetry._collect_usage_data(
    config: typing.Optional[nemoguardrails.rails.llm.config.RailsConfig],
    deployment_type: str
) -> nemoguardrails.telemetry.GuardrailsUsageEvent
```

Collect anonymous usage data into a `GuardrailsUsageEvent`.

Always populates system fields (version, platform, Python version).
When `config` is provided, additionally populates config-derived
fields: LLM provider names, rail types in use, built-in features,
custom flow count, and feature flags. Never reads model names,
prompts, or user content.

**Parameters:**

The `RailsConfig` to inspect, or `None` for a
system-only event (e.g. from the server startup context).

How guardrails was deployed, e.g. `"library"`,
`"api"`, or `"cli"`. Coerced to
`DeploymentTypeEnum.UNDEFINED` if falsy.

**Returns:** `GuardrailsUsageEvent`

A fully populated `GuardrailsUsageEvent`.

```python
nemoguardrails.telemetry._detect_builtin_features(
    config: nemoguardrails.rails.llm.config.RailsConfig
) -> typing.List[str]
```

Detect which built-in NeMo Guardrails library features are active.

Uses two signals: (1) fields on `RailsConfigData` that differ from
their defaults (explicit config), and (2) exact-match flow names
against a known set of built-in library flows. Only our own feature
names are ever reported, never user-defined flow names.

**Parameters:**

The `RailsConfig` instance to inspect.

**Returns:** `List[str]`

Sorted list of active built-in feature names (e.g.

```python
nemoguardrails.telemetry._flow_file_name(
    flow: typing.Any
) -> typing.Optional[str]
```

```python
nemoguardrails.telemetry._get_audit_file() -> pathlib.Path
```

Return the local audit JSONL path, honoring test overrides.

```python
nemoguardrails.telemetry._get_config_dir() -> pathlib.Path
```

Return the telemetry config directory, honoring test overrides.

```python
nemoguardrails.telemetry._get_do_not_track_file() -> pathlib.Path
```

Return the do-not-track marker path, honoring test overrides.

```python
nemoguardrails.telemetry._get_heartbeat_interval_s() -> float
```

Return the heartbeat interval, falling back safely on bad env values.

```python
nemoguardrails.telemetry._get_iso_timestamp(
    ts: typing.Optional[float] = None
) -> str
```

Format a Unix timestamp as an ISO 8601 UTC string with millisecond precision.

**Parameters:**

Unix timestamp (seconds since epoch). If `None`, uses
the current UTC time.

**Returns:** `str`

ISO 8601 formatted string ending with `"Z"`, e.g.

```python
nemoguardrails.telemetry._get_usage_stats_server_url() -> str
```

Return the telemetry server URL, honoring runtime env overrides.

```python
nemoguardrails.telemetry._get_version(
    package_name: str
) -> str
```

```python
nemoguardrails.telemetry._heartbeat_loop(
    startup_event: nemoguardrails.telemetry.GuardrailsUsageEvent,
    session_id: str,
    client_version: str
) -> None
```

Run the heartbeat loop forever in a daemon thread.

Started exactly once per process (gated by `_heartbeat_started`).
Sleeps at least `_HEARTBEAT_INTERVAL_S` seconds, then emits a
heartbeat event tied to the process's session ID. The heartbeat
reuses a copy of the first startup event's metadata and changes
only `event`, `timestamp`, and `sessionId`. The thread is a
daemon so it dies with the main process; no explicit shutdown is
required.

**Parameters:**

The first startup event emitted by this process.

The process-stable session ID, mirrored into the
heartbeat event's `session_id` field and the envelope.

Value to set as `clientVer` in the envelope.

```python
nemoguardrails.telemetry._is_custom_flow(
    flow: typing.Any
) -> bool
```

```python
nemoguardrails.telemetry._is_usage_stats_enabled() -> bool
```

Check whether usage reporting is enabled.

Opt-out signals, any of which disables reporting:

* `NEMO_GUARDRAILS_NO_USAGE_STATS=1` / `true` env var
  (product-specific).
* `DO_NOT_TRACK=1` / `true` env var (industry-standard).
* `~/.config/nemoguardrails/do_not_track` file present.
* `CI` env var truthy (set by GitHub Actions, GitLab CI, CircleCI,
  Travis, Buildkite, etc.). Suppresses telemetry from automated test
  runs that are not real deployments. Honoring `CI` is the same
  convention used by Homebrew, npm, conda, and others.
* `PYTEST_CURRENT_TEST` env var present, or `pytest` already
  loaded in the process. Catches the case of a developer running
  tests locally without `CI=true`, including collection/import
  phases where `PYTEST_CURRENT_TEST` is not set, and suppresses
  any telemetry that would otherwise leak from a downstream user's
  test suite that happens to import nemoguardrails.

The intent is that adoption metrics reflect real deployments only,
not synthetic test/CI traffic.

**Returns:** `bool`

True if reporting should proceed, False if any opt-out is active.

```python
nemoguardrails.telemetry._is_v2_library_flow(
    flow: typing.Any
) -> bool
```

```python
nemoguardrails.telemetry._normalize_builtin_feature_id(
    field_name: str
) -> str
```

Return the documented feature id for a RailsConfigData field.

```python
nemoguardrails.telemetry._reset_for_fork() -> None
```

Clear module state in a forked child so it starts a fresh session.

Registered via `os.register_at_fork(after_in_child=...)` at module
import time on POSIX platforms. Without this, workers spawned by
`gunicorn --preload` (or any other fork-based runtime) would
inherit the parent's session ID and its `_heartbeat_started`
flag, but lose the actual heartbeat thread (POSIX `fork()` only
duplicates the calling thread). The result would be silent: every
worker would report under the parent's session and never emit
heartbeats. After this hook runs, the child's first `report_usage`
call generates a fresh session UUID and starts its own heartbeat.
The deployment-type override is intentionally preserved so a forked
API or CLI worker keeps the attribution claimed by its parent.

```python
nemoguardrails.telemetry._rotate_audit_file(
    audit_file: typing.Optional[pathlib.Path] = None
) -> None
```

Rotate the local audit file when it exceeds the size cap.

The current `usage_stats.json` is renamed to `usage_stats.json.1`,
overwriting any previous backup. This bounds on-disk usage at
approximately `2 * _AUDIT_FILE_MAX_BYTES`. Errors are silently
logged at DEBUG level.

```python
nemoguardrails.telemetry._safe_home_dir() -> pathlib.Path
```

Return the user's home directory without raising at import time.

```python
nemoguardrails.telemetry._send_one_event(
    event: nemoguardrails.telemetry.GuardrailsUsageEvent,
    server_url: str,
    client_version: str,
    session_id: str
) -> None
```

Write a single event to the audit file and POST it.

Used as the target of a one-shot daemon thread spawned by
`report_usage`. Fire-and-forget: errors are swallowed at DEBUG
level inside `_write_audit_file` and `_send_report`.

**Parameters:**

The telemetry event to record and transmit.

Full HTTPS URL of the telemetry endpoint.

Value to set as `clientVer` in the envelope.

Value to set as `sessionId` in the envelope.

```python
nemoguardrails.telemetry._send_report(
    event: nemoguardrails.telemetry.TelemetryEvent,
    server_url: str,
    client_version: str,
    session_id: str
) -> None
```

POST a single telemetry event to the configured server.

Fire-and-forget: a single attempt with a 5-second timeout, no
retries, all exceptions silently logged at DEBUG level. Runs in a
daemon thread so it never blocks the main process.

**Parameters:**

The telemetry event to send.

Full HTTPS URL of the telemetry endpoint.

Value to set as `clientVer` in the envelope.

Value to set as `sessionId` in the envelope.

```python
nemoguardrails.telemetry._start_daemon_thread(
    target: typing.Any,
    args: tuple[typing.Any, ...],
    failure_message: str
) -> bool
```

Start a daemon thread and report whether startup succeeded.

```python
nemoguardrails.telemetry._write_audit_file(
    data: typing.Dict[str, typing.Any]
) -> None
```

Append a payload to the local audit file as a JSON line.

Creates the config directory if it does not exist. Rotates the
audit file when it exceeds `_AUDIT_FILE_MAX_BYTES`. All errors
(permission denied, disk full, etc.) are silently logged at DEBUG
level so telemetry never disrupts the main process.

**Parameters:**

Serialized event payload (already converted to a dict
via `model_dump(by_alias=True)`).

```python
nemoguardrails.telemetry.report_usage(
    config: typing.Optional[nemoguardrails.rails.llm.config.RailsConfig] = None,
    deployment_type: str = 'library',
    rails_engine: str = ''
) -> None
```

Emit one anonymous usage event for the given config.

Each call produces a single event tied to the process's session ID
(lazily generated on first call, reused thereafter). The heartbeat
daemon thread is started exactly once per process. All work happens
off the calling thread so this function returns immediately.

The effective deployment type is resolved as: the value previously
passed to `set_deployment_type` if any, else the function argument.
This lets the server lifespan or CLI command claim the deployment
context once, and downstream `LLMRails.__init__` /
`Guardrails.__init__` calls inherit it without coordination.

Respects the triple opt-out (env vars and file).

**Parameters:**

`RailsConfig` to introspect. When `None`, only
system-level fields are populated.

How guardrails was deployed (e.g. `"library"`,
`"api"`, `"cli"`). Overridden by `set_deployment_type`.

Which engine class is in use (e.g. `"LLMRails"`,
`"IORails"`). Ignored if empty.

```python
nemoguardrails.telemetry.set_deployment_type(
    deployment_type: str
) -> None
```

Set the deployment type that subsequent `report_usage` calls will use.

Called by the FastAPI server lifespan (`"api"`) and the
`nemoguardrails chat` CLI command (`"cli"`) before `LLMRails`
is constructed. Takes precedence over the `deployment_type` argument
passed by `LLMRails.__init__` and `Guardrails.__init__`, so the
same library-internal call sites emit the correct value depending on
how the process was invoked.

Invalid values are silently ignored (logged at DEBUG level), so a
bad caller never crashes the host process.

**Parameters:**

One of the `DeploymentTypeEnum` string values
(e.g. `"api"`, `"cli"`, `"library"`).

```python
nemoguardrails.telemetry._AUDIT_FILE: Optional[Path] = None
```

```python
nemoguardrails.telemetry._AUDIT_FILE_MAX_BYTES = 10 * 1024 * 1024
```

```python
nemoguardrails.telemetry._COLANG_V2_LIBRARY_DIR = Path(__file__).resolve().parent / 'colang' / 'v2_x' / 'library'
```

```python
nemoguardrails.telemetry._CONFIG_BUILTIN_FEATURE_ALIASES = {'fact_checking': 'factchecking', 'patronus': 'patronusai', 'regex_detection': '...
```

```python
nemoguardrails.telemetry._CONFIG_DIR: Optional[Path] = None
```

```python
nemoguardrails.telemetry._DO_NOT_TRACK_FILE: Optional[Path] = None
```

```python
nemoguardrails.telemetry._HEARTBEAT_INTERVAL_S = _get_heartbeat_interval_s()
```

```python
nemoguardrails.telemetry._KNOWN_BUILTIN_FLOWS = {'activefence moderation on input': 'activefence', 'activefence moderation on in...
```

```python
nemoguardrails.telemetry._NVIDIA_CLIENT_ID = '184482118588404'
```

```python
nemoguardrails.telemetry._NVIDIA_EVENT_PROTOCOL = '1.6'
```

```python
nemoguardrails.telemetry._NVIDIA_EVENT_SYS_VER = 'nemo-telemetry/1.0'
```

```python
nemoguardrails.telemetry._USAGE_STATS_SERVER = 'https://events.telemetry.data.nvidia.com/v1.1/events/json'
```

```python
nemoguardrails.telemetry._deployment_type_override: Optional[DeploymentTypeEnum] = None
```

```python
nemoguardrails.telemetry._heartbeat_started = False
```

```python
nemoguardrails.telemetry._lock = threading.Lock()
```

```python
nemoguardrails.telemetry._session_uuid: Optional[str] = None
```

```python
nemoguardrails.telemetry.log = logging.getLogger(__name__)
```