postrundocs Back to siteGet early accessAccess
Browse docsEvent schema v1.2

Event schema v1.2

Every agent's activity is normalized into the same v1.2 records, so sessions from different agents read and export the same way. The step is the one atom: a single command, edit, read, message or other tool call. Turns group steps, segments group turns across a resume, and a session holds them all. This page lists every field, as checked by the runtime validator that POST /api/ingest uses.

Validation rules

These apply to every record below:

  • Required fields must be present with the right type.
  • Optional fields may be left out, but not set to null. JSON null is an error.
  • Unknown fields are rejected on every modelled object, so typos and stale fields fail instead of being stored. The two deliberately open shapes, OtherPayload.raw and EditPayload.structured_patch, are not inspected.
  • Timestamps are ISO 8601 date-times with a timezone (Z or +hh:mm), with optional fractional seconds. 2026-10-05T22:00:00Z passes; 2026-10-05 22:00 does not.
  • Integers must be whole numbers. Where noted, they must be 0 or more.
  • Closed enums accept only the listed values. Open enums list common values but accept any non-empty string, so an agent can record a value Postrun has not mapped yet.
EnumKindValues
Step typeclosedcommand, edit, read, message, other
content_statusclosedinline, reference_only
Flag severityclosedinfo, warn, danger
decisionopenaccepted, rejected, auto, n/a
outcomeopenok, failed
Flag kindopendangerous_command, dead_end_edit, rejected, failed, secret_in_output
Actor typeopenroot, subagent
agent.kindopenclaude-code, cline

Session

A session is one run of one agent against one working directory. When you push through the ingest API, you send the session header:

FieldTypeRequiredNotes
idstringyesPostrun's id for the session, mapped from the agent's own id.
agent.kindstringyesOpen enum. Shown as a badge and used as the filter.
agent.versionstringyesThe agent's version.
agent.format_versionstringnoThe agent's storage format version, where it has one.
workspace.rootstringyesThe working directory.
workspace.repostringnoA repository identifier.
started_attimestampyes
ended_attimestampnoUnset while the session is open.
sourcestringnoWhere the session came from. Pushed sessions default to push:<agent kind>.
metrics.cost_usdnumber, 0 or morewith metricsCumulative API cost the agent reported.
metrics.api_requestsinteger, 0 or morewith metrics
metrics.tokens.input, .output, .cache_read, .cache_creationinteger, 0 or morewith metrics

