Agent Trajectory Interchange Format (ATIF)
Agent Trajectory Interchange Format (ATIF)
Use the atif section when you want one Agent Trajectory Interchange Format
(ATIF) trajectory artifact per top-level Agent scope or supported coding-agent
turn scope.
The plugin-managed ATIF dispatcher creates a scope-local exporter for each
top-level Agent scope and each root-child custom scope marked
nemo_relay_scope_role = "turn". It writes the trajectory when that root scope
ends. Nested Agent scopes remain in the parent trajectory.
plugins.toml Example
Add the following ATIF exporter configuration to plugins.toml:
This configuration writes a trajectory file such as
logs/trajectory-<scope-uuid>.json for each top-level Agent scope or supported
coding-agent turn scope.
Fields
The following table describes the top-level ATIF settings:
Remote Storage
Use storage when local trace files are not durable across sessions, such as in
sandboxed runtimes. When storage is non-empty, Relay uploads each completed
trajectory to every configured backend instead of writing a local file.
output_directory is ignored.
Each storage entry is tagged with a type discriminator so additional
backends can be added without breaking existing configs. S3-compatible object
storage and HTTP endpoints are supported.
S3-Compatible Storage
Configure an S3-compatible destination as follows:
HTTP Endpoint Storage
Configure an HTTP destination as follows:
The HTTP backend sends one POST per completed trajectory. The request body is
the rendered ATIF JSON file with content-type: application/json. NeMo Relay
also sets x-nemo-relay-atif-filename and
x-nemo-relay-atif-session-id headers so receivers can keep the same object
identity that local files and S3 uploads use.
HTTP 2xx responses are treated as success. Any non-2xx response or
transport error records the endpoint as unhealthy and skips it for later
trajectories. Other configured destinations continue to receive writes.
The following table describes HTTP storage settings:
Multiple Destinations
Add another [[components.config.atif.storage]] table to send each trajectory
to every configured destination. For example, this configuration uses an
in-cluster MinIO target and a remote HTTP endpoint:
Connection Fields
By default, Relay reads credentials, region, and endpoint URL from standard AWS environment variables. You can also set non-secret connection fields directly in the configuration. This lets one file describe multiple S3-compatible destinations, such as an in-cluster MinIO target and a remote AWS target:
The following table describes S3-compatible connection settings:
Explicit fields take precedence; anything left unset falls back to the matching
AWS_* environment variable.
Secret Credential Fields
Secret values stay out of checked-in config files. Each secret field carries a
_var suffix and holds the name of an environment variable that contains the
secret value. The plugin validates the name during initialization:
The following table describes secret credential settings:
Relay uploads each trajectory under {key_prefix}{rendered_filename}. It
renders filename_template the same way it does for local files, so a
local→remote transition keeps object names stable. Relay adds a trailing / to
key_prefix when one is missing.
If an upload fails for a destination, the ATIF exporter records that destination as unhealthy and skips it for later trajectories. Other destinations continue to receive writes. The exporter reports fatal dispatcher failures, such as trajectory serialization failures, during plugin teardown. It isolates per-destination sink failures to the failed sink.
Expected Output
The exporter translates NeMo Relay lifecycle events into ATIF v1.7 trajectory
data. LLM start and end events become model steps, tool events become tool
calls and observations, and scope nesting contributes lineage metadata.
Nested agent scopes are embedded in the parent file as subagent_trajectories
and referenced from parent observation results with
subagent_trajectory_ref.trajectory_id. The reference points to the embedded
child trajectory by ID so consumers can validate the parent and child as one
single-file ATIF v1.7 artifact.
The plugin writes each trajectory when its top-level Agent scope or supported coding-agent turn scope closes. If the plugin is cleared while that root scope is still open, teardown flushes the partial trajectory.
To correlate ATIF with OpenTelemetry or OpenInference traces from the same run,
join on NeMo Relay UUIDs. The plugin-managed ATIF session_id is the
top-level trajectory root scope UUID. Each step’s extra.ancestry.function_id is the event UUID,
and extra.ancestry.parent_id is the parent event UUID. Trace spans expose the
same values as nemo_relay.uuid and nemo_relay.parent_uuid attributes.
When present, a step’s metrics can carry prompt_tokens, completion_tokens,
cached_tokens (cache read + write), and cost_usd (USD only); the trajectory
final_metrics sums the metrics present on its steps as total_*. Refer to
Token and Cost Field Semantics
for the full mapping, including how ATIF sources these values from the codec
annotation and the raw payload.
ATIF is a trajectory projection over NeMo Relay events. It should preserve the meaning of scope parentage, event UUIDs, codec annotations, and exporter-local lineage rules without becoming the source of truth for runtime ownership, middleware ordering, or provider payload decoding.
Plugin Configuration
Use plugin configuration when the application should let NeMo Relay own the ATIF dispatcher lifecycle. The following examples configure and activate the ATIF exporter through each supported language binding.
validate() checks only the supplied in-memory object. initialize() also
layers discovered plugins.toml configuration. For effective file-backed
validation, refer to Plugin Configuration Files
and run the gateway with the same configuration path that production uses.
Python
Node.js
Rust
Manual API
Use the manual AtifExporter API when you need explicit collection boundaries
or one exporter object per run.
Python
Node.js
Rust
Common Configuration and Runtime Issues
filename_templatedoes not contain{session_id}.- The output directory is not writable at runtime.
- Tool definitions or
extrametadata are not JSON-compatible. - The application never opens a top-level Agent scope or a supported coding-agent turn scope, so no trajectory file is created.
storage[i].typeis unknown orstorage[i].bucketis empty for some entry.storageis non-empty in a build that was compiled without theatif-storagefeature.