Concepts

Event Streams

Ordered run evidence, event families, custom events, sequence behavior, and append semantics.

Every run has an ordered event stream. Events are the chronological spine that connects higher-level records: a ModelCall projection is useful, but the model_call.started and model_call.finished events place that call in time.

Event Shape

Each event has:

FieldMeaning
idDurable event ID.
projectIdOwning project.
runIdOwning run.
seqMonotonic non-negative sequence number inside the run.
typeKnown event type or custom framework event string.
refIdOptional ID of the record the event is about.
parentEventIdOptional parent event for nested or derived events.
occurredAtISO timestamp from the producer.
dataJSON payload.
metadataExtra structured metadata.

Known Event Families

FamilyEventsUse
Run lifecyclerun.started, run.finishedEstablishes the execution boundary.
Model lifecyclemodel_call.started, model_call.finishedCaptures model request/response timing and projection IDs.
Tool lifecycletool.proposed, tool.started, tool.finishedSeparates model intent from runtime execution.
Statecheckpoint.createdMarks a branchable state snapshot.
Artifactsartifact.createdRecords payload creation when useful for trace reading.
Replay and analysisbranch.created, intervention.created, replay.started, replay.paused, replay.finished, analysis.createdLinks counterfactual work back to the baseline.
Fixturesfixture.required, fixture.createdKeeps missing divergent tool outputs explicit.

The schema accepts arbitrary strings, so adapters can emit framework events such as mastra.step.finished, langgraph.node.completed, codex.hook.PreToolUse, or openclaw.llm_input.

Sequence Semantics

The SDK uses async run context to allocate event sequence numbers during a run. The Postgres store validates contiguous batch order, rejects appends after a run is terminal, and enforces uniqueness on (run_id, seq).

Idempotency and conflicts

Retrying the exact same event at the same (runId, seq) is idempotent. Reusing a sequence number with different event content is a conflict, because silently dropping a divergent event would corrupt the trace.

What Belongs In data

Use event data for the concise thing an analyst needs in sequence. Put large payloads in artifacts and reference artifact IDs from the event or projection. A good event payload is:

  • JSON-serializable.
  • Redacted before it leaves the app.
  • Small enough to scan.
  • Linked to a durable projection with refId when possible.
  • Rich enough to understand the transition without fetching every artifact.

On this page