kernel-broker — Architecture
The kernel-broker service bridges the CQRS command spine to remote agent-kernel processes running on customer hosts. It manages the full lifecycle of kernel connections: enrollment, session negotiation, tool dispatch, and revocation.
Responsibilities
- Maintain a persistent mTLS WebSocket registry of enrolled kernels via
registry.ts - Accept
InvokeKernelToolcommands from the command bus and forward them as JSON-RPC calls to the target kernel - Monitor kernel heartbeats and emit
KernelOnline/KernelOfflineevents when connectivity changes - Collect kernel metrics (CPU, memory, tool invocation latency) and emit
KernelMetricsCollectedevents - Evict stale kernel connections via
stale-watchdog.ts - Handle certificate rotation for enrolled kernels
Key Components
| File | Role |
|---|---|
src/server.ts | Hono WebSocket server accepting kernel mTLS connections |
src/registry.ts | In-memory registry mapping kernelId → WebSocket connection + metadata |
src/dispatch.ts | JSON-RPC dispatcher — routes InvokeKernelTool commands to the correct kernel |
src/certs.ts | mTLS certificate validation and rotation helpers |
src/metrics-collector.ts | Periodic metrics collection from connected kernels |
src/stale-watchdog.ts | Background loop that evicts kernels that haven’t heartbeated within the configured TTL |
Connection Lifecycle
agent-kernel (remote host) ↓ TLS ClientHello + certkernel-broker: validate cert against stored fingerprint (KernelEnrolled event) ↓ acceptedWebSocket upgrade → registry.add(kernelId, socket) ↓ heartbeat loopkernel-broker emits KernelOnline ↓InvokeKernelTool command arrives via Pub/Sub ↓dispatch.send(kernelId, toolName, args) → JSON-RPC over WebSocket ↓KernelInvocationCompleted | KernelInvocationFailed event emittedSession Model
Kernel sessions are gated by KernelSessionRequested / KernelSessionDecided events. The agent must approve a session (with a permission tier: read, read_write, privileged) before InvokeKernelTool commands targeting that kernel are dispatched.
Deployment
Runs as a single Cloud Run service with CPU-always-on enabled — WebSocket connections must remain alive. The kernel registry is in-memory and per-instance, so the broker requires exactly one replica (max-instances: 1 on Cloud Run, or session affinity if multiple replicas are unavoidable). The WebSocket connection, /pubsub push, and /invocations/:id/await long-poll must all land on the same instance. A Redis-backed routing table is planned to remove this single-replica constraint; until then the broker logs a startup warning when REPLICA_COUNT > 1 is detected.