metrics is stored as reported, not calculated, because API request events are session-level telemetry and not steps. The store also keeps owner_id (always local for now) and captured_on (this machine's hostname) for each session, and an optional review verdict with a state (reviewed, approved, needs_attention or any string), a note and a reviewer.

These are calculated when a session is read, never stored: step counts by type, failed and reference-only counts, flag count, turn count, and the title (the first user prompt).

Segment

A segment is a contiguous run within a session. Most sessions have one. A session that is resumed after it ended gets another, so the timeline can show where it resumed.

FieldTypeRequiredNotes
indexinteger, 0 or moreyesUnique within the session. Segments are upserted by index.
start_reasonstringyesFor example start, resume or clear.
started_attimestampyes
ended_attimestampno
source_filesstring arrayyesCapture files this segment came from. Can be empty.

Actor

An actor is the entity within a session that took a step: the main agent, or a subagent it started.

FieldTypeRequiredNotes
idstringyes
parent_idstringnoLeave out for the root actor. Must name an actor in the session.
typestringyesOpen enum: root, subagent.
labelstringno

Turn

A turn starts with a user prompt and holds everything the agent did in response.

FieldTypeRequiredNotes
idstringyes
session_idstringyesMust equal the session id.
segment_indexinteger, 0 or moreyesMust name a segment in the session.
actor_idstringyesMust name an actor in the session.
indexinteger, 0 or moreyesThe turn's position. Postrun's adapters number turns from 1.
prompt_idstringnoThe agent's prompt id, where it has one.
modestringnoThe agent's own mode string, such as Cline's plan or act. Not normalized.
started_attimestampyes
step_idsstring arrayyesAccepted but ignored on ingest. The store builds it from the steps, in seq order.

Step

Every step has these fields, plus a type and a matching payload.

FieldTypeRequiredNotes
idstringyes
session_idstringyesMust equal the session id.
segment_indexinteger, 0 or moreyes
turn_idstringyesMust name a turn in the session.
actor_idstringyesMust name an actor in the session.
seqinteger, 0 or moreyesOrder within the session. Unique per session.
attimestampyes
typestringyesClosed enum. Selects the payload shape.
decisionstringyesOpen enum. The permission decision: accepted, rejected, auto, or n/a for steps that are not tool calls.
outcomestringyesOpen enum. The execution result: ok or failed.
content_statusstringyesClosed enum: inline or reference_only.
errorobjectnoWhy the step failed, when the agent reported a reason.
channelsstring arrayyesWhich capture channels evidenced this step, such as hook or otel. Can be empty.
flagsFlag arrayyesCan be empty.
payloadobjectyesShape depends on type.

decision and outcome

These are two fields because one status could not say "accepted, then failed". decision records whether the call was allowed (by you, by configuration, or rejected). outcome records what happened when it ran. A step can be accepted and failed at once.

content_status

inline means the payload holds the content. reference_only means the content was not available on any readable channel: the content fields are left out, and a pointer goes in output_ref (commands) or text_ref (messages). This keeps a missing value from looking like a real empty one. The review app marks these steps as reference-only.

error

FieldTypeRequiredNotes
typestringyesNon-empty. The agent's error type, for example Error:EISDIR or cline_tool_error.
messagestringyesCan be empty.

Flag

FieldTypeRequiredNotes
kindstringyesOpen enum.
severitystringyesClosed enum: info, warn, danger.
reasonstringyes

Payloads

command

A shell command. Every field is optional.

FieldTypeNotes
commandstringLeft out when the step is reference-only.
stdoutstring
stderrstring
exit_codeintegerOften present only on failure.
cwdstring
output_refstringPointer to the output when it is not inline.

edit

A file write or edit.

FieldTypeRequiredNotes
pathstringyesNon-empty.
old_stringstringno
new_stringstringno
structured_patchanynoThe agent's own structured diff, stored as is. Not validated.
is_full_writebooleanyestrue when the whole file was written or created.
landed_in_final_statebooleannoA projection: false marks an edit that did not survive. Adapters do not set it.

read

A file read.

FieldTypeRequiredNotes
pathstringyesNon-empty.
range[start_line, end_line]noExactly two integers.

message

A prompt or reply.

FieldTypeRequiredNotes
rolestringyesNon-empty. Usually user or assistant. The Cline adapter also uses thinking.
textstringno
text_refstringnoPointer to the text when it is not inline.

other

Any tool call without its own type.

FieldTypeRequiredNotes
tool_namestringyesNon-empty.
rawobjectyesThe tool's input and result as an object. Contents are not validated.

Example step

{
  "id": "step-1",
  "session_id": "demo-0001",
  "segment_index": 0,
  "turn_id": "turn-1",
  "actor_id": "root",
  "seq": 1,
  "at": "2026-10-05T22:00:04.250Z",
  "type": "command",
  "decision": "auto",
  "outcome": "failed",
  "content_status": "inline",
  "error": { "type": "exit_code", "message": "Exit code 1" },
  "channels": ["push"],
  "flags": [],
  "payload": { "command": "npm test", "stdout": "1 failing", "exit_code": 1, "cwd": "/home/me/project" }
}

Error paths

Validation errors name the field with a path into the request body, such as steps[3].payload.exit_code or turns[0].started_at, and a message such as required, unknown field, must be omitted, not null or expected ISO 8601 date-time with timezone. See the ingest API for the response shape.

Found something wrong? These docs live in apps/docs of the postrun repo. Privacy · Security