Session Data

Session Data is what was actually in a conversation, in one shape regardless of which agent produced it. A landed file has the extension .sd. Its first line is a header carrying everything constant for the file. Every line after it is one source record, converted, with its content broken into parts named for what they are: a message, a thought, a call, its result.

The conversion happens once, while the source is read, and never again. A runtime’s vocabulary stops at its adapter. A reader is handed parts, so there is no runtime shape for it to reach into. A dialect that meets something it cannot describe keeps the bytes verbatim in an unknown part rather than guessing or dropping them.

The format is public. Package pkg/sessiondata defines it, and a third-party adapter produces it. The schema is sd/1.

{"h":1,"schema":"sd/1","seq":2,"at":"2026-09-01T12:56:03.1818Z","kind":"transcript",
 "adapter":"claude-code-local/0.1.0","dialect":"claude-code/1",
 "src":"-Users-me-github-skywalking/0438c73b-….jsonl","session":"0438c73b-…","stream":"main"}
Field Meaning
h envelope version, 1
schema sd/1
seq the landed sequence number, monotonic per session
at when the file was collected
kind what it was collected from: transcript, agent_meta, journal, workflow_manifest, workflow_script, provider_body. otlp_log and otlp_span are reserved for a push transport.
adapter how the records were acquired, with its contract version
dialect whose schema they were read as. A push receiver and a local reader for one runtime share a dialect and nothing else.
src the source, relative to the adapter’s root
session, stream, batch the session, the execution stream (main or an agent id), and the group of children a workflow run started

File kinds

One .sd file holds one cut of one source. The header’s kind says which, and the records of each kind carry a characteristic set of fields.

kind Collected from Its records What refers to it
transcript one execution stream: the main stream or a child agent’s own the conversation itself: inputs, calls in fragments, results, injections, resets. stream on the header is main or the agent id. almost every node of a round
agent_meta what the runtime recorded about a child agent when it started it one record, from: runtime, with child and label, and a data part the child’s stream node, for its label
journal a workflow run’s journal one record per event, from: runtime, with child and batch; a child_result flag on the record that returns a child’s value agent.output nodes and ends_with relations
workflow_manifest a workflow run’s manifest one record with batch and label, and a data part the run’s name
workflow_script the program a workflow ran one record whose part is unknown: the source is a program, not data nothing; kept because it is part of the session

Files of every kind are bound by the rounds’ input_digest, so a session travels or archives as all of them. A session’s agent_meta, workflow_manifest and workflow_script records carry no time, so those files have no record time range.

Record

{"ord":12,"off":25086,"sha":"4fed1b624096","bytes":1524,
 "id":"c8b85d73-…","parent":"a5f0a42d-…","call":"msg_011Cdm…",
 "from":"agent","time":"2026-08-06T16:57:22.652Z","flags":["finished"],
 "usage":{"in":2,"out":331,"cache_read":20729,"cache_write":19709},
 "parts":[{"k":"call","id":"toolu_015jKz…","name":"Bash","data":{"command":"make check"},
           "state":"available","bytes":181}]}

Two halves. The record level carries provenance and the identifiers structure is built from, in role names. The part level carries what the content is.

Field Meaning
ord, off, sha, bytes where the record was in the source: line number, byte offset, digest of the source bytes and their size. The bytes themselves are not kept; the digest stays so provenance is provable, and a record that claims a source it did not come from is detectable.
id, parent the record’s own identity and its containment parent
call the provider call this record is a fragment of
run the agent loop it belongs to, one per trigger
continues on a reset boundary only, the record the new context resumes from
tool, child, batch, started_by joins the runtime states outside the content: the call a sidecar answers, the child stream a record names, the group it belongs to, the stream that started this one
label a name the runtime gave something. The only naming evidence in the data.
from who produced it: agent, external, runtime. A record’s type is not what a record is; most records that look like a person are a tool answering.
time, trigger, flags when, what started the loop, and states such as finished
usage what the provider reported: input, output, cache read and cache write tokens. Meaningful only where the call finished.
model the provider model the call ran on, as the runtime named it, on the records of a call. What a token count is reported under. Empty on records landed before it was kept.
parts the content
dropped what the conversion chose to leave out, with its size and the reason

Empty identifiers are common and mean the runtime supplied none. Nothing is inferred to fill them.

Parts

Kind Is Carries
text readable text text
reasoning the model’s own reasoning text when the runtime kept it
call a request to run something id, name, data
result what a call returned of, text or data, failed
media an image or a document media, data
data structure that is not prose: a record the runtime keeps for itself, a manifest data
unknown content the dialect could not describe the raw bytes in data

Every part carries state and bytes. state is one of available, truncated, redacted, omitted or unavailable, and bytes is the size of the original even when the part holds less. A reader is always told how much of the original it has. One tool result in the measured corpus was 1.1 MB, and the share of a session that is tool output ran from 17% to 84%, so a reader is routinely shown part of something and has to know it.

failed is absent, not false, when the runtime said nothing. Most results carry no error flag, and reading that as success would report something the runtime never claimed.

The set of kinds is small because the thing described is small. Measured across a corpus of 3,032 Claude Code files, six content shapes exist and four cover 99.99% of records.

Dropped

"dropped":[{"what":"reasoning signature","bytes":588,"why":"a provider verifies it; a reader cannot read it"}]

dropped exists so a loss is stated rather than silent. It lists only what the dialect understood and chose not to carry. Everything it did not understand travels as an unknown part, so a later version of the dialect can interpret it without collecting again.