From e159476d31b4afe41aa45c53cea97a647ff83f67 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Sun, 15 Feb 2026 11:21:39 -0800 Subject: [PATCH] docs(architecture): explain gateway session mapping and per-session queueing --- docs/README.md | 2 +- .../GATEWAY_SESSIONS_AND_QUEUE.md | 100 ++++++++++++++++++ docs/plans/state.json | 5 + 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 docs/architecture/GATEWAY_SESSIONS_AND_QUEUE.md diff --git a/docs/README.md b/docs/README.md index bef70e2..d05fb8a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,6 +6,7 @@ This documentation is written to be useful to both humans and AI agents. If you 1. Architecture overview (agent-oriented) - `docs/architecture/AGENT_DIAGRAM.md` + - `docs/architecture/GATEWAY_SESSIONS_AND_QUEUE.md` - `docs/architecture/TYPESCRIPT_MAP.md` - `docs/architecture/SYMBOL_INDEX.md` - `docs/architecture/CONTRIBUTOR_MAP.md` @@ -37,4 +38,3 @@ flowchart TD NA --> TP[ToolPolicy + ToolRegistry] TP --> TE[ToolExecutor\nhooks + enforcement + audit] ``` - diff --git a/docs/architecture/GATEWAY_SESSIONS_AND_QUEUE.md b/docs/architecture/GATEWAY_SESSIONS_AND_QUEUE.md new file mode 100644 index 0000000..10d8ffb --- /dev/null +++ b/docs/architecture/GATEWAY_SESSIONS_AND_QUEUE.md @@ -0,0 +1,100 @@ +# Gateway Sessions and Queueing (Agent Execution Model) + +This document explains how the gateway maps WebSocket clients onto durable sessions, and how work is serialised per session so agent execution stays coherent under concurrent requests. + +If you only want the protocol surface, see `docs/api/PROTOCOL.md`. + +## Key Ideas + +- A WebSocket client gets a `connectionId`. +- Each connection is attached to a `sessionId`. +- Agent work is queued per `sessionId` (FIFO), not per connection. +- Sessions persist in SQLite via `SessionManager` even if clients disconnect. + +## Component Map + +```mermaid +flowchart LR + subgraph GW[Gateway Process] + WS[WebSocket connection\n(connectionId)] + GS[GatewayServer] + LQ[LaneQueue\nper-session FIFO] + SB[SessionBridge\nconnectionId -> sessionId -> AgentOrchestrator] + end + + subgraph CORE[Flynn Core] + SM[SessionManager\nin-memory cache + SQLite] + SS[SessionStore\nSQLite tables] + AO[AgentOrchestrator] + end + + WS --> GS + GS --> LQ + GS --> SB + + SB --> AO + SB --> SM + SM --> SS +``` + +## Session IDs (What Actually Gets Stored) + +The durable session ID stored by `SessionManager` is: + +`:` + +For the gateway: + +- `SessionBridge.connect()` assigns a `connectionId` (UUID). +- It defaults the connection's `sessionId` to `ws:`. +- It then calls `SessionManager.getSession('ws', sessionId)`. + +That means gateway sessions are stored as: + +- `ws:ws:` + +This is expected: the gateway adds its own namespace, and the session manager namespaces again by frontend. + +Key files: + +- `src/gateway/session-bridge.ts` +- `src/session/manager.ts` + +## Per-Session FIFO Queueing (LaneQueue) + +`agent.send` uses a lane ID derived from the session: + +- lane = `SessionBridge.getSessionId(connectionId)` (preferred) +- fallback lane = `connectionId` (only if session lookup fails) + +Within a lane: + +- Only one request executes at a time. +- Later requests queue (FIFO) and start after the active request finishes. + +Across lanes: + +- Independent sessions run in parallel. + +Key files: + +- `src/gateway/lane-queue.ts` +- `src/gateway/handlers/agent.ts` + +## Cancellation Semantics + +`agent.cancel` performs two separate actions: + +1. Cancels any queued (not-yet-started) work in the lane (`LaneQueue.cancel(laneId)`). +2. Requests cancellation of the active agent operation (`AgentOrchestrator.cancel()` via `SessionBridge.cancel()`). + +Important: + +- Cancellation is best-effort for the currently running work: it stops at the next safe point in the agent loop. +- Queued work is deterministically rejected. + +Key files: + +- `src/gateway/handlers/agent.ts` +- `src/backends/native/orchestrator.ts` + diff --git a/docs/plans/state.json b/docs/plans/state.json index 47d11f1..a7369ab 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -9,6 +9,11 @@ "date": "2026-02-15", "summary": "Docs gap pass: added docs/README.md as a start-here index and expanded docs/api/PROTOCOL.md with a precise Mermaid diagram explaining per-session lane queueing and cancellation semantics for agent.send/agent.cancel." }, + "docs-gateway-sessions-and-queue": { + "status": "completed", + "date": "2026-02-15", + "summary": "Added docs/architecture/GATEWAY_SESSIONS_AND_QUEUE.md to document how gateway connectionIds map to durable sessionIds, how per-session FIFO lane queueing works, and how agent.cancel behaves." + }, "openclaw-gap-roadmap": { "file": "2026-02-15-openclaw-gap-roadmap.md", "status": "planned",