ASR-NNN), and each one maps to a validator check.
Readers
- Check the version. Read
formatVersionfrom the header. Declare which major versions you support and fail explicitly on the others. - Tolerate damage. Ignore a partially written final line. A malformed line in the middle yields a diagnostic and a gap; never silently reconnect the context around it.
- Order by
seq. Timestamps are optional, may have different precisions and may come from different clocks. - Preserve what you don’t understand. Skip unknown record types and fields when interpreting, but keep them when storing or rewriting. Every enum is open.
- Resolve references carefully. A reference to an entity, such as a
callIdormessageId, means its latest revision; a reference to a recordidmeans exactly that revision. Asupersedesrecord is a full replacement. - Pair tool calls as recorded. Duplicate native call IDs are never paired by order. A call without a result is dangling and its outcome is unknown. Orphan results, which have no matching call, are kept.
- Don’t double-count. Records copied from an ancestor session can be searched and displayed, but their usage, cost, edits and commits are not attributed to the child session. The same applies when one app runs another agent: the app’s stream links to the backing session with
executedBy, and its copies of that session’s records carrycopiedFrom. Use either ausage_summarythat covers the records being counted or the component records, never both. Never add parent and child totals when their scope is unknown. - Treat absence as unknown. A missing cost does not mean zero cost; missing lineage information does not mean the session is a root session; a missing
triggerdoes not mean a person started the turn. - Find features by record type. Questions to the user are
input_requestrecords, delegation issubagentand plans areplan, whatever the tool was called. Don’t rely on a tool call’s name orkindto find them. - Don’t assume delivery. An assistant
messagemeans a reply was generated. Whether it reached anyone is adeliveryrecord; without one, delivery is unknown. - Read senders from the record.
fromnames who sent a message: a participant in a group chat, another session or an agent’s address.author: "human"says only that a person wrote it, not which person. - Compute the context view as specified. Follow predecessors back from a head, then apply rewinds and compactions in
seqorder. The result is a projection of the recorded evidence, not proof of what the model actually received. See Order, branches and context. - Display safely. Treat transcript content as untrusted input. Never execute it, fetch URIs automatically, or render it as active HTML.
Converters
- Set
producer.methodtoconverterand list every feature you could not carry over inproducer.lossy. - Keep native IDs verbatim. Where the source has none, derive deterministic IDs and mark them
idSource: "derived". For sources rewritten as whole snapshots, mark positional IDsidScope: "capture". Never use paths, import time or content hashes as identity inputs. - Never fabricate IDs, timestamps, models, outcomes, durations, costs or token counts. Keep text exactly.
- Fold incremental updates during streaming into one record and mark its
assembly. When the source keeps a revision of an already-final fact, such as a tool status that changed, keep it as asupersedeschain, or declare folding it as a loss. - Write
inferencerecords only when the source identifies a model call. - Put facts that have no standard field where the agent registry says: a
_metakey on the nearest record, or a vendor record type. Never drop a recorded fact to stay conformant. - Never record secret answers to questions, whether normalized, raw or in a blob.
- Record lineage and copies only from positive evidence, with the evidence kind stated per facet.
- Use capture states for truncated, masked, summarized or omitted content. A copy limited to part of the source is never labeled complete.
- On re-export, never renumber records that were already exported.
- Keep the source record in
native(embedded or referenced) when you can.
Exporters
Companion specifications define the derived formats:- ATIF: one trajectory document per root-to-leaf path.
- OpenTelemetry GenAI: spans only where timing exists.
- Attribution: Agent Trace records and Git AI notes, derived from
file_changeandvcsrecords. - GitHub UAS import and export, and Entire import.
derivedFrom and covers reachable blobs, native sidecars, unknown extensions, identifiers and embedded paths. When redaction and preservation conflict, redaction wins. See Privacy and security.
Storage tools
- Store bundles as a directory or archive with an authoritative
bundle.jsonmanifest,sessions/,blobs/sha256/<hex>and, optionally,native/. - Never include
native/files in a shareable bundle by default. - Keep streams of unsupported major versions as opaque bytes.
- Extract archives safely and set limits when parsing. Never run discovery commands automatically.
Validator and corpus
The reference validator checks syntax, semantics and unsupported features separately, against the JSON Schemas. It ships with conformance fixtures: every semantic requirement has at least one valid and one invalid case. The JSON Schemas (draft 2020-12) are published here:agent-session.schema.json: every record type.bundle-manifest.schema.json: the bundle manifest.discovery.schema.json: the discovery file from the integration companion.