Companion draft, separately versioned. Version: draft 0.1, for ASR format version 0.1 and ATIF v1.8. Not part of core conformance.
ATIF (Agent Trajectory Interchange Format) is a JSON format that stores a whole agent trajectory in a single document, used for evaluation, supervised fine-tuning and reinforcement learning. ASR is the primary record; ATIF is an export target. This companion defines the export so that two exporters produce the same trajectories from the same stream.

Export

One document per path

ATIF steps are linear. An exporter writes one ATIF document per head (see Structure): the steps follow the head’s active path. By default it exports only the primary head; other heads are exported on request, each as a separate document. The active path is used, not the context view: ATIF keeps records that a compaction replaced, “for auditability”, and marks the compaction with a context-management step.

Document fields

Steps

Steps are numbered from 1 in path order. When the parts of one message carry their own author or origin (see Messages), the exporter applies the table to each part’s effective values, and writes consecutive parts with the same source as one step. Messages with status: "withdrawn" are not exported. Tool calls that a program made (requestedBy: "code") are not tool calls of an agent step; the exporter lists them in the extra of the step that holds the enclosing call. Field details:
  • tool_calls[]: tool_call_id = callId, function_name = name, arguments = input (an object), or {"_text": inputText} when the input is text.
  • observation.results[]: source_call_id = callId; content from the result’s content text, or its displayContent when content is absent (noted in extra).
  • timestamp = the first entry’s ts, omitted when absent.
  • metrics: prompt_tokens is all input tokens including cache (ATIF counts cache inside prompt tokens): input.total when includesCache is true; uncached + cacheRead + cacheWrite when all three are known; otherwise omitted. completion_tokens = output.total; cached_tokens = cacheRead; cost_usd = cost.amount when currency is USD. cacheWrite and output.reasoning go in metrics.extra.
  • is_copied_context: true on every step built from copied records (see Lineage). Steps of unknown originality are marked in extra and SHOULD be excluded from training sets.
  • extra["org.agent-session"] on each step: the record IDs it came from.
Opaque reasoning, opaque parts and signatures are never exported. data parts are exported as JSON in the step’s extra. Records with audience: "user" are exported as system steps flagged in extra, or omitted on request.

Metrics

final_metrics comes from the stream’s effective session-scope usage_summary when one exists with known coverage. Otherwise, it comes from the sum of the exported steps’ metrics. The two sources are never combined (ASR-321). Copied records are not counted (ASR-417).

Subagents

When a subagent record announces a child session and the child’s stream is available, the exporter embeds it as a trajectory in subagent_trajectories with its own trajectory_id, and references it from the delegating tool call’s observation result through subagent_trajectory_ref. A child whose stream is not available is referenced by session_id only.

Losses

The export does not carry: branches other than the exported head, file_change, vcs, workspace_state and checkpoint records (except as tool content), permission and input_request records, memory_change and delivery records, hook and terminal records, turn triggers, participants and conversations, state and config_change history, capture states (summarized in extra), redaction records, opaque reasoning and signatures, and timestamps of individual records within a step. An exporter MUST NOT describe an ATIF export as a complete representation of the stream (ASR-617).

Import

An ATIF document imports as one ASR stream:
  • producer.method: "import", producer.source: {"format": "atif", "formatVersion": <schema_version>}.
  • The session key: agent.name mapped through the registry (or a reverse-DNS name supplied by the importer) and session_id as sessionId when present; otherwise the importer cannot form a session key without inventing one and MUST be given one.
  • Steps become a linear sequence of records in step order, with record IDs and message IDs derived from step_id (idSource: derived).
  • tool_call_id becomes callId with callIdSource: native; observation results with source_call_id become tool_result records with linkage: exact.
  • metrics on a step with llm_call_count 1 become an inference with a derived ID. Steps with a higher or absent count put their metrics in a usage_summary with scope: turn and callCount when known.
  • Because ATIF includes cache in prompt_tokens, usage is input.total with includesCache: true, and cacheRead from cached_tokens.
  • is_copied_context cannot become copiedFrom (ATIF does not name the source session). The importer keeps it in _meta and declares the loss copies.
  • subagent_trajectories become separate streams with lineage.spawnedBy (evidence: native_structure).
  • Declared losses typically include timestamps (when steps lack them), branches, file_change and copies.