> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blobhub.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Events

> Definitions for asynchronous events emitted by a Session context.

Session Events report changes to a session — both to the session itself as it moves through its
lifecycle, and to the data held inside it. They let a listener react to session state without
polling for it.

Every event is delivered over the realtime WebSocket API and, with one documented exception below,
also recorded in the session's stored event stream, readable with
[List Session Events](/blob-types/workflow/operations/list-session-events).

## Shared Event Format

All session events conform to the following base structure:

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",   
  "created_at": "2026-05-28T12:00:00.000000Z",
  "type": "event_type_string",
  ... // Dynamic event-specific properties
}
```

Events fall into two families: **lifecycle** events, which mark a change to the session's own
`status`, and **content** events, which report a change to something held inside it.

## Lifecycle Events

These four mark the transitions described in
[Session Lifecycle](/blob-types/workflow/workflows/session-lifecycle). They carry no payload beyond
the shared fields — the `type` and the `session_id` are the whole message.

<Note>
  Closing and deleting are asynchronous, so each emits one event when it starts and another when it
  finishes. Reopening is synchronous and emits **no** event: the caller reads the new status from the
  `reopen_session` response.
</Note>

### `session_closing`

Fired when `close_session` is accepted. The session is now read-only — every mutating command,
including `create_execution`, returns `409` — but any executions still running are only beginning to
stop.

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",
  "created_at": "2026-07-24T12:00:00.000000Z",
  "type": "session_closing"
}
```

### `session_closed`

Fired once the close has completed: every execution has reached a terminal status and the session is
frozen. This — not the `close_session` response — is the signal that a close is finished.

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",
  "created_at": "2026-07-24T12:00:42.000000Z",
  "type": "session_closed"
}
```

### `session_deleting`

Fired when `delete_session` is accepted. Teardown has begun: running executions are being stopped,
and once they are terminal the session's contents are purged.

**This event stands alone.** A session may be deleted directly from `open`, in which case there is
no preceding `session_closing` or `session_closed` — the delete performs the stop-and-purge itself.
Treat `session_deleting` as a complete "this session is going away" signal in its own right, and do
not wait for a close that will never come.

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",
  "created_at": "2026-07-24T12:01:00.000000Z",
  "type": "session_deleting"
}
```

### `session_deleted`

Fired when teardown has finished. The session and everything in it are gone; requests referencing it
now return `403`.

<Warning>
  This event is delivered over the realtime WebSocket API **only**. The session's stored event stream
  is purged as part of the teardown, so `session_deleted` cannot be read back afterwards with
  `list_session_events` — by the time it fires there is no stream left to read. Every other event on
  this page is available through both channels.
</Warning>

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",
  "created_at": "2026-07-24T12:01:40.000000Z",
  "type": "session_deleted"
}
```

### Reacting to lifecycle events

* **Applications** should reflect the new status, disable editing affordances once a session leaves
  `open`, and on `session_deleted` drop the session from their local state and refresh any listing.
* **Workers and other long-lived consumers** should detach on `session_closed` or `session_deleting`:
  release any lease held on the session and stop polling it. Continuing to write will only produce
  `409`s, and continuing to poll a deleted session yields nothing.

## Content Events

### `session_object_modified`

Fired whenever an object is created or overwritten in the session — whether the write comes from the
REST `upload_session_object` command or a workflow processor that writes into the session store. Useful
for reactive applications that poll or stream session state.

The `session_object` payload carries the object's `alias` and its `type` (the envelope's `value.type` —
e.g. `message`, `graph`, `thread`), so a listener can skip downloading kinds it does not care about.

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",   
  "created_at": "2026-05-28T12:00:00.000000Z",
  "type": "session_object_modified",
  "session_object": {
    "alias": "my_stored_configuration_data",
    "type": "message"
  }
}
```

### `session_object_deleted`

Fired when a `delete_session_object` call removes a session object from the active session. For
thread- and graph-typed objects this cascades to remove all of the object's items or elements.

The `session_object` payload carries the deleted object's `alias` and its `type` when it is known — a
REST delete reads the envelope first, so it includes the `type`; other callers may omit it, in which
case `type` is `null`.

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",
  "created_at": "2026-05-28T12:00:00.000000Z",
  "type": "session_object_deleted",
  "session_object": {
    "alias": "my_stored_configuration_data",
    "type": "graph"
  }
}
```

### `session_thread_item_posted`

Fired when a `post_session_thread_item` call adds an item to a thread session object. Listeners can
re-fetch the thread tail via `list_session_thread_items` using the `item_id` to anchor
`created_since`.

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",
  "created_at": "2026-05-28T12:00:00.000000Z",
  "type": "session_thread_item_posted",
  "session_object": {
    "alias": "onboarding_thread",
    "item_id": "uuid-of-the-new-item"
  }
}
```

### `session_graph_changed`

Fired once per `apply_session_graph_mutations` call, carrying the change delta for the affected graph
session object. Each entry in `changes` identifies one applied operation.

```json theme={null}
{
  "id": "uuid-event-id",
  "revision_id": "uuid-workflow-revision",
  "session_id": "uuid-active-session",
  "created_at": "2026-06-06T10:00:01.000000Z",
  "type": "session_graph_changed",
  "session_object": {
    "alias": "task_graph",
    "changes": [
      { "op": "upsert", "element_id": "t1", "type": "vertex", "rev": 4 },
      { "op": "delete", "element_id": "e7", "type": "edge" }
    ]
  }
}
```

Listeners apply the delta incrementally: remove elements whose `op` is `"delete"` from the local
cache, then call `get_session_graph_elements` with the `element_id` values from the remaining
`"upsert"` entries to fetch their updated state. This avoids refetching the entire graph on each
mutation.
