Session Model
Sessions, runs, turns, lineage, and identity
Layers
L0 raw blob content-addressed native bytes (import = snapshot)
L1 canonical log unified envelope, append-only, single durable source of truth
L2 projections read models, always rebuildable from the logHierarchy
Session ──1:N──> Run ──1:N──> Turn ──1:N──> Message ──> ordered ContentBlocks
└──> ToolCall / ToolResult- Session — one conversation:
nativeSessionId(harness-native) +id(content-addressed canonical id). - Run — an execution unit (harnesses delimit run/turn differently).
- Turn — one user input → agent output.
- Message —
role ∈ {system, user, assistant, tool, unknown}+ ordered blocks. - Tool —
tool-call+tool-resultpairing; the result lives on the tool entity, decoupled from message block shape.
Lineage DAG
Sessions are not a flat table:
relation { id, sourceSessionId, targetSessionId, type, typeData, createdAt }
type ∈ { fork, resume, handoff, subagent, compact }handoff creates a new session + relation — it never masquerades as the same session, so provenance stays honest.
Identity & idempotency
- Event ids are content-addressed → re-import is idempotent.
- Session canonical id =
sha256(harness ‖ native_session_id ‖ source_sha256)(length-prefixed, cross-harness collision-safe). - Event ids are globally idempotent; replays deduplicate by
eventId.
Full detail: asp/spec/overview.md and schema/agent-session-contracts.ts.