Gateway
WebSocket JSON-RPC gateway for client connections, session management, execution engine, and multi-interface support.
The gateway module is Aleph's WebSocket JSON-RPC gateway. It handles client connections, session management, the execution engine, and interfaces with multiple messaging platforms (Discord, Telegram, CLI, TUI, etc.).
Design Philosophy
- Interface-agnostic core — The same agent brain serves every interface
- Session isolation — Each conversation is an independent session with its own context
- Streaming responses — Real-time token streaming to all connected clients
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Gateway │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ WebSocket │ │ Session │ │ Execution │ │
│ │ Handler │ │ Manager │ │ Engine │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Discord │ │ Telegram │ │ CLI │ │
│ │ Interface │ │ Interface │ │ Interface │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘Core Components
WebSocket Handler
Accepts JSON-RPC 2.0 connections:
pub struct WebSocketHandler;
impl WebSocketHandler {
pub async fn handle(
&self,
socket: WebSocket,
) -> Result<()> { /* ... */ }
}Methods:
session.create— Create a new sessionsession.send— Send a messagesession.history— Get conversation historysession.clear— Clear session contexttool.call— Invoke a tool directly
SessionManager
Manages active sessions:
pub struct SessionManager {
sessions: HashMap<SessionId, Session>,
}
impl SessionManager {
pub async fn create(
&self,
config: SessionConfig,
) -> Result<SessionId> { /* ... */ }
pub async fn get(
&self,
id: SessionId,
) -> Option<Session> { /* ... */ }
}Session types:
Owner— Full access to all featuresGuest— Restricted access, no persistent historyPaired— Linked to a specific channel (Telegram, Discord)
ExecutionEngine
The agent loop that processes messages:
pub struct ExecutionEngine {
thinker: Thinker,
tool_service: ToolService,
provider: Arc<dyn LlmProvider>,
}
impl ExecutionEngine {
pub async fn run(
&self,
request: RunRequest,
) -> Result<RunOutput> { /* ... */ }
}Flow:
- Receive
RunRequest(message + attachments + context) - Process attachments via
MediaProcessor - Build system prompt via
Thinker - Call LLM provider
- Parse response (text + tool calls)
- Execute tools
- Stream results back to client
Interfaces
Platform-specific adapters:
Discord:
- Bot integration via
serenity - Slash commands
- DM and guild channel support
Telegram:
- Bot integration via
teloxide - Inline queries
- Group chat support
CLI:
- Interactive terminal interface
- Command history
- Tab completion
TUI:
- Terminal UI with
ratatui - Multi-pane layout
- Real-time streaming
Routing
Messages are routed to the appropriate handler:
pub struct InboundRouter {
handlers: HashMap<InterfaceType, Box<dyn MessageHandler>>,
}Routing rules:
- WebSocket → SessionManager → ExecutionEngine
- Discord → ChannelManager → SessionManager
- Telegram → BotHandler → SessionManager
- CLI → DirectExecution
Rate Limiting
pub struct RateLimiter {
buckets: HashMap<String, TokenBucket>,
}Per-session and per-user rate limits prevent abuse.
Safety Properties
- UTF-8 safe — All string operations use
char_indices()or.find() - Lock recovery —
unwrap_or_else(|e| e.into_inner()) - No unwrap in production — All hot paths return
Result - Saturating arithmetic —
saturating_subfor index calculations
Code Location
src/gateway/— Module rootsrc/gateway/handlers/— WebSocket and HTTP handlerssrc/gateway/session/— Session managementsrc/gateway/execution_engine/— Agent execution loopsrc/gateway/interfaces/— Platform adapters (Discord, Telegram, CLI, TUI)src/gateway/routing/— Message routing
See Also
- Session Management — Session lifecycle
- Event System — Event distribution
- Thinker — Prompt construction
26.7.x Addendum
Single-Source Error Chain
26.7.21+: the gateway returns a single-source user-readable error to the client. The raw error chain never leaks out to the Panel — the previous implementation would surface raw serde_json / sqlx / io errors directly to the user.
WS Task-Leak Fixes
26.7.21+: per-connection event-forward tasks no longer leak on WebSocket disconnect; the channel forwarder recovers on broadcast::RecvError::Lagged rather than dying permanently.
Webhook Backpressure
26.7.21+: webhook receivers return 503 under congestion rather than silently dropping inbound messages.
Dead-Letter and Re-Drive
26.7.17+: channel.dead_letters collects undelivered messages; channel.redrive_dead_letters re-drives them.
Self-Signed TLS + TOFU
26.7.17/18+:
- In-process gateway TLS (
[gateway] tls/trusted_proxy/allow_insecure_remote) - Self-signed cert SAN auto-discovers host's non-loopback interface IPs
- Drift sidecar + atomic regen marker
- Client-side TOFU (fingerprint + SAN approval + pinned trust store)
- macOS WKWebView + iOS Keychain adapters
Real Client IP
26.7.17+: [gateway] trusted_proxy reverse-proxy trust list — decides whether the gateway reads the real client IP (capacity limits, rate limits, audit, connect-auth).
gateway.ticket.create / token.rotate / devices.*
26.7.x full device-ticket / token-rotation / device-management RPC. Remote sessions are closed on token rotation; loopback sessions are preserved.
Full RPC
26.7.x the gateway exposes ~265 RPC methods — see Gateway Methods Reference.
See Also
- Gateway Protocol — WebSocket protocol
- Gateway Auth — auth / pairing / TOFU
- Gateway Methods — full RPC
Bundled Content
Compile-time-embedded official skills / plugins / templates, extracted on startup via version comparison into `~/.aleph/bundled/`, with symlink-planting rejected.
Thinker (Prompt Engine)
Thinker is Aleph's prompt construction engine: ~28 fine-grained PromptLayers with priority + the stable_summary / live_status dual-track cache discipline, plus the prompt_contract reachability / ratchet checks.