Session

AEP Session Lifecycle

> Status: draft. Part of the AEP 0.1 protocol specification.

Purpose

Define the session lifecycle that governs protocol-level communication between an AEP producer and consumer. A session represents an established bidirectional event stream.

State Machine

A session moves through the following states:

 CREATED
    │
    ▼
 OPENED ──────────────────────────────────┐
    │                                      │
    ▼                                      │
  READY ──────────(heartbeat loop)────────┐│
    │           │                          ││
    │           └──────────────────────┐   ││
    ▼                                  ▼   ▼▼
 CLOSED                              ERROR

Valid transitions:

FromToTrigger
CREATEDOPENEDsession.opened event sent or received
CREATEDCLOSEDTransport disconnect before open
CREATEDERRORProtocol or transport error before open
OPENEDREADYsession.ready sent, capability negotiation complete
OPENEDCLOSEDsession.closed or transport disconnect
OPENEDERRORProtocol or transport error
READYCLOSEDsession.closed or graceful transport shutdown
READYERRORUnrecoverable error or heartbeat timeout
CLOSEDTerminal state
ERRORTerminal state

Session Events

session.opened

Sent by the initiator to begin a session.

{
  "type": "session.opened",
  "payload": {
    "session_id": "sess_01",
    "version": "0.1"
  }
}

Required payload fields: session_id, version.

session.ready

Sent when the handshake completes and both sides agree on capabilities. A session is not usable until session.ready has been exchanged.

{
  "type": "session.ready",
  "payload": {
    "session_id": "sess_01",
    "capabilities": {
      "protocol": "aep",
      "aep_version": "0.1",
      "transports": ["stdio", "websocket"],
      "delivery_modes": ["best_effort", "at_least_once", "replayable"],
      "features": ["envelope", "subscription", "task_lifecycle", "error_model"],
      "max_payload_size": 1048576,
      "compression": ["gzip"],
      "heartbeat_interval_ms": 30000
    }
  }
}

Required payload fields: session_id, capabilities.

Capability fields:

FieldTypeRequiredDescription
protocolstringyes"aep"
aep_versionstringyesProtocol version string
transportsstring[]yesSupported transport names
delivery_modesstring[]noSupported delivery guarantees
featuresstring[]noSupported protocol features
max_payload_sizenumbernoMaximum payload bytes accepted
compressionstring[]noSupported compression algorithms
heartbeat_interval_msnumbernoExpected heartbeat interval (0 = disabled)

session.heartbeat

Sent periodically by either side when heartbeat_interval_ms > 0. No response is expected. A peer that misses N consecutive heartbeat intervals (implementation-defined, recommended N=3) should transition the session to ERROR.

{
  "type": "session.heartbeat",
  "payload": {
    "session_id": "sess_01"
  }
}

session.closed

Graceful shutdown. After sending or receiving session.closed, the session is in terminal state and no further events should be exchanged.

{
  "type": "session.closed",
  "payload": {
    "session_id": "sess_01",
    "reason": "done"
  }
}

session.error

Unrecoverable session error. The session transitions to ERROR on send or receive. The transport should close after delivering this event.

{
  "type": "session.error",
  "payload": {
    "session_id": "sess_01",
    "error": {
      "code": "session_timeout",
      "message": "heartbeat timeout after 3 missed intervals",
      "retryable": true,
      "details": {
        "last_heartbeat_at": "2026-07-09T10:05:00Z"
      }
    }
  }
}

Error payload structure follows the error model.

Implementation Notes