Skip to main content
Gateway sessions preserve pending messages and in-flight executions across disconnects, restarts, and graceful shutdowns.

Quick Start

1

Start gateway with an agent

from praisonaiagents import Agent

agent = Agent(
    name="assistant",
    instructions="Answer user messages in order.",
)

# Default drain timeout is 10 s on stop()
# praisonai gateway start --config gateway.yaml
2

Graceful shutdown with drain

import asyncio
from praisonai.gateway.server import WebSocketGateway

async def shutdown_gateway(gateway: WebSocketGateway):
    await gateway.stop(drain_timeout=10.0)  # wait up to 10 s for in-flight turns

asyncio.run(shutdown_gateway(gateway))

How It Works

When a client reconnects, the gateway checks whether the session has queued inbox messages or an in-flight execution. If so, it sends a status frame, marks the session as executing before spawning the queue task (preventing duplicate workers), and processes pending messages in FIFO order.

Graceful Drain on Shutdown

WebSocketGateway.stop() calls _drain_active_sessions before closing WebSocket clients. The gateway waits up to drain_timeout seconds (default 10.0) for sessions that are executing or have a non-empty inbox.
PhaseBehaviour
Within timeoutSessions that finish are persisted via the configured session store
After timeoutRemaining sessions are force-persisted with pending work; a SESSION_END event is emitted
Force-closed SESSION_END payload:
{
  "session_id": "...",
  "reason": "Force-closed during shutdown after timeout",
  "had_pending_work": true,
  "was_executing": true
}
Configure a _session_store so drained sessions survive restarts. Without one, force-closed sessions are only logged.

Reconnect and Auto-Resume

On resume, clients receive:
{
  "type": "status",
  "message": "Resuming processing (2 pending messages)..."
}
The gateway sets mark_executing(True) before launching asyncio.create_task(_run_session_queue(...)), so a race between reconnect and shutdown cannot spawn duplicate queue processors.

Persisted Shape

Gateway session snapshots now include pending work:
{
  "session_id": "...",
  "messages": [],
  "events": [],
  "event_cursor": 42,
  "pending_inbox": ["queued message 1", "queued message 2"],
  "is_executing": true
}
The inbox is snapshotted non-destructively: items are drained into a list and put back so live processing is unaffected.

Configuration

OptionTypeDefaultDescription
drain_timeoutfloat10.0Seconds to wait for in-flight sessions during WebSocketGateway.stop() before force-persisting

Best Practices

Set drain_timeout to at least your longest expected agent turn so clean shutdowns finish naturally before force-persist.
Without persistence, drained sessions cannot be resumed after restart — only logged.
Listen for had_pending_work: true or was_executing: true in audit or observability hooks to detect force-closed sessions.
Send messages faster than the agent processes them, then drop the WebSocket — pending messages should resume in order on reconnect.

Gateway

WebSocket control plane overview

Session Persistence

Persistent sessions and event replay

Error Handling

Reconnect and error recovery

Session Protocol

Session message format