跳到正文
FunCoding

搜索

搜索文档、文章、Skill 和 MCP

Gateway protocol versioning

Protocol version constants, the N-1 node window, and client defaults

Which protocol versions a client may negotiate, and the constants a reference client ships with.

Versioning

  • PROTOCOL_VERSION, MIN_CLIENT_PROTOCOL_VERSION, MIN_NODE_PROTOCOL_VERSION, and MIN_PROBE_PROTOCOL_VERSION live in packages/gateway-protocol/src/version.ts.
  • Clients send minProtocol + maxProtocol. Operator and UI clients must include the current protocol in that range; current clients and servers run protocol v4.
  • Authenticated clients with both role: "node" and client.mode: "node" may use the N-1 node protocol (v3). Lightweight restart checks use the same N-1 window. Device auth, pairing, scopes, command policy, and exec approvals are unchanged by this compatibility window. Plugin-owned node capabilities and commands are withheld until the node upgrades to the current protocol because their hosted surfaces are not part of the N-1 contract.
  • Schemas and models are generated from TypeBox definitions:
    • pnpm protocol:gen
    • pnpm protocol:gen:swift
    • pnpm 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.

ConstantDefaultSource
PROTOCOL_VERSION4packages/gateway-protocol/src/version.ts
MIN_CLIENT_PROTOCOL_VERSION4packages/gateway-protocol/src/version.ts
MIN_NODE_PROTOCOL_VERSION3packages/gateway-protocol/src/version.ts
MIN_PROBE_PROTOCOL_VERSION3packages/gateway-protocol/src/version.ts
Request timeout (per RPC)30_000 mspackages/gateway-client/src/client.ts (requestTimeoutMs)
Preauth / connect-challenge timeout15_000 mspackages/gateway-client/src/timeouts.ts (OPENCLAW_HANDSHAKE_TIMEOUT_MS env can raise the paired server/client budget)
Initial reconnect backoff1_000 mspackages/gateway-client/src/client.ts (GATEWAY_RECONNECT_POLICY)
Max reconnect backoff30_000 mspackages/gateway-client/src/client.ts (GATEWAY_RECONNECT_POLICY)
Fast-retry clamp after device-token close250 mspackages/gateway-client/src/client.ts
Force-stop grace before terminate()250 msFORCE_STOP_TERMINATE_GRACE_MS
stopAndWait() default timeout1_000 msSTOP_AND_WAIT_TIMEOUT_MS
Default tick interval (pre hello-ok)30_000 mspackages/gateway-client/src/client.ts
Tick-timeout closecode 4000 when silence exceeds tickIntervalMs * 2packages/gateway-client/src/client.ts
MAX_PAYLOAD_BYTES25 * 1024 * 1024 (25 MB)src/gateway/server-constants.ts
Chat attachment ceilingagents.defaults.mediaMaxMb, default 20 MB decodedsrc/gateway/chat-attachment-policy.ts
Chat attachment image ceilingmin(attachment ceiling, 6 MB)src/gateway/chat-attachment-policy.ts, packages/media-core/src/constants.ts

The server advertises the effective policy.tickIntervalMs, policy.maxPayload, policy.maxBufferedBytes, and policy.attachments in hello-ok; clients should honor those values rather than the pre-handshake defaults or hardcoded attachment sizes.

The reference client lets finite requests own their configured deadline when every pending request has one. An expectFinal request without a finite timeoutMs, any request with timeoutMs: null, or a mix of finite and unbounded requests keeps the tick watchdog active. If inbound events and responses remain silent past the tick-timeout threshold, the client closes the socket with code 4000, rejects every pending request, and reconnects. It does not replay rejected requests after reconnecting.

Local state owner routing

Supported local administrative commands discover the process that owns their selected physical state directory before opening mutation-capable state. A live owner receives authenticated RPCs on its recorded local port; a configured remote Gateway or URL override does not redirect these local targets. With no owner, the CLI acquires exclusive lifecycle ownership and retains it until accepted work and cleanup settle. An unreachable, uninspectable, or still-starting owner is not evidence that the directory is offline.

These routes require operator.admin and local-state-owner-routing-v1 in hello-ok.features.capabilities. Method presence alone is insufficient. Except for creation, which is covered by that original capability, each operation also requires its own capability:

