Gateway protocol
기준일: 2026-07-26
공식 기준: Gateway protocol
Gateway protocol 문서는 OpenClaw 공식 문서(gateway/protocol)를 한국어로 정리한 가이드입니다. Gateway WebSocket protocol: handshake, frames, versioning 명령·설정 키·코드 예시는 공식 문서를 그대로 보존하며, 해석과 절차 안내는 한국어로 제공합니다. 최종 동작은 설치된 CLI 버전과 공식 원문을 확인하세요.
핵심 요약
Gateway WebSocket protocol: handshake, frames, versioning
한국어 가이드 범위: gateway/protocol 경로의 설정·명령·제약·예시를 학습용으로 재구성합니다.
문서 구성
공식 문서의 주요 섹션은 다음과 같습니다.
- npm packages
- Transport and framing
- Handshake
- Worker role and closed protocol
- Client capabilities
- Node connect example
- Roles and scopes
- Caps/commands/permissions (node)
- Presence
- Node background alive event
- Broadcast event scoping
- RPC method families
- Common event families
- Node helper methods
- Audit ledger RPC
- Task ledger RPCs
- Operator helper methods
- models.list views
- Exec approvals
- Agent delivery fallback
- Versioning
- Client constants
- Auth
- Device identity and pairing
- Device auth migration diagnostics
- TLS and pinning
- Scope
- 관련 문서
상세 내용
본문
The Gateway WS protocol is the single control plane and node transport for OpenClaw. Operator and node clients (CLI, web UI, macOS app, iOS/Android nodes, headless nodes) connect over WebSocket and declare a role and scope at handshake time.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
npm packages
These packages ship with OpenClaw release trains. During the initial rollout, npm may return E404 until the first package-bearing release is published.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
@openclaw/gateway-protocol@openclaw/gateway-client
Transport and framing
handshake, follow hello-ok.policy.maxPayload and hello-ok.policy.maxBufferedBytes. With diagnostics enabled, oversized inbound frames and slow outbound buffers emit payload.large events before the gateway closes or drops the frame. These events carry surface, byte sizes, limits, and a safe reason code, never message bodies, attachment contents, raw frame bytes, tokens, cookies, or secrets.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- WebSocket, text frames, JSON payloads.
- First frame must be a
connectrequest. - Pre-connect frames are capped at 64 KiB (
MAX_PREAUTH_PAYLOAD_BYTES). After - Request:
{type:"req", id, method, params} - Response:
{type:"res", id, ok, payload|error} - Event:
{type:"event", event, payload, seq?, stateVersion?} - Missing scope:
{ code: "MISSING_SCOPE", missingScope, requiredScopes }.
Handshake
server, features, snapshot, policy, and auth are all required by HelloOkSchema (packages/gateway-protocol/src/schema/frames.ts). auth reports the negotiated role/scopes even when no device token is issued (shape above). pluginSurfaceUrls is optional and maps plugin surface names (e.g. canvas) to scoped hosted URLs; it may expire, so nodes call node.pluginSurface.refresh with { "surface": "canvas" } for a fresh entry. The deprecated canvasHostUrl / canvasCapability / node.canvas.capability.refresh path is not supported; use plugin surfaces. The snapshot's optional appliedConfigHash is the resolved source-config revision accepted by the active Gateway runtime. Clients can compare it with config.get.configRevisionHash to determine whether a newer saved config still needs a restart. config.get.hash remains the raw root-file revision used by config write conflict guards.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
{
"type": "event",
"event": "connect.challenge",
"payload": { "nonce": "…", "ts": 1737264000000 }
}
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 4,
"maxProtocol": 4,
"client": {
"id": "cli",
"version": "1.2.3",
"platform": "macos",
"mode": "operator"
},
"role": "operator",
"scopes": ["operator.read", "operator.write"],
"caps": [],
"commands": [],
"permissions": {},
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-cli/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}
{
"type": "res",
"id": "…",
"ok": true,
"payload": {
"type": "hello-ok",
"protocol": 4,
"server": { "version": "…", "connId": "…" },
"features": { "methods": ["…"], "events": ["…"] },
"snapshot": { "…": "…" },
"auth": {
"role": "operator",
"scopes": ["operator.read", "operator.write"]
},
"policy": {
"maxPayload": 26214400,
"maxBufferedBytes": 52428800,
"tickIntervalMs": 15000
}
}
}
{
"auth": {
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.read", "operator.write"]
}
}
Worker role and closed protocol
Cloud workers use a dedicated loopback ingress through the gateway-owned, host-key-pinned SSH tunnel. It accepts only worker identity and never dispatches general auth, node events, operator RPCs, or plugin methods. A strict connect verifies a hash-at-rest, short-lived credential bound to the environment, bundle hash, owner epoch, RPC-set version, expiry, and one nullable session; it separately checks the current version and feature set. Success returns minimal worker-hello-ok; feature negotiation is independent of the general protocol version. Frames stay under 64 KiB, except a negotiated worker.inference.start frame may be up to 25 MiB. The closed allowlist contains worker.heartbeat, worker.transcript.commit, worker.live-event, worker.inference.start, and worker.inference.cancel.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Client capabilities
Operator clients may advertise optional capabilities in connect.params.caps:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
tool-events: accepts structured tool lifecycle events.inline-widgets: can render hosted inline widget tool results.
Node connect example
Nodes declare capability claims at connect time:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
caps: high-level categories such ascamera,canvas,screen,commands: command allowlist for invoke.permissions: granular toggles (e.g.screen.record,camera.capture).
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 4,
"maxProtocol": 4,
"client": {
"id": "ios-node",
"version": "1.2.3",
"platform": "ios",
"mode": "node"
},
"role": "node",
"scopes": [],
"caps": ["camera", "canvas", "screen", "location", "voice"],
"commands": ["camera.snap", "canvas.navigate", "screen.record", "location.get"],
"permissions": { "camera.capture": true, "screen.record": false },
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-ios/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}
Roles and scopes
For the full operator scope model, approval-time checks, and shared-secret semantics, see Operator scopes.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
operator: control-plane client (CLI/UI/automation).node: capability host (camera/screen/canvas/system.run).worker: cloud execution host on the dedicated, closed worker protocol.operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
| Declared commands | Required scopes |
|---|---|
| none | operator.pairing |
| ordinary commands | operator.pairing + operator.write |
includes system.run, system.run.prepare, system.which, browser.proxy, fs.listDir, or system.execApprovals.get/set |
operator.pairing + operator.admin |
Caps/commands/permissions (node)
Nodes declare capability claims at connect time:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
caps: high-level capability categories such ascamera,canvas,screen,commands: command allowlist for invoke.permissions: granular toggles (e.g.screen.record,camera.capture).
Presence
deviceId, roles, and scopes, so UIs can show one row per device even when it connects as both operator and node.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
system-presencereturns entries keyed by device identity, includingnode.listincludes optionallastSeenAtMsandlastSeenReason. Connected
Node background alive event
Nodes call node.event with event: "node.presence.alive" to record that a paired node was alive during a background wake, without marking it connected:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
{
"event": "node.presence.alive",
"payloadJSON": "{\"trigger\":\"silent_push\",\"sentAtMs\":1737264000000,\"displayName\":\"Peter's iPhone\",\"version\":\"2026.4.28\",\"platform\":\"iOS 18.4.0\",\"deviceFamily\":\"iPhone\",\"modelIdentifier\":\"iPhone17,1\",\"pushTransport\":\"relay\"}"
}
{
"ok": true,
"event": "node.presence.alive",
"handled": true,
"reason": "persisted"
}
Broadcast event scoping
Server-pushed broadcast events are scope-gated so pairing-scoped or node-only sessions do not passively receive session content (src/gateway/server-broadcast.ts):
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Chat, agent, and tool-result frames (streamed
agentevents, tool-result - Plugin-defined
plugin.*broadcasts are gated tooperator.writeor - Status/transport events (
heartbeat,presence,tick, connect/disconnect - Unknown broadcast event families are scope-gated by default (fail-closed)
RPC method families
hello-ok.features.methods is a conservative discovery list built from src/gateway/server-methods-list.ts plus loaded plugin/channel method exports — it is not a generated dump of every method, and some methods (for example push.test, web.login.start, web.login.wait, sessions.usage) are intentionally excluded from discovery even though they are real, callable methods. Treat this as feature discovery, not a full enumeration of src/gateway/server-methods/*.ts.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
healthreturns the cached or freshly probed gateway health snapshot.diagnostics.stabilityreturns the recent bounded diagnostic stability recorder: event names, counts, byte sizes, memory readings, queue/session state, channel/plugin names, session ids. No chat text, webhook bodies, tool outputs, raw request/response bodies, tokens, cookies, or secrets. Requiresoperator.read.statusreturns the/status-style gateway summary; sensitive fields only for admin-scoped operator clients.gateway.identity.getreturns the gateway device identity used by relay and pairing flows.system-presencereturns the current presence snapshot for connected operator/node devices.system-eventappends a system event and can update/broadcast presence context.last-heartbeatreturns the latest persisted heartbeat event.set-heartbeatstoggles heartbeat processing on the gateway.gateway.suspend.preparecreates a short cooperative-suspension lease only when tracked Gateway work is idle.gateway.suspend.statuschecks that lease, andgateway.suspend.resumereleases it after thaw or an aborted host operation.models.listreturns the runtime-allowed model catalog. See "models.listviews" below.usage.statusreturns provider usage windows/remaining quota summaries.usage.costreturns aggregated cost usage summaries for a date range. PassagentIdfor one agent, oragentScope: "all"to aggregate configured agents.doctor.memory.statusreturns vector-memory / cached embedding readiness for the active default agent workspace. Pass{ "probe": true }or{ "deep": true }only for an explicit live embedding provider ping. Pass{ "agentId": "agent-id" }to scope Dreaming store stats to one agent workspace; omitting it aggregates configured Dreaming workspaces.doctor.memory.dreamDiary,doctor.memory.backfillDreamDiary,doctor.memory.resetDreamDiary,doctor.memory.resetGroundedShortTerm,doctor.memory.repairDreamingArtifacts, anddoctor.memory.dedupeDreamDiaryaccept optional{ "agentId": "agent-id" }; omitted, they operate on the configured default agent workspace.doctor.memory.remHarnessreturns a bounded, read-only REM harness preview for remote control-plane clients, including workspace paths, memory snippets, rendered grounded markdown, and deep promotion candidates. Requiresoperator.read.sessions.usagereturns per-session usage summaries. PassagentIdfor one agent, oragentScope: "all"to list configured agents together.sessions.usage.timeseriesreturns timeseries usage for one session.sessions.usage.logsreturns usage log entries for one session.channels.statusreturns built-in + bundled channel/plugin status summaries.channels.logoutlogs out a specific channel/account where the channel supports it.web.login.startstarts a QR/web login flow for the current QR-capable web channel provider.web.login.waitwaits for that flow to complete and starts the channel on success.push.testsends a test APNs push to a registered iOS node.voicewake.getreturns the stored wake-word triggers.voicewake.setupdates wake-word triggers and broadcasts the change.
Common event families
events. In protocol v4, delta payloads carry deltaText; message remains the cumulative assistant snapshot. Non-prefix replacements set replace=true and use deltaText as the replacement text.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
chat: UI chat updates such aschat.injectand other transcript-only chatsession.message,session.operation,session.tool: transcript, in-flightsession.approval: sanitized pending and terminal approval truth for ansessions.changed: session index or metadata changed.presence: system presence snapshot updates.tick: periodic keepalive/liveness event.health: gateway health snapshot update.heartbeat: heartbeat event stream update.cron: cron run/job change event.shutdown: gateway shutdown notification.node.pair.requested/node.pair.resolved: node pairing lifecycle.node.invoke.request: node invoke request broadcast.device.pair.requested/device.pair.resolved: paired-device lifecycle.voicewake.changed: wake-word trigger config changed.config.changed: a config write persisted (payload carries the config path,exec.approval.requested/exec.approval.resolved: exec approvalplugin.approval.requested/plugin.approval.resolved: plugin approval
Node helper methods
Nodes may call skills.bins to fetch the current list of skill executables for auto-allow checks.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Audit ledger RPC
audit.activity.list gives operator clients a stable newest-first view of agent run, tool action, and opt-in message lifecycle metadata. It requires operator.read. Queries exclude records older than 30 days, and the shared SQLite ledger is capped at 100,000 records. Expired rows are deleted during Gateway startup, hourly maintenance, and later writes. See Audit history for the data model and privacy semantics.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Params: optional exact
agentId,sessionKey, orrunId; optionalkind - Result:
{ "events": AuditActivityEventV1[], "nextCursor"?: string }. conversationKind:direct,group,channel, orunknown.- Inbound
outcome:completed,skipped, orfailed; optional - Outbound
outcome:sent,suppressed,failed, orunknown; optional deliveryKind:text,media, orother;failureStage:
eventType |
Required fields | Optional fields |
|---|---|---|
agent_run |
agentId, runId; kind: "agent_run" |
sessionKey, sessionId, errorCode |
tool_action |
agentId, runId; kind: "tool_action" |
sessionKey, sessionId, toolCallId, toolName, errorCode |
inbound_message |
direction: "inbound", channel, conversationKind, outcome |
agentId, runId, durationMs, resultCount, identity references, reasonCode, errorCode |
outbound_message |
direction: "outbound", channel, conversationKind, outcome |
agentId, runId, durationMs, resultCount, identity references, reasonCode, deliveryKind, failureStage, errorCode |
| Variant | Terminal mapping |
|---|---|
| Agent run | started has no errorCode; each non-success finished status requires its matching run_* code. |
| Tool action | started and succeeded have no errorCode; each other finished status requires its matching tool_* code. |
| Inbound message | succeeded = completed; blocked = skipped; failed = failed plus message_processing_failed. reasonCode, when present, must belong to that terminal family. |
| Outbound message | succeeded = sent; blocked = suppressed plus reasonCode; failed = failed plus errorCode and failureStage; unknown = unknown plus failureStage. |
Task ledger RPCs
Operator clients inspect and cancel gateway background task records through the task ledger RPCs (packages/gateway-protocol/src/schema/tasks.ts). These return sanitized task summaries, not raw runtime state.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
tasks.listrequiresoperator.read.- Params: optional
status("queued","running","completed", - Result:
{ "tasks": TaskSummary[], "nextCursor"?: string }. tasks.getrequiresoperator.read.- Params:
{ "taskId": string }. - Result:
{ "task": TaskSummary }. - Missing task ids return the gateway not-found error shape.
tasks.cancelrequiresoperator.write.- Params:
{ "taskId": string, "reason"?: string }. - Result:
{ "found": boolean, "cancelled": boolean, "reason"?: string, "task"?: TaskSummary }. foundreports whether the ledger had a matching task.cancelled
Operator helper methods
the primary text command token without the leading /; native and the default both path return provider-aware native names when available.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
commands.list(operator.read) fetches the runtime command inventory foragentIdis optional; omit it to read the default agent workspace.scopecontrols which surface the primarynametargets:textreturnstextAliasescarries exact slash aliases such as/modeland/m.nativeNamecarries the provider-aware native command name when oneprovideris optional and only affects native naming plus native pluginincludeArgs=falseomits serialized argument metadata from the response.tools.catalog(operator.read) fetches the runtime tool catalog for ansource:coreorpluginpluginId: plugin owner whensource="plugin"optional: whether a plugin tool is optionaltools.effective(operator.read) fetches the runtime-effective toolsessionKeyis required.- The gateway derives trusted runtime context from the session server-side
- The response is a session-scoped server-derived projection of the active
tools.effectiveis read-only for MCP: it may project a warm session MCP- Effective tool entries use
source="core",source="plugin", tools.invoke(operator.write) invokes one available tool through thenameis required.args,sessionKey,agentId,confirm, and- If both
sessionKeyandagentIdare present, the resolved session agent - Owner-only core wrappers such as
cron,gateway, andnodesrequire - The response is an SDK-facing envelope with
ok,toolName, optional skills.status(operator.read) fetches the visible skill inventory for anagentIdis optional; omit it to read the default agent workspace.- The response includes eligibility, missing requirements, config checks,
models.list views
models.list accepts an optional view parameter (src/agents/model-catalog-visibility.ts):
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Omitted or
"default": ifagents.defaults.modelPolicy.allowis configured, the "configured": picker-sized behavior. Ifagents.defaults.modelPolicy.allowis"provider-config": source-authoredmodels.providers.*.modelsinventory,"all": full gateway catalog, bypassingagents.defaults.modelPolicy.allow. Use for
Exec approvals
(canonical argv/cwd/rawCommand/session metadata). Requests missing systemRunPlan are rejected.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- When an exec request needs approval, the gateway broadcasts
- Operator clients resolve by calling
exec.approval.resolve(requires - For
host=node,exec.approval.requestmust includesystemRunPlan - After approval, forwarded
node.invoke system.runcalls reuse that - If a caller mutates
command,rawCommand,cwd,agentId, or
Agent delivery fallback
internal-only delivery targets return INVALID_REQUEST.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
agentrequests can includedeliver=trueto request outbound delivery.bestEffortDeliver=false(the default) keeps strict behavior: unresolved orbestEffortDeliver=trueallows fallback to session-only execution when no- Final
agentresults may includeresult.deliveryStatuswhen delivery was
Versioning
MIN_NODE_PROTOCOL_VERSION, and MIN_PROBE_PROTOCOL_VERSION live in packages/gateway-protocol/src/version.ts.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
PROTOCOL_VERSION,MIN_CLIENT_PROTOCOL_VERSION,- Clients send
minProtocol+maxProtocol. Operator and UI clients must - Authenticated clients with both
role: "node"andclient.mode: "node" - Schemas and models are generated from TypeBox definitions:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
Client constants
The reference client implementation lives in packages/gateway-client/src/ (OpenClaw wraps it via the thin src/gateway/client.ts facade). These defaults are stable across protocol v4 and are the expected baseline for third-party clients.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
| Constant | Default | Source |
|---|---|---|
PROTOCOL_VERSION |
4 |
packages/gateway-protocol/src/version.ts |
MIN_CLIENT_PROTOCOL_VERSION |
4 |
packages/gateway-protocol/src/version.ts |
MIN_NODE_PROTOCOL_VERSION |
3 |
packages/gateway-protocol/src/version.ts |
MIN_PROBE_PROTOCOL_VERSION |
3 |
packages/gateway-protocol/src/version.ts |
| Request timeout (per RPC) | 30_000 ms |
packages/gateway-client/src/client.ts (requestTimeoutMs) |
| Preauth / connect-challenge timeout | 15_000 ms |
packages/gateway-client/src/timeouts.ts (OPENCLAW_HANDSHAKE_TIMEOUT_MS env can raise the paired server/client budget) |
| Initial reconnect backoff | 1_000 ms |
packages/gateway-client/src/client.ts (GATEWAY_RECONNECT_POLICY) |
| Max reconnect backoff | 30_000 ms |
packages/gateway-client/src/client.ts (GATEWAY_RECONNECT_POLICY) |
| Fast-retry clamp after device-token close | 250 ms |
packages/gateway-client/src/client.ts |
Force-stop grace before terminate() |
250 ms |
FORCE_STOP_TERMINATE_GRACE_MS |
stopAndWait() default timeout |
1_000 ms |
STOP_AND_WAIT_TIMEOUT_MS |
Default tick interval (pre hello-ok) |
30_000 ms |
packages/gateway-client/src/client.ts |
| Tick-timeout close | code 4000 when silence exceeds tickIntervalMs * 2 |
packages/gateway-client/src/client.ts |
MAX_PAYLOAD_BYTES |
25 * 1024 * 1024 (25 MB) |
src/gateway/server-constants.ts |
Auth
connect.params.auth.password, depending on the configured gateway.auth.mode ("none" | "token" | "password" | "trusted-proxy").
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Shared-secret gateway auth uses
connect.params.auth.tokenor - Identity-bearing modes such as Tailscale Serve (
gateway.auth.allowTailscale: true) - Private-ingress
gateway.auth.mode: "none"skips shared-secret connect auth - After pairing, the gateway issues a device token scoped to the connection
- Reconnecting with that stored device token should also reuse the stored
- Client-side connect auth assembly (
selectConnectAuthin auth.passwordis orthogonal and always forwarded when set.auth.tokenis populated in priority order: explicit shared token first,auth.bootstrapTokenis sent only when none of the above resolved- Auto-promotion of a stored device token on the one-shot
- Built-in setup-code bootstrap returns the primary node
- While a non-baseline setup-code bootstrap waits for approval,
- Persist
hello-ok.auth.deviceTokensonly when the connect used bootstrap - If a client supplies an explicit
deviceTokenor explicitscopes, that - Device tokens can be rotated/revoked via
device.token.rotateand device.token.rotatereturns rotation metadata. It echoes the replacement- Token issuance, rotation, and revocation stay bounded to the approved role
- For paired-device token sessions, device management is self-scoped unless
device.token.rotateanddevice.token.revokealso check the target- Auth failures include
error.details.codeplus recovery hints: error.details.canRetryWithDeviceToken(boolean)error.details.recommendedNextStep: one ofretry_with_device_token,- Client behavior for
AUTH_TOKEN_MISMATCH: - Trusted clients may attempt one bounded retry with a cached per-device
- If that retry fails, stop automatic reconnect loops and surface operator
Device identity and pairing
node). The only device-less operator exceptions are explicit trust paths:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Nodes should include a stable device identity (
device.id) derived from a - Gateways issue tokens per device + role.
- Pairing approvals are required for new device IDs unless local
- Pairing auto-approval is centered on direct local loopback connects.
- OpenClaw also has a narrow backend/container-local self-connect path for
- Same-host tailnet or LAN connects are still treated as remote for pairing
- WS clients normally include
deviceidentity duringconnect(operator + - successful
gateway.auth.mode: "trusted-proxy"operator Control UI auth. - direct-loopback
gateway-clientbackend RPCs on the reserved internal - Omitting device identity has scope consequences. When a device-less
- The reserved direct-loopback
gateway-clientbackend helper path preserves - All connections must sign the server-provided
connect.challengenonce.
Device auth migration diagnostics
For legacy clients that still use pre-challenge signing behavior, connect returns DEVICE_AUTH_* detail codes under error.details.code with a stable error.details.reason.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Always wait for
connect.challenge. - Sign the v2 payload that includes the server nonce.
- Send the same nonce in
connect.params.device.nonce. - Preferred signature payload is
v3 - Legacy
v2signatures remain accepted for compatibility, but paired-device
| Message | details.code | details.reason | Meaning |
|---|---|---|---|
device nonce required |
DEVICE_AUTH_NONCE_REQUIRED |
device-nonce-missing |
Client omitted device.nonce (or sent blank). |
device nonce mismatch |
DEVICE_AUTH_NONCE_MISMATCH |
device-nonce-mismatch |
Client signed with a stale/wrong nonce. |
device signature invalid |
DEVICE_AUTH_SIGNATURE_INVALID |
device-signature |
Signature payload does not match v2 payload. |
device signature expired |
DEVICE_AUTH_SIGNATURE_EXPIRED |
device-signature-stale |
Signed timestamp is outside allowed skew. |
device identity mismatch |
DEVICE_AUTH_DEVICE_ID_MISMATCH |
device-id-mismatch |
device.id does not match public key fingerprint. |
device public key invalid |
DEVICE_AUTH_PUBLIC_KEY_INVALID |
device-public-key |
Public key format/canonicalization failed. |
TLS and pinning
gateway.remote.tlsFingerprint or CLI --tls-fingerprint.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- TLS is supported for WS connections (
gateway.tlsconfig). - Clients may optionally pin the gateway cert fingerprint via
Scope
This protocol exposes the full gateway API: status, channels, models, chat, agent, sessions, nodes, approvals, and more. The exact surface is defined by the TypeBox schemas re-exported from packages/gateway-protocol/src/schema.ts.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
관련 문서
주요 항목:
- Building a Gateway client
- Embedding OpenClaw
- Bridge protocol
- Gateway runbook
실습 체크리스트
- 공식 문서와 로컬 버전을 대조합니다:
https://docs.openclaw.ai/gateway/protocol - 관련 CLI는
openclaw --help및 하위 명령--help로 옵션을 확인합니다. - 설정 변경 시
openclaw config/openclaw doctor로 유효성을 검사합니다. - Gateway·채널·플러그인 변경 후에는 필요 시 Gateway를 재시작합니다.
자주 쓰는 명령·설정 예시
{
"type": "event",
"event": "connect.challenge",
"payload": { "nonce": "…", "ts": 1737264000000 }
}
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 4,
"maxProtocol": 4,
"client": {
"id": "cli",
"version": "1.2.3",
"platform": "macos",
"mode": "operator"
},
"role": "operator",
"scopes": ["operator.read", "operator.write"],
"caps": [],
"commands": [],
"permissions": {},
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-cli/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}
{
"type": "res",
"id": "…",
"ok": true,
"payload": {
"type": "hello-ok",
"protocol": 4,
"server": { "version": "…", "connId": "…" },
"features": { "methods": ["…"], "events": ["…"] },
"snapshot": { "…": "…" },
"auth": {
"role": "operator",
"scopes": ["operator.read", "operator.write"]
},
"policy": {
"maxPayload": 26214400,
"maxBufferedBytes": 52428800,
"tickIntervalMs": 15000
}
}
}
{
"auth": {
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.read", "operator.write"]
}
}
{
"auth": {
"deviceToken": "…",
"role": "node",
"scopes": [],
"deviceTokens": [
{
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"]
}
]
}
}
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 4,
"maxProtocol": 4,
"client": {
"id": "ios-node",
"version": "1.2.3",
"platform": "ios",
"mode": "node"
},
"role": "node",
"scopes": [],
"caps": ["camera", "canvas", "screen", "location", "voice"],
"commands": ["camera.snap", "canvas.navigate", "screen.record", "location.get"],
"permissions": { "camera.capture": true, "screen.record": false },
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-ios/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}
관련 링크
- 공식 원문: gateway/protocol
- OpenClaw 문서 홈
이 가이드는 공식 문서를 한국어 학습용으로 재구성한 것입니다. 옵션 기본값·플래그 이름은 설치 버전에 따라 달라질 수 있습니다.