Sessions and runs
Distinguish a persistent work surface from one execution and its lifecycle.
A session is the durable conversation or execution record. A turn is one admitted input. A run is the active model-and-tool execution for that turn.
The distinction matters because continuity, queueing, and execution do not have the same lifetime.
Sessions keep continuity
The session holds its project link, title, model defaults, messages, event history, uploads, output references, unread state, and aggregate usage. A sandbox id is attached after a run provisions an execution environment.
Session shape depends on the work mode:
- a chat reuses one session across its conversation;
- an agent has exactly one lifetime session that compacts older context rather than ending, and its title follows the agent name;
- every automation occurrence gets a new session;
- every dashboard build or refresh gets a new session;
- a sub-agent runs in its own child session linked to the parent.
Runs have a lifecycle
Sending a message first creates a durable queued-turn event. If the session lane is free, d5s dispatches it; otherwise it records a queue position. A queued turn can be cancelled before dispatch.
While active, the run streams events such as sandbox readiness, tool calls and results, reasoning steps, sub-agent activity, research progress, and connector approval requests. It ends as completed, failed, cancelled, or stopped. The event log also supplies token, tool-call, duration, and context-window aggregates.
Stopping is cooperative: the UI records a stopping state, asks the worker to abort, and waits for the terminal event. It does not delete the surrounding session.
Tool calls that completed before the stop, together with any recorded partial assistant text, remain in the conversation history. A later turn can therefore use completed work from the stopped run without repeating it.
History and the live tail
Conversation history and live execution use the same durable event shape but different transports. The app loads recent, whole-turn history pages over REST, then resumes one SSE connection after the page's latest sequence for events that happen next. Scrolling upward requests older pages with an exclusive sequence cursor; it does not create another SSE replay.
The conversation overview is a separate lightweight index across all authorized turns. This lets the rail represent the entire session immediately while the transcript mounts only a small virtualized window. Selecting a distant marker loads the required history pages before focusing that turn.
Why the distinction matters
This model explains several product behaviors:
- another message can queue behind active work without creating a second chat;
- waking an agent appends a proactive turn to its existing conversation;
- an automation's runs can be compared without merging their transcripts;
- a completed assistant response can be branched into a new chat at that point in history;
- deleting a project is blocked while a run still owes a terminal event.
Treat the session id as the stable handle for conversation and streaming. Treat the turn id and event sequence as the handles for one input and its lifecycle.