protocol

March 28, 2026 ยท View on GitHub

import "github.com/a3tai/openclaw-go/protocol"

Package protocol defines all wire types, constants, and serialization helpers for the OpenClaw Gateway WebSocket protocol (version 3). It contains no networking code -- only data structures and JSON marshal/unmarshal functions.

Every other package in this module depends on protocol.

Frame Types

The gateway protocol uses typed JSON frames over WebSocket text messages:

Frame TypeConstantDirectionPurpose
reqFrameTypeRequestclient -> gatewayRPC request
resFrameTypeResponsegateway -> clientRPC response
eventFrameTypeEventbidirectionalOne-way notification
invokeFrameTypeInvokegateway -> nodeInvoke a node capability
invoke-resFrameTypeInvokeResponsenode -> gatewayInvoke result
type Request struct {
    Type   FrameType       `json:"type"`
    ID     string          `json:"id"`
    Method string          `json:"method"`
    Params json.RawMessage `json:"params,omitempty"`
}

type Response struct {
    Type    FrameType       `json:"type"`
    ID      string          `json:"id"`
    OK      bool            `json:"ok"`
    Payload json.RawMessage `json:"payload,omitempty"`
    Error   *ErrorPayload   `json:"error,omitempty"`
}

type Event struct {
    Type         FrameType       `json:"type"`
    EventName    string          `json:"event"`
    Payload      json.RawMessage `json:"payload,omitempty"`
    Seq          *int64          `json:"seq,omitempty"`
    StateVersion *StateVersion   `json:"stateVersion,omitempty"`
}

Serialization Helpers

// Serialize frames
data, err := protocol.MarshalRequest(id, method, params)
data, err := protocol.MarshalResponse(id, payload)
data, err := protocol.MarshalErrorResponse(id, errPayload)
data, err := protocol.MarshalEvent(eventName, payload)

// Deserialize frames
frame, err := protocol.ParseFrame(data)      // determine type
req, err   := protocol.UnmarshalRequest(data)
resp, err  := protocol.UnmarshalResponse(data)
ev, err    := protocol.UnmarshalEvent(data)

Roles and Scopes

// Roles
protocol.RoleOperator  // "operator" - UI/CLI clients
protocol.RoleNode      // "node"     - capability hosts

// Operator scopes
protocol.ScopeOperatorRead      // "operator.read"
protocol.ScopeOperatorWrite     // "operator.write"
protocol.ScopeOperatorAdmin     // "operator.admin"
protocol.ScopeOperatorApprovals // "operator.approvals"
protocol.ScopeOperatorPairing   // "operator.pairing"

Scope Requirements

Each RPC method requires a minimum scope. Declare all needed scopes in WithScopes at connect time.

ScopeMethods covered
operator.readchat.history, cron.list, cron.status, cron.runs, sessions.list, sessions.preview, sessions.usage, agents.list, agents.files.list, config.get, config.schema, nodes.list, logs.tail, models.list
operator.writechat.send, chat.abort, sessions.send
operator.admincron.add, cron.update, cron.run, cron.remove, agents.create, agents.update, agents.delete, agents.files.set, config.set, config.apply, sessions.patch, sessions.reset, skills.install, skills.update
operator.approvalsexec.approvals.get, exec.approvals.resolve, exec.approvals.wait-decision
operator.pairingnode.pair.request, node.pair.approve, device.pair.approve, device.token.rotate

Common mistake: Using only operator.read + operator.write and hitting missing scope: operator.admin errors. The gateway enforces scopes on each RPC โ€” only request what you need, but request everything you need.

Connect Handshake

The connection lifecycle is: challenge -> connect request -> hello-ok response.

type ConnectChallenge struct {
    Nonce string `json:"nonce"`
    Ts    int64  `json:"ts"`
}

type ConnectParams struct {
    MinProtocol int            `json:"minProtocol"`
    MaxProtocol int            `json:"maxProtocol"`
    Auth        AuthParams     `json:"auth"`
    Client      ClientInfo     `json:"client"`
    Role        Role           `json:"role"`
    Scopes      []Scope        `json:"scopes,omitempty"`
    // ... plus Caps, Commands, Permissions, Device, Locale, UserAgent, PathEnv
}

type HelloOK struct {
    Protocol int            `json:"protocol"`
    Server   HelloServer    `json:"server"`
    Features HelloFeatures  `json:"features"`
    Snapshot *Snapshot      `json:"snapshot,omitempty"`
    Policy   HelloPolicy    `json:"policy"`
}

RPC Parameter/Result Types

The package defines typed Go structs for every gateway RPC method. Major categories:

CategoryExample Types
ChatChatSendParams, ChatHistoryParams, ChatAbortParams, ChatEvent
AgentAgentParams, AgentEvent, AgentIdentityParams
SessionsSessionsListParams, SessionsPatchParams, SessionsUsageParams
Agents CRUDAgentsCreateParams, AgentsUpdateParams, AgentsFilesGetParams
ConfigConfigGetParams, ConfigSetParams, ConfigApplyParams, ConfigSchemaResponse
NodesNodePairRequestParams, NodeInvokeParams, NodeEventParams
Device PairingDevicePairApproveParams, DeviceTokenRotateParams
Exec ApprovalsExecApprovalRequestParams, ExecApprovalResolveParams, ExecApprovalWaitDecisionParams
CronCronAddParams, CronUpdateParams, CronRunParams, CronJob
TTSTTSConvertParams, TTSSetProviderParams, TTSStatusResult
Channels/TalkTalkModeParams, TalkConfigParams, ChannelsStatusResult
SkillsSkillsInstallParams, SkillsUpdateParams, SkillsBinsResult
WizardWizardStartParams, WizardNextParams, WizardStep
ModelsModelChoice, ModelsListResult
LogsLogsTailParams, LogsTailResult
PushPushTestParams, PushTestResult
Health/PresencePresenceEntry, HealthEvent, HeartbeatEvent

Event Payload Types

// Real-time events with fully-typed payloads
PresenceEvent           // client presence changes
HealthEvent             // system health snapshots
HeartbeatEvent          // periodic heartbeat with system stats
TickEvent               // keepalive tick
ShutdownEvent           // gateway shutdown
CronEvent               // cron job execution events
VoicewakeChangedEvent   // voice wake word state changes
ExecApprovalResolvedEvent // approval decision events

Constants

protocol.ProtocolVersion              // 3
protocol.MaxPayloadBytes              // 25 MiB
protocol.MaxBufferedBytes             // 50 MiB
protocol.DefaultTickIntervalMs        // 30,000
protocol.DefaultHandshakeTimeoutMs    // 10,000
protocol.SessionLabelMaxLength        // 64

// Error codes
protocol.ErrorCodeNotLinked
protocol.ErrorCodeNotPaired
protocol.ErrorCodeAgentTimeout
protocol.ErrorCodeInvalidRequest
protocol.ErrorCodeUnavailable

// Client IDs
protocol.ClientIDCLI
protocol.ClientIDGateway
protocol.ClientIDMacOS
// ... and more