> This page is for version 0.3.0.
> For other versions, use one of these documentation indexes:
> - Main (default): https://docs.nvidia.com/nemo/gym/main/llms.txt
> - 0.7.0: https://docs.nvidia.com/nemo/gym/v0.7.0/llms.txt
> - 0.6.0: https://docs.nvidia.com/nemo/gym/v0.6.0/llms.txt
> - 0.5.1: https://docs.nvidia.com/nemo/gym/v0.5.1/llms.txt
> - 0.5.0: https://docs.nvidia.com/nemo/gym/v0.5.0/llms.txt
> - 0.4.0: https://docs.nvidia.com/nemo/gym/v0.4.0/llms.txt
> - 0.3.0: https://docs.nvidia.com/nemo/gym/v0.3.0/llms.txt
> - 0.2.1: https://docs.nvidia.com/nemo/gym/v0.2.1/llms.txt

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

# nemo_gym.trajectory.trajectory_format

Versioned trajectory wire formats and their deliberately lossy v1 projection.

## Module Contents

### Functions

| Name                                                                                              | Description                                                                          |
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| [`_legacy_interval_preserved`](#nemo_gym-trajectory-trajectory_format-_legacy_interval_preserved) | -                                                                                    |
| [`_project_gaps_v1`](#nemo_gym-trajectory-trajectory_format-_project_gaps_v1)                     | -                                                                                    |
| [`_restore_native_tool_ids`](#nemo_gym-trajectory-trajectory_format-_restore_native_tool_ids)     | Restore v1's native request namespace only with an explicit, collision-free mapping. |
| [`canonical_tool_record`](#nemo_gym-trajectory-trajectory_format-canonical_tool_record)           | Keep canonical timing separate from the old flat compatibility projection.           |
| [`project_bundle_v1`](#nemo_gym-trajectory-trajectory_format-project_bundle_v1)                   | Return the unversioned observation envelope accepted by existing readers.            |
| [`project_observation_v1`](#nemo_gym-trajectory-trajectory_format-project_observation_v1)         | Project only qualified intervals, keeping unknown values unknown.                    |
| [`project_result_v1`](#nemo_gym-trajectory-trajectory_format-project_result_v1)                   | Export both retained envelopes with one atomic, conservative identity decision.      |
| [`project_trajectory_v1`](#nemo_gym-trajectory-trajectory_format-project_trajectory_v1)           | Return v1, losing attempt, instance, parent, failure and detailed timing provenance. |
| [`reject_v2_fields`](#nemo_gym-trajectory-trajectory_format-reject_v2_fields)                     | Do not silently discard meaningful v2 evidence mislabeled as a v1 wire record.       |
| [`validate_failure_events`](#nemo_gym-trajectory-trajectory_format-validate_failure_events)       | Validate the shared serialized failure-event map without constructing exceptions.    |

### Data

[`_TOOL_FLAT_FIELDS`](#nemo_gym-trajectory-trajectory_format-_TOOL_FLAT_FIELDS)

[`_TOOL_V2_FIELDS`](#nemo_gym-trajectory-trajectory_format-_TOOL_V2_FIELDS)

[`_V2_ONLY_GAPS`](#nemo_gym-trajectory-trajectory_format-_V2_ONLY_GAPS)

### API

```python
nemo_gym.trajectory.trajectory_format._legacy_interval_preserved(
    gap: dict[str, typing.Any],
    tools: list[dict[str, typing.Any]]
) -> bool
```

```python
nemo_gym.trajectory.trajectory_format._project_gaps_v1(
    gaps: list[dict[str, typing.Any]],
    tools: list[dict[str, typing.Any]]
) -> list[dict[str, typing.Any]]
```

```python
nemo_gym.trajectory.trajectory_format._restore_native_tool_ids(
    tool_groups: list[list[dict[str, typing.Any]]],
    invocations: list[dict[str, typing.Any]],
    turns: list[dict[str, typing.Any]],
    compactions: list[dict[str, typing.Any]],
    gaps: list[dict[str, typing.Any]],
    model_calls: list[dict[str, typing.Any]]
) -> None
```

Restore v1's native request namespace only with an explicit, collision-free mapping.

Model-call payloads and text are independent evidence and are never rewritten. All
reference values are collected before any edit so chained mappings cannot cascade.

```python
nemo_gym.trajectory.trajectory_format.canonical_tool_record(
    record: dict[str, typing.Any],
    include_join_evidence: bool
) -> dict[str, typing.Any]
```

Keep canonical timing separate from the old flat compatibility projection.

```python
nemo_gym.trajectory.trajectory_format.project_bundle_v1(
    bundle: dict[str, typing.Any],
    restore_native_ids: bool = True
) -> dict[str, typing.Any]
```

Return the unversioned observation envelope accepted by existing readers.

```python
nemo_gym.trajectory.trajectory_format.project_observation_v1(
    record: dict[str, typing.Any]
) -> dict[str, typing.Any]
```

Project only qualified intervals, keeping unknown values unknown.

```python
nemo_gym.trajectory.trajectory_format.project_result_v1(
    trajectory: dict[str, typing.Any],
    bundle: dict[str, typing.Any] | None
) -> tuple[dict[str, typing.Any], dict[str, typing.Any] | None]
```

Export both retained envelopes with one atomic, conservative identity decision.

```python
nemo_gym.trajectory.trajectory_format.project_trajectory_v1(
    trajectory: dict[str, typing.Any],
    restore_native_ids: bool = True
) -> dict[str, typing.Any]
```

Return v1, losing attempt, instance, parent, failure and detailed timing provenance.

This does not establish that v1 consumers can represent retries: consumers that need
those identities must migrate to v2. No endpoints or durations are manufactured.

```python
nemo_gym.trajectory.trajectory_format.reject_v2_fields(
    records: object
) -> None
```

Do not silently discard meaningful v2 evidence mislabeled as a v1 wire record.

```python
nemo_gym.trajectory.trajectory_format.validate_failure_events(
    events: dict[str, dict[str, typing.Any]]
) -> None
```

Validate the shared serialized failure-event map without constructing exceptions.

```python
nemo_gym.trajectory.trajectory_format._TOOL_FLAT_FIELDS = {'started_at', 'completed_at', 'duration_ms', 'timing_source'}
```

```python
nemo_gym.trajectory.trajectory_format._TOOL_V2_FIELDS = {'agent_instance', 'span_id', 'native_tool_call_id', 'parent_span_id', 'model_ca...
```

```python
nemo_gym.trajectory.trajectory_format._V2_ONLY_GAPS = frozenset({'tool_attempt_identity_unavailable', 'tool_agent_instance_unavailable...
```