Documentation Index Fetch the complete documentation index at: https://mintlify.com/asundar43/simpleclaw/llms.txt
Use this file to discover all available pages before exploring further.
WebSocket Protocol
The SimpleClaw Gateway uses a binary WebSocket protocol for all client-server communication. The protocol supports request/response patterns and server-pushed events.
Connection Flow
Open WebSocket Connection
Connect to the Gateway WebSocket endpoint: const ws = new WebSocket ( 'ws://127.0.0.1:18789' );
Remote connections: Use Tailscale Serve/Funnel for WSS:const ws = new WebSocket ( 'wss://gateway-name.tailnet.ts.net' );
Send Connect Frame
Send a ConnectParams object as the first message: {
"minProtocol" : 1 ,
"maxProtocol" : 1 ,
"client" : {
"id" : "web-ui" ,
"displayName" : "Web Dashboard" ,
"version" : "2026.3.1" ,
"platform" : "web" ,
"mode" : "interactive"
},
"caps" : [],
"locale" : "en-US"
}
Receive Hello-OK
Server responds with a HelloOk frame: {
"type" : "hello-ok" ,
"protocol" : 1 ,
"server" : {
"version" : "2026.3.1" ,
"connId" : "conn-abc123"
},
"features" : {
"methods" : [ "chat.send" , "sessions.list" , ... ],
"events" : [ "chat" , "agent" , "tick" ]
},
"snapshot" : {
"agents" : [ ... ],
"channels" : [ ... ]
},
"policy" : {
"maxPayload" : 10485760 ,
"maxBufferedBytes" : 52428800 ,
"tickIntervalMs" : 30000
}
}
Send Requests
After receiving HelloOk, send method calls as RequestFrame: {
"type" : "req" ,
"id" : "req-001" ,
"method" : "sessions.list" ,
"params" : { "agentId" : "main" }
}
Receive Responses and Events
The server sends:
Response frames matching request IDs
Event frames for asynchronous updates
Frame Types
Request Frame
Client-to-server method invocation:
interface RequestFrame {
type : "req" ;
id : string ; // Unique request ID (client-generated)
method : string ; // Method name (e.g., "sessions.list")
params ?: unknown ; // Method parameters (optional)
}
Example:
{
"type" : "req" ,
"id" : "req-123" ,
"method" : "config.get" ,
"params" : { "path" : "agent.model" }
}
Response Frame
Server response to a request:
interface ResponseFrame {
type : "res" ;
id : string ; // Matches request ID
ok : boolean ; // Success indicator
payload ?: unknown ; // Result data (if ok=true)
error ?: ErrorShape ; // Error details (if ok=false)
}
Success Example:
{
"type" : "res" ,
"id" : "req-123" ,
"ok" : true ,
"payload" : { "agent" : { "model" : "anthropic/claude-opus-4-6" } }
}
Error Example:
{
"type" : "res" ,
"id" : "req-123" ,
"ok" : false ,
"error" : {
"code" : "INVALID_PARAMS" ,
"message" : "path is required" ,
"retryable" : false
}
}
Event Frame
Server-pushed events (no request):
interface EventFrame {
type : "event" ;
event : string ; // Event name (e.g., "chat", "tick")
payload ?: unknown ; // Event data
seq ?: number ; // Optional sequence number
stateVersion ?: object ; // Optional state version
}
Example:
{
"type" : "event" ,
"event" : "chat" ,
"seq" : 42 ,
"payload" : {
"sessionKey" : "main" ,
"role" : "assistant" ,
"text" : "Hello! How can I help?"
}
}
Common Events
chat Event
Agent conversation events:
interface ChatEvent {
sessionKey : string ;
role : "user" | "assistant" | "system" ;
text ?: string ;
tool ?: string ;
thinking ?: string ;
done ?: boolean ;
}
agent Event
Agent state changes:
interface AgentEvent {
agentId : string ;
model ?: string ;
thinkingLevel ?: string ;
verboseLevel ?: string ;
}
tick Event
Periodic heartbeat:
interface TickEvent {
ts : number ; // Unix timestamp (ms)
}
shutdown Event
Gateway restart notification:
interface ShutdownEvent {
reason : string ;
restartExpectedMs ?: number ;
}
Error Codes
Common error codes returned in ErrorShape:
Code Description Retryable INVALID_PARAMSInvalid request parameters No METHOD_NOT_FOUNDUnknown method No PERMISSION_DENIEDInsufficient permissions No RATE_LIMITEDToo many requests Yes TIMEOUTRequest timed out Yes INTERNAL_ERRORServer error Maybe AGENT_NOT_FOUNDUnknown agent ID No SESSION_NOT_FOUNDUnknown session key No
Message Size Limits
Default policy from HelloOk:
{
"maxPayload" : 10485760 , // 10MB per message
"maxBufferedBytes" : 52428800 , // 50MB total buffer
"tickIntervalMs" : 30000 // 30s heartbeat
}
Exceeding maxPayload returns PAYLOAD_TOO_LARGE error.
Client Implementation
import WebSocket from 'ws' ;
class GatewayClient {
private ws : WebSocket ;
private reqId = 0 ;
private pending = new Map < string , ( res : ResponseFrame ) => void >();
constructor ( url : string ) {
this . ws = new WebSocket ( url );
this . ws . on ( 'message' , ( data ) => this . handleMessage ( data ));
}
async connect ( clientInfo : ConnectParams ) : Promise < HelloOk > {
this . ws . send ( JSON . stringify ( clientInfo ));
return new Promise (( resolve ) => {
this . ws . once ( 'message' , ( data ) => {
resolve ( JSON . parse ( data . toString ()));
});
});
}
async request < T >( method : string , params ?: unknown ) : Promise < T > {
const id = `req- ${ this . reqId ++ } ` ;
const frame : RequestFrame = { type: 'req' , id , method , params };
return new Promise (( resolve , reject ) => {
this . pending . set ( id , ( res ) => {
if ( res . ok ) {
resolve ( res . payload as T );
} else {
reject ( res . error );
}
});
this . ws . send ( JSON . stringify ( frame ));
});
}
private handleMessage ( data : WebSocket . Data ) {
const frame = JSON . parse ( data . toString ());
if ( frame . type === 'res' ) {
const handler = this . pending . get ( frame . id );
if ( handler ) {
handler ( frame );
this . pending . delete ( frame . id );
}
} else if ( frame . type === 'event' ) {
this . emit ( frame . event , frame . payload );
}
}
}
Reconnection Strategy
Exponential Backoff
Retry with increasing delays: 1s, 2s, 4s, 8s, max 30s
Re-authenticate
Send fresh ConnectParams after reconnect
Re-subscribe
Restore any stateful subscriptions (e.g., log tailing)
Next Steps
Protocol Reference Complete schema documentation for all methods
Build a Client SDK reference for custom integrations