> This page is for version 0.2.1.
> 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.atif_export

Strict offline conversion from Gym rollout trajectories to ATIF v1.7.

## Module Contents

### Classes

| Name                                                                    | Description                                                      |
| ----------------------------------------------------------------------- | ---------------------------------------------------------------- |
| [`AtifExportError`](#nemo_gym-trajectory-atif_export-AtifExportError)   | A rollout cannot be represented by Gym's supported ATIF profile. |
| [`AtifExportResult`](#nemo_gym-trajectory-atif_export-AtifExportResult) | -                                                                |
| [`ExportAtifConfig`](#nemo_gym-trajectory-atif_export-ExportAtifConfig) | Settings of `gym eval export atif`.                              |
| [`_AgentGroup`](#nemo_gym-trajectory-atif_export-_AgentGroup)           | -                                                                |
| [`_ModelCallIndex`](#nemo_gym-trajectory-atif_export-_ModelCallIndex)   | -                                                                |

### Functions

| Name                                                                                            | Description                                                                                                  |
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| [`_apply_turns`](#nemo_gym-trajectory-atif_export-_apply_turns)                                 | -                                                                                                            |
| [`_attach_user_observation`](#nemo_gym-trajectory-atif_export-_attach_user_observation)         | The Terminus extension: a user turn after agent output is what that step observed.                           |
| [`_build_groups`](#nemo_gym-trajectory-atif_export-_build_groups)                               | -                                                                                                            |
| [`_canonical_conversation_copy`](#nemo_gym-trajectory-atif_export-_canonical_conversation_copy) | Validate a redundant turn copy and compare its normalized supported fields.                                  |
| [`_encoded_trajectory`](#nemo_gym-trajectory-atif_export-_encoded_trajectory)                   | -                                                                                                            |
| [`_final_metrics`](#nemo_gym-trajectory-atif_export-_final_metrics)                             | -                                                                                                            |
| [`_index`](#nemo_gym-trajectory-atif_export-_index)                                             | -                                                                                                            |
| [`_json_value`](#nemo_gym-trajectory-atif_export-_json_value)                                   | -                                                                                                            |
| [`_live_arguments`](#nemo_gym-trajectory-atif_export-_live_arguments)                           | The live profile's tool arguments: a string that is not a JSON object becomes `&#123;&#125;`, kept verbatim. |
| [`_live_reasoning_text`](#nemo_gym-trajectory-atif_export-_live_reasoning_text)                 | The live profile's reading of a step's reasoning items: lossy where a model is, never failing on it.         |
| [`_message_content`](#nemo_gym-trajectory-atif_export-_message_content)                         | -                                                                                                            |
| [`_model_call_index`](#nemo_gym-trajectory-atif_export-_model_call_index)                       | -                                                                                                            |
| [`_parse_arguments`](#nemo_gym-trajectory-atif_export-_parse_arguments)                         | -                                                                                                            |
| [`_path_error`](#nemo_gym-trajectory-atif_export-_path_error)                                   | -                                                                                                            |
| [`_preflight_conversation`](#nemo_gym-trajectory-atif_export-_preflight_conversation)           | Reject raw fields that supported Pydantic variants would silently erase.                                     |
| [`_preflight_model_call_refs`](#nemo_gym-trajectory-atif_export-_preflight_model_call_refs)     | -                                                                                                            |
| [`_preflight_model_ref`](#nemo_gym-trajectory-atif_export-_preflight_model_ref)                 | -                                                                                                            |
| [`_preflight_parts`](#nemo_gym-trajectory-atif_export-_preflight_parts)                         | -                                                                                                            |
| [`_preflight_raw_trajectory`](#nemo_gym-trajectory-atif_export-_preflight_raw_trajectory)       | -                                                                                                            |
| [`_preflight_training_metadata`](#nemo_gym-trajectory-atif_export-_preflight_training_metadata) | -                                                                                                            |
| [`_reasoning_text`](#nemo_gym-trajectory-atif_export-_reasoning_text)                           | -                                                                                                            |
| [`_reject_unknown_fields`](#nemo_gym-trajectory-atif_export-_reject_unknown_fields)             | -                                                                                                            |
| [`_resolve_model_call`](#nemo_gym-trajectory-atif_export-_resolve_model_call)                   | -                                                                                                            |
| [`_source_item_ids`](#nemo_gym-trajectory-atif_export-_source_item_ids)                         | Return provider item identities that ATIF has no standard fields for.                                        |
| [`_text_content`](#nemo_gym-trajectory-atif_export-_text_content)                               | -                                                                                                            |
| [`_tool_record_extra`](#nemo_gym-trajectory-atif_export-_tool_record_extra)                     | -                                                                                                            |
| [`_transcript_items`](#nemo_gym-trajectory-atif_export-_transcript_items)                       | -                                                                                                            |
| [`_transcript_text`](#nemo_gym-trajectory-atif_export-_transcript_text)                         | Text content of a message or tool output; images and other parts are not representable.                      |
| [`_validate_json_value`](#nemo_gym-trajectory-atif_export-_validate_json_value)                 | Reject Python values that cannot round-trip through UTF-8 JSON unchanged.                                    |
| [`encode_atif_trajectory`](#nemo_gym-trajectory-atif_export-encode_atif_trajectory)             | The trajectory as the UTF-8 JSON bytes Harbor reads from `trajectory.json`.                                  |
| [`export_rollouts_to_atif`](#nemo_gym-trajectory-atif_export-export_rollouts_to_atif)           | Validate a rollout JSONL completely, then atomically publish ATIF files and a manifest.                      |
| [`gym_rollout_to_atif`](#nemo_gym-trajectory-atif_export-gym_rollout_to_atif)                   | Convert one rollout row, rejecting any structure Gym cannot represent completely.                            |
| [`transcript_to_atif`](#nemo_gym-trajectory-atif_export-transcript_to_atif)                     | Convert a live Responses API transcript into an ATIF v1.7 trajectory.                                        |

### Data

[`TRANSCRIPT_EXPORT_PROFILE`](#nemo_gym-trajectory-atif_export-TRANSCRIPT_EXPORT_PROFILE)

[`_CONVERSATION_ADAPTER`](#nemo_gym-trajectory-atif_export-_CONVERSATION_ADAPTER)

[`_KNOWN_INCOMPLETE_FINISH_REASONS`](#nemo_gym-trajectory-atif_export-_KNOWN_INCOMPLETE_FINISH_REASONS)

[`_TEXT_PART_TYPES`](#nemo_gym-trajectory-atif_export-_TEXT_PART_TYPES)

[`_TRAINING_METADATA_FIELDS`](#nemo_gym-trajectory-atif_export-_TRAINING_METADATA_FIELDS)

### API

```python
class nemo_gym.trajectory.atif_export.AtifExportError()
```

**Bases:** [ConfigError](/nemo/gym/nemo-gym/nemo_gym/config/config_types#nemo_gym-config-config_types-ConfigError)

A rollout cannot be represented by Gym's supported ATIF profile.

```python
class nemo_gym.trajectory.atif_export.AtifExportResult(
    output_dirpath: pathlib.Path,
    trajectory_count: int,
    manifest_fpath: pathlib.Path
)
```

Dataclass

**`manifest_fpath`** `Path`

---

**`output_dirpath`** `Path`

---

**`trajectory_count`** `int`

---

```python
class nemo_gym.trajectory.atif_export.ExportAtifConfig()
```

**Bases:** [RunExportConfig](/nemo/gym/nemo-gym/nemo_gym/config/config_types#nemo_gym-config-config_types-RunExportConfig)

Settings of `gym eval export atif`.

**`agent_version`** `str = Field(min_length=1)`

---

**`format`** `Literal['atif'] = 'atif'`

---

**`output_dirpath`** `Path`

---

**`session_id`** `str = Field(min_length=1)`

---

```python
nemo_gym.trajectory.atif_export.ExportAtifConfig.reject_blank_identity(
    value: str
) -> str
```

classmethod

```python
class nemo_gym.trajectory.atif_export._AgentGroup(
    question: list[typing.Any],
    reasoning: list[typing.Any],
    answer: list[typing.Any],
    step: nemo_gym.trajectory.atif_v1_7.AtifStep
)
```

Dataclass

**`answer`** `list[Any]`

---

**`question`** `list[Any]`

---

**`reasoning`** `list[Any]`

---

**`step`** `AtifStep`

---

```python
class nemo_gym.trajectory.atif_export._ModelCallIndex(
    calls: list[nemo_gym.trajectory.trajectory_record.TrajectoryModelCall],
    by_id: dict[str, list[int]],
    by_response: dict[tuple[str, str, str], list[int]]
)
```

Dataclass

**`by_id`** `dict[str, list[int]]`

---

**`by_response`** `dict[tuple[str, str, str], list[int]]`

---

**`calls`** `list[TrajectoryModelCall]`

---

```python
nemo_gym.trajectory.atif_export._apply_turns(
    trajectory: nemo_gym.trajectory.trajectory_record.TrajectoryRecord,
    groups: list[nemo_gym.trajectory.atif_export._AgentGroup]
) -> set[int]
```

```python
nemo_gym.trajectory.atif_export._attach_user_observation(
    step: nemo_gym.trajectory.atif_v1_7.AtifStep,
    item: typing.Any,
    path: str
) -> None
```

The Terminus extension: a user turn after agent output is what that step observed.

```python
nemo_gym.trajectory.atif_export._build_groups(
    trajectory: nemo_gym.trajectory.trajectory_record.TrajectoryRecord,
    invocation: typing.Any
) -> tuple[list[nemo_gym.trajectory.atif_v1_7.AtifStep], list[nemo_gym.trajectory.atif_export._AgentGroup]]
```

```python
nemo_gym.trajectory.atif_export._canonical_conversation_copy(
    value: typing.Any,
    path: str
) -> typing.Any
```

Validate a redundant turn copy and compare its normalized supported fields.

```python
nemo_gym.trajectory.atif_export._encoded_trajectory(
    trajectory: nemo_gym.trajectory.atif_v1_7.AtifTrajectoryV1_7
) -> bytes
```

```python
nemo_gym.trajectory.atif_export._final_metrics(
    groups: list[nemo_gym.trajectory.atif_export._AgentGroup],
    total_steps: int
) -> nemo_gym.trajectory.atif_v1_7.AtifFinalMetrics
```

```python
nemo_gym.trajectory.atif_export._index(
    row: dict[str, typing.Any],
    key: str,
    path: str
) -> int
```

```python
nemo_gym.trajectory.atif_export._json_value(
    value: typing.Any
) -> typing.Any
```

```python
nemo_gym.trajectory.atif_export._live_arguments(
    call: nemo_gym.core.responses_api_types.NeMoGymResponseFunctionToolCall,
    reasons: set[str]
) -> tuple[dict[str, typing.Any], dict[str, typing.Any] | None]
```

The live profile's tool arguments: a string that is not a JSON object becomes `{}`, kept verbatim.

A harness that survives a malformed call (it hands the model a tool error and goes on) produced a
gradable episode; the original string travels in the call's `extra` and the trajectory is partial.

```python
nemo_gym.trajectory.atif_export._live_reasoning_text(
    items: list[nemo_gym.core.responses_api_types.NeMoGymResponseReasoningItem],
    path: str,
    reasons: set[str]
) -> str | None
```

The live profile's reading of a step's reasoning items: lossy where a model is, never failing on it.

Empty and encrypted reasoning (OpenAI reasoning models answer with `summary: []` unless a summary
is requested) export without `reasoning_content`; several segments, from several items or one
item's summary list (one `<think>` block each), join with newlines. Each departure from the strict
mapping is named in `reasons`, so the trajectory says it is partial. Only a segment without text
(a converter defect) still raises.

```python
nemo_gym.trajectory.atif_export._message_content(
    item: typing.Any,
    path: str
) -> nemo_gym.trajectory.atif_v1_7.AtifContent
```

```python
nemo_gym.trajectory.atif_export._model_call_index(
    calls: list[nemo_gym.trajectory.trajectory_record.TrajectoryModelCall]
) -> nemo_gym.trajectory.atif_export._ModelCallIndex
```

```python
nemo_gym.trajectory.atif_export._parse_arguments(
    call: nemo_gym.core.responses_api_types.NeMoGymResponseFunctionToolCall,
    path: str
) -> dict[str, typing.Any]
```

```python
nemo_gym.trajectory.atif_export._path_error(
    path: str,
    detail: str
) -> nemo_gym.trajectory.atif_export.AtifExportError
```

```python
nemo_gym.trajectory.atif_export._preflight_conversation(
    conversation: typing.Any,
    path: str
) -> None
```

Reject raw fields that supported Pydantic variants would silently erase.

```python
nemo_gym.trajectory.atif_export._preflight_model_call_refs(
    value: typing.Any,
    path: str
) -> None
```

```python
nemo_gym.trajectory.atif_export._preflight_model_ref(
    value: typing.Any,
    path: str
) -> None
```

```python
nemo_gym.trajectory.atif_export._preflight_parts(
    value: typing.Any,
    path: str,
    supported_fields: dict[str, frozenset[str]]
) -> None
```

```python
nemo_gym.trajectory.atif_export._preflight_raw_trajectory(
    value: typing.Any
) -> None
```

```python
nemo_gym.trajectory.atif_export._preflight_training_metadata(
    item: dict[typing.Any, typing.Any],
    path: str
) -> None
```

```python
nemo_gym.trajectory.atif_export._reasoning_text(
    items: list[nemo_gym.core.responses_api_types.NeMoGymResponseReasoningItem],
    path: str
) -> str | None
```

```python
nemo_gym.trajectory.atif_export._reject_unknown_fields(
    value: dict[typing.Any, typing.Any],
    allowed: set[str] | frozenset[str],
    path: str
) -> None
```

```python
nemo_gym.trajectory.atif_export._resolve_model_call(
    ref: nemo_gym.trajectory.trajectory_record.ModelCallRef,
    calls: nemo_gym.trajectory.atif_export._ModelCallIndex,
    path: str
) -> tuple[int, nemo_gym.trajectory.trajectory_record.TrajectoryModelCall]
```

```python
nemo_gym.trajectory.atif_export._source_item_ids(
    group: nemo_gym.trajectory.atif_export._AgentGroup
) -> dict[str, typing.Any]
```

Return provider item identities that ATIF has no standard fields for.

```python
nemo_gym.trajectory.atif_export._text_content(
    value: typing.Any,
    path: str
) -> nemo_gym.trajectory.atif_v1_7.AtifContent
```

```python
nemo_gym.trajectory.atif_export._tool_record_extra(
    record: typing.Any,
    source_item_id: str | None = None
) -> dict[str, typing.Any] | None
```

```python
nemo_gym.trajectory.atif_export._transcript_items(
    items: typing.Any,
    path: str
) -> list[typing.Any]
```

```python
nemo_gym.trajectory.atif_export._transcript_text(
    value: typing.Any,
    path: str,
    reasons: set[str] | None = None
) -> nemo_gym.trajectory.atif_v1_7.AtifContent
```

Text content of a message or tool output; images and other parts are not representable.

With `reasons` (the model's own output), a `refusal` part exports as its text and is noted there:
the model refused, the harness went on, and the episode is still graded, as Harbor grades a refused
Terminus turn (Harbor keeps an empty step; the text is kept here). Without it, a refusal is rejected
like any other non-text part.

```python
nemo_gym.trajectory.atif_export._validate_json_value(
    value: typing.Any,
    path: str
) -> None
```

Reject Python values that cannot round-trip through UTF-8 JSON unchanged.

```python
nemo_gym.trajectory.atif_export.encode_atif_trajectory(
    trajectory: nemo_gym.trajectory.atif_v1_7.AtifTrajectoryV1_7
) -> bytes
```

The trajectory as the UTF-8 JSON bytes Harbor reads from `trajectory.json`.

```python
nemo_gym.trajectory.atif_export.export_rollouts_to_atif(
    config: nemo_gym.trajectory.atif_export.ExportAtifConfig
) -> nemo_gym.trajectory.atif_export.AtifExportResult
```

Validate a rollout JSONL completely, then atomically publish ATIF files and a manifest.

```python
nemo_gym.trajectory.atif_export.gym_rollout_to_atif(
    rollout: dict[str, typing.Any],
    session_id: str,
    agent_version: str
) -> nemo_gym.trajectory.atif_v1_7.AtifTrajectoryV1_7
```

Convert one rollout row, rejecting any structure Gym cannot represent completely.

```python
nemo_gym.trajectory.atif_export.transcript_to_atif(
    input_items: typing.Any,
    output_items: typing.Any,
    session_id: str,
    agent_name: str,
    agent_version: str,
    model_name: str | None = None,
    usage: collections.abc.Mapping[str, typing.Any] | None = None
) -> nemo_gym.trajectory.atif_v1_7.AtifTrajectoryV1_7
```

Convert a live Responses API transcript into an ATIF v1.7 trajectory.

`input_items` is the task's `responses_create_params.input` (a string or item list) and
`output_items` the agent's `response.output`. Shapes a model causes (reasoning without an answer
when it ran out of tokens, several reasoning segments, empty or encrypted reasoning, arguments that are
not a JSON object) export with the departure named under `extra.nemo_gym.conversion` (`status:
partial`, `reasons`); raises `AtifExportError` only for what the mapping cannot represent at
all (a copied assistant turn, a later system turn, a result for no call or a second
`function_call_output` for the same `call_id`, item types ATIF has no place for).

```python
nemo_gym.trajectory.atif_export.TRANSCRIPT_EXPORT_PROFILE = 'ng-transcript-to-atif-v1'
```

```python
nemo_gym.trajectory.atif_export._CONVERSATION_ADAPTER = TypeAdapter(list[NeMoGymResponseInputItem])
```

```python
nemo_gym.trajectory.atif_export._KNOWN_INCOMPLETE_FINISH_REASONS = frozenset({'aborted', 'canceled', 'cancelled', 'content_filter', 'failed', 'inco...
```

```python
nemo_gym.trajectory.atif_export._TEXT_PART_TYPES = frozenset({'input_text', 'output_text', 'text'})
```

```python
nemo_gym.trajectory.atif_export._TRAINING_METADATA_FIELDS = frozenset({'prompt_token_ids', 'generation_token_ids', 'generation_log_probs', '...
```