Branches
Append-only event lines within a session, guarded by optimistic concurrency, with merges that are always explicit and never automatic.
A branch is an append-only line of events inside a session. It is how agent history grows: each turn adds one immutable event to the head of a branch, and the branch advances. Branches let you fork a workflow to explore an alternative without disturbing the line you forked from.
{
"id": "br_01jy...",
"object": "session_branch",
"session_id": "ses_01jy...",
"parent_branch_id": null,
"forked_from_event_id": null,
"head_event_id": "evt_01jy...",
"version": 17
}Append-only with a single causal parent
Events are immutable and form a causal chain. Every event has exactly one parent, except the branch root. You never edit history; you only extend it. This is what makes a branch replayable and auditable: the sequence of events that produced any state is fixed for all time.
Optimistic concurrency
Two writers must not silently clobber each other's appends. So an append is a compare-and-swap: you state what you believe the branch head is, and the write only succeeds if you are right.
POST /v2/sessions/{session_id}/branches/{branch_id}/events{
"expected_version": 17,
"expected_head_event_id": "evt_017",
"event": { "event_type": "user_message", "payload_ref": "art_..." }
}If the branch head moved since you read it, the append is rejected:
409 branch_version_conflictOn a conflict, re-read the branch head, decide whether your event still makes sense in the new context, and retry against the current version. The platform never resolves the conflict for you, because it cannot know your intent.
Creating a branch
Forking is explicit. You name the branch and the exact event you are forking from:
POST /v2/sessions/{session_id}/branches
{
"fork_from_branch_id": "br_main",
"fork_from_event_id": "evt_017",
"label": "alternative-debug-path"
}The new branch shares all history up to the fork point and diverges after it.
Merges are explicit, never automatic
There is no automatic branch merge. An opaque, machine-decided merge would silently rewrite causal history, which the model forbids. Instead you choose how to bring lines back together:
Every merge strategy produces new, explicit events. None of them mutate or delete existing events. History is always additive.
Branches and retries
The optimistic-concurrency discipline is also how retries stay safe. A transport retry reuses an idempotency key so a failed-then-retried append commits once. A provider failover preserves the logical response and adds a new attempt without touching branch history. Assistant output is committed to a branch exactly once. See idempotency and retries for the full retry model.
Sessions
A causal state container for an agent workflow - not a cache entry. How a session anchors bundles, branches, and the events that accumulate over a task.
Snapshots
A compiled, ordered logical state pinned to a branch head - the unit a response binds to, sitting at Layer 1 of the identity model.