Local operationRPCAdditional capability
worktrees createworktrees.createNone
worktrees remove, including lossless and exact-state modesworktrees.removeworktrees-remove-owner-v1
worktrees restore, including exact-state recoveryworktrees.restoreworktrees-restore-owner-v1
worktrees gcworktrees.gcworktrees-gc-owner-v1
worktrees recover-removalworktrees.recoverRemovalworktrees-recover-removal-owner-v1
worktrees retire-snapshotworktrees.retireSnapshotworktrees-retire-snapshot-owner-v1
pairing listchannels.pairing.listchannels-pairing-list-owner-v1
pairing approvechannels.pairing.approvechannels-pairing-approve-owner-v1
Default approvals getexec.approvals.getexec-approvals-get-owner-v1
Default approvals set and allowlist editsexec.approvals.setexec-approvals-set-owner-v1

The CLI sends the discovered expectedOwnerId; the server checks the current owner and requester before effects. Worktree creation also carries expectedRepoIdentity as the captured repository directory's device:inode. These fields identify the intended owner and target; they grant no permission. See worktree request and result contracts, channel pairing, and approval snapshots.

Refusals and uncertain outcomes

The CLI distinguishes OWNER_UNAVAILABLE (ownership cannot be established), OWNER_REFUSED (dispatch did not occur or the server explicitly refused before mutation), and OUTCOME_UNKNOWN (a dispatched operation may have taken effect). A server error with details.mutationAccepted: false identifies the explicit pre-mutation refusal; other errors after dispatch do not prove rollback.

None of these states triggers local fallback or automatic replay. For an older Gateway, missing capability, or authentication refusal, update the Gateway or fix authentication. To work offline, stop the Gateway through its service owner, wait for ownership to release, and rerun the exact command. After an uncertain reply, inspect the target and its operation-specific status or recovery output before deciding whether to retry. The local route allows up to ten minutes for the existing owner operation; a timeout does not transfer ownership.

Mixed versions and retained boundaries

New clients require the complete capability for their operation even if an older Gateway advertises the same method. They never drop a selector or guard to make an old request fit. Existing RPC clients can omit the additive owner fields on methods that predate routing and retain their existing response contracts. The new worktrees.recoverRemoval and worktrees.retireSnapshot methods require expectedOwnerId.

Older CLI and SDK binaries keep their existing direct-write behavior. Routing does not intercept those writes, arbitrary trusted SQL, or another state root sharing an external database. Match CLI, Gateway, and SDK versions; callers must retain their existing foreign-commit freshness checks. Routing covers the named operations above; it does not guarantee that the Gateway is the only SQLite writer.

The following boundaries retain their existing owners and contracts:

BoundaryRetained behavior
Device bootstrapImplicit-loopback device-pairing recovery, QR/setup-code issuance, and SDK device tokens remain with the bootstrap owner so obtaining RPC credentials does not require those credentials first.
Configuration and agent setupAgent identity, bindings, and config editing retain file-authoring/reload behavior. Interactive agent creation and onboarding still stage auth, plugins, workspace, and config locally; their authoritative commit has not moved to this route.
Exec-policy synchronizationexec-policy preset and exec-policy set retain their existing local config/policy owner. Routing the approvals commands does not change these operations or execution authorization.
CredentialsModel-auth keys/order and SDK auth writes, MCP OAuth, secret-store edits, and channel authentication retain their existing locking, invalidation, and lifecycle owners.
Client preferencesThe TUI's remembered session remains a client-preference write, not conversation authority.
Plugin and delivery statePlugin keyed stores and dedupe retain plugin ownership; delivery-queue operations retain outbound-owner admission.
Session and workspace SDKsSession entry, maintenance, catalog/import/link, transcript/callback, and workspace/worktree APIs retain their existing contracts. Session cleanup, agent deletion, and foreign SDK workspace/worktree mutations are not covered by this routing contract.
Raw storage APIsRaw cron replacement and low-level SQLite SDK/native access are not made exclusive by CLI routing. Prefer domain RPCs where available; a worker in a different process is still a foreign writer.
Offline and maintenance ownerssandbox recreate requires exclusive offline ownership. Embedded execution, reset/uninstall, boot admission, migrations, Doctor, and update retain their existing lifecycle owners.

Updates do not require a new routing RPC to install the version that supplies it. The installed updater and candidate Doctor retain their stop, drain, backup, maintenance, and finalization contracts. This routing adds no protocol-version, schema, configuration, retention, or durability change.