Proxy

WebSocket security proxy between clients and agent gateway.


@securitylayerai/proxy is a WebSocket proxy that sits between clients and the agent gateway. It intercepts every frame, runs it through the security pipeline via an adapter, and blocks or allows based on the evaluation result.

Architecture

Client (port 18790) ──→ Proxy ──→ Agent Gateway (port 18789)

                          ├── Adapter (parse frames)
                          ├── Interceptor (evaluate actions)
                          ├── Gateway Lock (prevent bypass)
                          └── Metrics (/metrics endpoint)

The proxy is transparent — clients connect to it instead of the agent gateway directly. The gateway lock ensures the agent gateway only accepts connections from the proxy, preventing bypass.

Components

Proxy server

Bun WebSocket server that accepts client connections and relays frames through the interceptor.

import { createProxyServer } from "@securitylayerai/proxy";

const server = createProxyServer({
  port: 18790,
  host: "127.0.0.1",
  getMetricsText: () => metrics.toPrometheusText(),
});

Also serves an HTTP /metrics endpoint for Prometheus scraping.

Upstream connection

WebSocket client that connects to the agent gateway with automatic reconnection and exponential backoff.

import { createUpstreamConnection } from "@securitylayerai/proxy";

const upstream = createUpstreamConnection({
  url: "ws://127.0.0.1:18789",
  maxRetries: 10,
  retryDelayMs: 1000,
  maxRetryDelayMs: 30000,
  onMessage: handleUpstreamMessage,
  onConnect: () => console.log("Connected to gateway"),
  onDisconnect: () => console.log("Disconnected from gateway"),
});

Interceptor

Routes parsed frames through the security pipeline using the adapter.

import { createInterceptor } from "@securitylayerai/proxy";

const interceptor = createInterceptor({
  adapter,
  evaluateAction: pipeline.evaluate,
});

const result = await interceptor.intercept(rawFrame);
// result.decision: "ALLOW" | "DENY" | "REQUIRE_APPROVAL"
// result.denyResponse?: Buffer (if denied)

Gateway lock

Prevents clients from connecting directly to the agent gateway, ensuring all traffic flows through the proxy.

Three lockdown strategies:

StrategyHow it works
validation_tokenProxy includes a secret token; gateway rejects connections without it
unix_socketGateway listens on a Unix socket only accessible to the proxy
firewallFirewall rules restrict gateway port to localhost
import { createGatewayLock } from "@securitylayerai/proxy";

const lock = createGatewayLock({
  strategy: "validation_token",
  token: process.env.GATEWAY_TOKEN,
});

await lock.verify(); // Throws if lockdown isn't active

Metrics collector

Tracks proxy performance and security decisions. Exposes Prometheus-compatible text output.

import { createMetricsCollector } from "@securitylayerai/proxy";

const metrics = createMetricsCollector();

metrics.recordDecision("ALLOW", 12);  // decision, latency_ms
metrics.recordDecision("DENY", 3);
metrics.recordTaintElevation("owner", "web");

console.log(metrics.toPrometheusText());
// securitylayer_decisions_total{decision="ALLOW"} 42
// securitylayer_decisions_total{decision="DENY"} 3
// securitylayer_latency_p50 8
// securitylayer_latency_p95 45
// securitylayer_latency_p99 120

Starting the proxy

The startProxy() function wires everything together:

import { startProxy } from "@securitylayerai/proxy";

const proxy = startProxy({
  listenPort: 18790,
  listenHost: "127.0.0.1",
  upstreamUrl: "ws://127.0.0.1:18789",
  adapter: openClawAdapter,
  evaluateAction: pipeline.evaluate,
  gatewayLock: {
    strategy: "validation_token",
    token: process.env.GATEWAY_TOKEN,
  },
});

// Later
await proxy.stop();

Configuration

interface ProxyConfig {
  listenPort: number;        // Default: 18790
  listenHost: string;        // Default: "127.0.0.1"
  upstreamUrl: string;       // Agent gateway URL
  adapter: AgentAdapter;     // From @securitylayerai/adapters
  evaluateAction: EvaluateActionFn;  // Security pipeline
  gatewayLock?: GatewayLockConfig;
}

Package structure

packages/proxy/
├── src/
│   ├── index.ts           # startProxy() + barrel exports
│   ├── types.ts           # ProxyConfig, ProxyState, etc.
│   ├── server.ts          # WebSocket server + /metrics
│   ├── upstream.ts        # Gateway connection + reconnect
│   ├── interceptor.ts     # Frame interception logic
│   ├── gateway-lock.ts    # Bypass prevention
│   └── metrics.ts         # Prometheus metrics
└── test/
    ├── interceptor.test.ts
    ├── gateway-lock.test.ts
    └── metrics.test.ts

See also

  • Adapters — Frame parsing for different agent protocols
  • Core — The security pipeline the proxy calls
  • Security pipeline — How evaluation works

On this page