Skip to content

Session Management

EleAgent supports up to 5 concurrent AI sessions, managed through a SQLite-backed slot system. This page documents how sessions work and how the concurrency limit is enforced.

How Sessions Work

Each time a user sends a message, the system:

  1. Acquires a session slot — one of the 5 available concurrent execution slots
  2. Binds the slot to a session ID — either reusing an existing session or creating a new one
  3. Sends heartbeats — the slot is kept alive while the query runs (every few seconds)
  4. Releases the slot — when the query completes, the slot becomes available for others

Slot Configuration

VariableDefaultDescription
MAX_ACTIVE_SESSIONS5Maximum simultaneous AI query executions
SESSION_LOCK_TTL_SECONDS120How long a slot stays reserved without a heartbeat

Database

Session state is tracked in an SQLite database at /artefacts/state/session_registry.db with two tables:

session_registry

Stores all known sessions:

ColumnDescription
session_idUnique session identifier
project_pathAssociated project directory
artefacts_dirSession's output directory
statusactive, completed, error
created_atCreation timestamp
last_activity_atLast activity timestamp

active_locks

Tracks currently held execution slots:

ColumnDescription
lock_idUnique lock identifier
session_idBound session (null until query starts)
owner_ws_idWebSocket connection holding the lock
acquired_atWhen the lock was acquired
heartbeat_atLast heartbeat timestamp
expires_atWhen the lock expires without heartbeat

Automatic Expiry

If a session holder crashes or disconnects without releasing its slot, the lock expires after SESSION_LOCK_TTL_SECONDS (default: 120 seconds). Expired locks are automatically purged when new slots are acquired or heartbeats are processed.

This prevents a single crashed session from permanently reducing the available slot pool.

Session Artefacts

Each session gets a dedicated output directory:

/artefacts/sessions/<session-key>/

Files created by the agent during a session (CSV exports, summaries, extracted data) are written here. These persist across session restarts and container rebuilds.

Monitoring

Check current slot usage:

bash
# From inside the controller container
sqlite3 /artefacts/state/session_registry.db \
  "SELECT COUNT(*) as active FROM active_locks WHERE expires_at > datetime('now')"

# Or via the health endpoint
curl http://localhost:3001/health