docs(gateway): add client-building and embedding guides (#111726)

* docs(gateway): add client-building and embedding guides

* docs(gateway): harden package rollout guidance
This commit is contained in:
Peter Steinberger
2026-07-20 02:12:52 -07:00
committed by GitHub
parent fd081d6521
commit 9056c43368
7 changed files with 436 additions and 15 deletions
+8
View File
@@ -131,6 +131,14 @@
"source": "Gateway RPC reference",
"target": "Gateway RPC 参考"
},
{
"source": "Building a Gateway client",
"target": "构建 Gateway 客户端"
},
{
"source": "Embedding OpenClaw",
"target": "嵌入 OpenClaw"
},
{
"source": "Secure file operations",
"target": "安全文件操作"
+2
View File
@@ -1686,6 +1686,8 @@
"group": "Protocols and APIs",
"pages": [
"gateway/protocol",
"gateway/clients",
"gateway/embedding",
"gateway/bridge-protocol",
"gateway/openai-http-api",
"gateway/openresponses-http-api",
+28
View File
@@ -3247,6 +3247,20 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H2: Troubleshooting
- H2: Related
## gateway/clients.md
- Route: /gateway/clients
- Headings:
- H2: Install the packages
- H2: Choose scopes and pair the device
- H2: Advertise client capabilities
- H2: Recover state after reconnect
- H2: Use history metadata and stable anchors
- H2: Subscribe instead of polling usage
- H2: Backfill exec approvals
- H2: Track protocol versions
- H2: Related
## gateway/cloud-workers.md
- Route: /gateway/cloud-workers
@@ -3496,6 +3510,19 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H2: Detailed behavior and rationale
- H2: Related
## gateway/embedding.md
- Route: /gateway/embedding
- Headings:
- H2: Start the child with an embedding preset
- H3: Electron shell snapshot warning
- H2: Handle invalid config by exit code
- H2: Wait for protocol readiness
- H2: Interpret restart and shutdown
- H2: Use RPC instead of state files
- H2: Install; do not flatten
- H2: Related
## gateway/external-apps.md
- Route: /gateway/external-apps
@@ -3793,6 +3820,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- Route: /gateway/protocol
- Headings:
- H2: npm packages
- H2: Transport and framing
- H2: Handshake
- H3: Worker role and closed protocol
+197
View File
@@ -0,0 +1,197 @@
---
summary: "Build a third-party operator or WebChat client for the Gateway WebSocket protocol"
read_when:
- Building an operator, dashboard, or WebChat client outside the OpenClaw repository
- Implementing Gateway reconnect, history, approvals, or device pairing
- Updating a third-party client for a new Gateway wire version
title: "Building a Gateway client"
---
Use the published Gateway packages to build operator dashboards, WebChat clients,
and other third-party applications. This guide covers the client lifecycle around
the wire contract: authentication, capabilities, reconnect recovery, history,
subscriptions, and version upgrades.
For frame shapes, the handshake, errors, and the complete method surface, read the
[Gateway protocol specification](https://docs.openclaw.ai/gateway/protocol).
## Install the packages
```bash
npm install @openclaw/gateway-client @openclaw/gateway-protocol
```
<Note>
These packages ship with OpenClaw release trains. During the initial rollout, npm
may return `E404` until the first package-bearing OpenClaw release is published;
install them only after the registry pages below resolve.
</Note>
- [`@openclaw/gateway-protocol`](https://www.npmjs.com/package/@openclaw/gateway-protocol)
provides schemas, runtime validators, TypeScript types, client identity and
capability registries, structured error readers, and protocol version constants.
Its npm tarball also includes the generated
[`protocol.schema.json`](https://unpkg.com/@openclaw/gateway-protocol/protocol.schema.json)
machine-readable contract.
- [`@openclaw/gateway-client`](https://www.npmjs.com/package/@openclaw/gateway-client)
is the reference connection implementation. Import the package root for the Node
client and `@openclaw/gateway-client/browser` for the browser-safe protocol,
device-auth, and reconnect helpers.
The Node entry owns its WebSocket transport. A browser host supplies a WebSocket
adapter plus persistent storage and signing callbacks for the device identity and
device token.
## Choose scopes and pair the device
A full interactive chat client that also renders approval prompts should request
`role: "operator"` with these scopes:
| Scope | Use it for |
| -------------------- | ----------------------------------------------------------------------------------------- |
| `operator.read` | `chat.history`, `sessions.list`, `sessions.subscribe`, model status, and read-only events |
| `operator.write` | `chat.send` and ordinary session mutations |
| `operator.approvals` | Listing, displaying, and resolving exec or plugin approvals |
Add `operator.questions` only if the client handles interactive questions,
`operator.pairing` only if it manages paired devices or nodes, and
`operator.admin` only for administrative operations such as `config.patch`.
The [operator scopes reference](https://docs.openclaw.ai/gateway/operator-scopes)
defines the complete method and approval-time rules.
Do not create a per-client bearer token by hand-editing `openclaw.json`. Configure
the Gateway's shared bootstrap authentication with `openclaw configure --section
gateway` or the `openclaw onboard --gateway-auth ...` options, then let device
pairing mint the client token:
1. Persist an Ed25519 device identity in the client.
2. Wait for `connect.challenge`, sign the challenge-bound device payload, and send
`connect` with the requested operator role, scopes, and the shared Gateway token
or password for bootstrap authentication.
3. If the Gateway returns structured `PAIRING_REQUIRED` details, show the request
ID and pause or retry according to `error.details.recommendedNextStep`.
4. On the Gateway host, review the request with `openclaw devices list`, then
approve that exact current request with `openclaw devices approve <requestId>`.
5. Reconnect and persist `hello-ok.auth.deviceToken` with the negotiated role and
scopes. Use that device token for later connections.
Scope or role upgrades create a new pending pairing request. Token rotation cannot
expand the approved pairing contract. See the
[Devices CLI](https://docs.openclaw.ai/cli/devices) for approval, rotation, and
revocation commands.
## Advertise client capabilities
`connect.params.caps` describes optional behavior the client can consume. It does
not grant authorization. Import names from `GATEWAY_CLIENT_CAPS` instead of
duplicating string literals:
```ts
import { GATEWAY_CLIENT_CAPS } from "@openclaw/gateway-protocol/client-info";
const caps = [GATEWAY_CLIENT_CAPS.TOOL_EVENTS];
```
The current registry contains `approvals`, `exec-approvals`, `inline-widgets`,
`run-tool-bindings`, `session-scoped-events`, `plugin-approvals`,
`task-suggestions`, `terminal-offset-seq`, `tool-events`, and `ui-commands`.
Advertise only capabilities the client actually implements.
<Warning>
`tool-events` gates live tool-execution streaming. The Gateway registers only
connections that advertise this capability as recipients for a run's structured
tool events. Without it, the connection receives no live tool events and the
handshake does not report an error.
</Warning>
Capability-gated agent tools are a separate use of the same declaration. If an
agent tool requires a client capability, the Gateway omits that tool unless the
originating client advertised every required capability.
## Recover state after reconnect
Treat every successful reconnect as a new projection over durable history and
current in-memory run state:
1. Re-establish `sessions.subscribe` and the selected session's
`sessions.messages.subscribe` subscription.
2. Call `chat.history` for the selected `sessionKey` and replace local persisted
rows with the returned `messages` projection.
3. If `inFlightRun` is present, adopt its `runId`, buffered `text`, and optional
`plan`. Adopt the run even when `text` is empty.
4. Read `sessionInfo.hasActiveRun` and `sessionInfo.activeRunIds`. Prefer exact
membership in `activeRunIds` when deciding whether a retained run still owns
the streaming UI. A true `hasActiveRun` with no listed ID can represent another
active runtime projection.
5. Reconcile subsequent `agent` events by `payload.runId` and `payload.seq`.
Maintain the highest accepted sequence independently for each run, ignore an
already-seen or lower sequence, and treat a forward gap as a reason to reload
authoritative history.
The outer event frame also has an optional `seq`, which orders events on the
current WebSocket connection. It resets with a new connection. The `seq` inside
an `agent` event payload is assigned per run and orders that run's lifecycle,
assistant, plan, tool, and other stream events.
## Use history metadata and stable anchors
Rows returned by `chat.history` can carry an `__openclaw` metadata envelope:
- `id` is the transcript entry identity. Use it for anchored history requests,
but not as a unique display-row key.
- `seq` is the positive transcript-record sequence. One stored record can project
into more than one display row, so keep siblings with the same `id` and sequence
together.
- `kind` identifies synthetic rows. A compaction boundary uses
`kind: "compaction"` and may include `tokensBefore` and `tokensAfter` when a
matching checkpoint recorded those metrics.
Page backward with the response's `hasMore` and `nextOffset` values. Numeric
offsets describe the current transcript projection, so do not persist them as
long-lived bookmarks across reset or compaction. Persist `__openclaw.id` instead.
To restore around a known row, call `chat.history` with `messageId` and the
`sessionId` that returned it. The Gateway can resolve that anchor from reset
archive history; anchored responses intentionally omit numeric paging metadata.
## Subscribe instead of polling usage
Load the initial catalog with `sessions.list`, then call `sessions.subscribe` once
per connection. Merge `sessions.changed` events by `sessionKey`. Session change
payloads can carry live `inputTokens`, `outputTokens`, `totalTokens`,
`totalTokensFresh`, `contextTokens`, `estimatedCostUsd`, response-usage settings,
and active-run state.
Some change notifications are only invalidation signals. If an event omits the
row fields your view needs, refresh `sessions.list`. Do not poll `usage.cost` or
`sessions.usage` to keep a live session list current; reserve those methods for
on-demand aggregate or detailed reports.
## Backfill exec approvals
A client with `operator.approvals` should install its event listener as soon as
`hello-ok` completes, then call `exec.approval.list` to backfill requests that
predate the connection. Reconcile the list and live
`exec.approval.requested` / `exec.approval.resolved` events by approval ID so a
transition racing the list request is neither lost nor resurrected.
## Track protocol versions
The current wire version is `4`. General operator and WebChat clients must
negotiate the exact current version with `minProtocol: 4` and `maxProtocol: 4`.
Only authenticated node clients and lightweight probes have the N-1 acceptance
window, currently protocol `3` through `4`.
Protocol changes are additive first. `protocol.schema.json` includes `since`
release-vintage metadata and required scope metadata for core methods, but a wire
version bump is still an explicit breaking event for third-party clients. Pin the
package versions you test, upgrade the client and Gateway together when the wire
version changes, and review the
[OpenClaw changelog](https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md)
before each upgrade.
## Related
- [Gateway protocol](https://docs.openclaw.ai/gateway/protocol)
- [Embedding OpenClaw](https://docs.openclaw.ai/gateway/embedding)
- [Gateway RPC reference](https://docs.openclaw.ai/reference/rpc)
- [Gateway integrations for external apps](https://docs.openclaw.ai/gateway/external-apps)
+161
View File
@@ -0,0 +1,161 @@
---
summary: "Supervise the OpenClaw Gateway as a child process from Electron or another host app"
read_when:
- Embedding OpenClaw in a desktop or server application
- Supervising the Gateway as a child process
- Handling Gateway readiness, restart, shutdown, or invalid config without scraping logs
title: "Embedding OpenClaw"
---
An embedding host should supervise the installed `openclaw` executable, use the
Gateway WebSocket protocol as its control plane, and treat the child process as a
replaceable runtime. This keeps process ownership, readiness, failure recovery,
and upgrades explicit without depending on OpenClaw's private state layout.
For client authentication and reconnect state, read
[Building a Gateway client](https://docs.openclaw.ai/gateway/clients).
## Start the child with an embedding preset
Use a real `node_modules` installation and spawn the package executable. A useful
baseline for a host that owns discovery, restart, and channel lifecycle is:
```ts
import { spawn } from "node:child_process";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
// Supply an absolute path to a real Node runtime managed by the host application.
declare const hostNodeExecutable: string;
const packageEntry = fileURLToPath(import.meta.resolve("openclaw"));
const openclawEntry = resolve(dirname(packageEntry), "..", "openclaw.mjs");
const gateway = spawn(hostNodeExecutable, [openclawEntry, "gateway", "--allow-unconfigured"], {
env: {
...process.env,
OPENCLAW_DISABLE_BONJOUR: "1",
OPENCLAW_EXEC_SHELL_SNAPSHOT: "0",
OPENCLAW_NO_RESPAWN: "1",
OPENCLAW_SKIP_CHANNELS: "1",
},
stdio: ["ignore", "inherit", "inherit"],
});
```
Resolve OpenClaw through the installed package as shown; do not assume that a
project-local `openclaw` binary is on the host process's `PATH`. The example
inherits output so the child cannot block on full stdout or stderr pipes. If the
host captures those streams instead, attach consumers immediately after spawning.
| Setting | Embedding effect |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `OPENCLAW_DISABLE_BONJOUR=1` | Disables Gateway-owned LAN multicast advertising when the host owns discovery. |
| `OPENCLAW_NO_RESPAWN=1` | In an unmanaged embedding child, prevents OpenClaw from handing an update restart to a detached child. Routine restarts remain in process, so the host keeps ownership of the tracked PID. |
| `OPENCLAW_EXEC_SHELL_SNAPSHOT=0` | Disables login-shell snapshot capture for host exec commands. |
| `OPENCLAW_SKIP_CHANNELS=1` | Skips channel startup and reload. Set it only when the embedding app wants a control-plane or WebChat-only Gateway. |
`--allow-unconfigured` bypasses only the `gateway.mode=local` startup guard. It
does not write configuration or repair an invalid file. Omit it when the embedding
app provisions a normal local configuration through onboarding, the config CLI,
or Gateway RPC.
### Electron shell snapshot warning
Shell snapshot capture runs `process.execPath -e <script>` from a login shell. In
a normal Node process, `process.execPath` is the Node executable. Under Electron,
it is the Electron binary, which can interpret the invocation as an application
launch and show an "Unable to find Electron app" popup. Set
`OPENCLAW_EXEC_SHELL_SNAPSHOT=0` in the Gateway child's environment, not only in
the renderer process. For the same reason, `hostNodeExecutable` must point to a
real Node runtime rather than Electron's `process.execPath`.
## Handle invalid config by exit code
Gateway startup uses exit code `78` (`EX_CONFIG`) for configuration-class startup
failures, including an invalid config. Branch on the exit code instead of scraping
human-readable stderr:
1. Run `openclaw doctor --fix --yes --non-interactive` against the same config and
state environment as the Gateway child.
2. Retry Gateway startup once after doctor exits successfully.
3. If the child exits `78` again, stop the repair loop and surface the config
failure to the user.
Keep stderr for diagnostics, but do not make lifecycle decisions from its wording.
After a successful startup, an invalid live config edit is less destructive. The
config watcher logs that reload was skipped and continues serving the last accepted
in-memory config. Repair the file, then let the watcher accept the next valid
snapshot.
## Wait for protocol readiness
Use WebSocket signals instead of a log substring:
1. Open the Gateway WebSocket.
2. Wait for the `connect.challenge` event. It proves that the listener accepted the
WebSocket and the challenge handshake can begin.
3. Send `connect` with the challenge-bound device signature.
4. Treat `hello-ok` as application readiness for authenticated RPC.
The challenge is deliberately earlier than full initialization. If startup
sidecars are still pending, `connect` returns a retryable `UNAVAILABLE` error with
`details.reason: "startup-sidecars"`, a bounded `retryAfterMs`, and then closes
with code `1013` and reason `gateway starting`. Use
`resolveGatewayStartupRetryAfterMs` from
`@openclaw/gateway-protocol/startup-unavailable` or the reference client's built-in
policy, then reconnect.
## Interpret restart and shutdown
Before an orderly close, the Gateway broadcasts a `shutdown` event with `reason`
and `restartExpectedMs`. A non-null `restartExpectedMs` means an in-process or
supervised restart is expected; `null` means a terminal shutdown.
The subsequent WebSocket close code is `1012` for both cases. The ordinary client
close reason is also `service restart` in both cases, so neither the close code nor
the reason distinguishes restart from shutdown. Preserve the preceding `shutdown`
payload when it arrives, and combine it with the host's own stop intent and the
child exit status. If the connection disappears without the event, use normal
bounded reconnect and child-supervision policy.
## Use RPC instead of state files
Keep the Gateway as the only owner of OpenClaw state. Common embedding operations
already have RPC methods:
| Task | RPC methods |
| ----------------------------- | ---------------------------------------------------- |
| Session catalog and lifecycle | `sessions.list`, `sessions.patch`, `sessions.delete` |
| Transcript display | `chat.history` |
| Cost and usage reports | `usage.cost`, `sessions.usage` |
| Model credential status | `models.authStatus` |
| Configuration | `config.get`, `config.patch` |
`config.get` redacts sensitive values and SecretRef identifiers before returning
the snapshot. Write methods also return redacted config. A client must treat the
redaction sentinel as opaque and use the documented config write contract; it
must never expect the Gateway to return plaintext secrets.
Do not read or mutate files, SQLite tables, transcript files, or cache directories
under `~/.openclaw` to implement app features. Those layouts are private runtime
implementation details and can move or change without protocol compatibility.
## Install; do not flatten
The root `openclaw` package is not a single-file vendoring target. Bundled runtime
files under `dist/extensions` retain bare self-imports such as
`openclaw/plugin-sdk/*`, while the npm package intentionally excludes
per-extension `node_modules` trees.
Install OpenClaw through npm, pnpm, or another normal Node package installation so
Node can resolve the package exports and root dependency tree. Spawn the installed
`openclaw` executable. Do not copy only `dist`, flatten the package into an app
bundle, or vendor selected extension files.
## Related
- [Building a Gateway client](https://docs.openclaw.ai/gateway/clients)
- [Gateway protocol](https://docs.openclaw.ai/gateway/protocol)
- [Gateway CLI](https://docs.openclaw.ai/cli/gateway)
- [Gateway integrations for external apps](https://docs.openclaw.ai/gateway/external-apps)
+19 -15
View File
@@ -14,11 +14,15 @@ transport plus RPC methods. Use it when a script, dashboard, CI job, IDE
extension, or another process wants to start agent runs, stream events, wait
for results, cancel work, or inspect Gateway resources.
<Warning>
There is no public npm client package yet. Do not add OpenClaw client package
names as application dependencies until release notes announce a published
package and this page includes install instructions.
</Warning>
<Note>
For npm packages, device pairing, reconnect recovery, history, subscriptions,
and approvals, start with
[Building a Gateway client](https://docs.openclaw.ai/gateway/clients). If your
app supervises the Gateway as a child process, also read
[Embedding OpenClaw](https://docs.openclaw.ai/gateway/embedding). During the
initial package rollout, npm may return `E404` until the first package-bearing
OpenClaw release is published.
</Note>
<Note>
This page is for code outside the OpenClaw process. Plugin code that runs
@@ -27,16 +31,14 @@ for results, cancel work, or inspect Gateway resources.
## What is available today
| Surface | Status | Use it for |
| --------------------------------------- | ------ | --------------------------------------------------------------------------------------------- |
| [Gateway protocol](/gateway/protocol) | Ready | WebSocket transport, connect handshake, auth scopes, protocol versioning, and events. |
| [Gateway RPC reference](/reference/rpc) | Ready | Current Gateway methods for agents, sessions, tasks, models, tools, artifacts, and approvals. |
| [`openclaw agent`](/cli/agent) | Ready | One-shot script integration when shelling out to the CLI is enough. |
| [`openclaw message`](/cli/message) | Ready | Sending messages or channel actions from scripts. |
A future client library package is in progress internally, but it is not a
public install surface yet. Treat it as preview implementation detail until a
release announces a published, versioned package.
| Surface | Status | Use it for |
| ---------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------- |
| [Gateway client guide](https://docs.openclaw.ai/gateway/clients) | Release train | npm packages, auth, reconnect, history, events, approvals, and version policy. |
| [Embedding guide](https://docs.openclaw.ai/gateway/embedding) | Release train | Child-process environment, readiness, lifecycle, recovery, RPC ownership, and packaging. |
| [Gateway protocol](/gateway/protocol) | Ready | WebSocket transport, connect handshake, auth scopes, protocol versioning, and events. |
| [Gateway RPC reference](/reference/rpc) | Ready | Current Gateway methods for agents, sessions, tasks, models, tools, artifacts, and approvals. |
| [`openclaw agent`](/cli/agent) | Ready | One-shot script integration when shelling out to the CLI is enough. |
| [`openclaw message`](/cli/message) | Ready | Sending messages or channel actions from scripts. |
## Recommended path
@@ -176,6 +178,8 @@ plugins loaded by OpenClaw.
## Related
- [Building a Gateway client](https://docs.openclaw.ai/gateway/clients)
- [Embedding OpenClaw](https://docs.openclaw.ai/gateway/embedding)
- [Gateway protocol](/gateway/protocol)
- [Gateway RPC reference](/reference/rpc)
- [CLI agent command](/cli/agent)
+21
View File
@@ -12,6 +12,25 @@ 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.
## 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.
- [`@openclaw/gateway-protocol`](https://www.npmjs.com/package/@openclaw/gateway-protocol)
publishes the schemas, validators, TypeScript types, lightweight frame and error
helpers, and version constants. Its tarball includes the generated
[`protocol.schema.json`](https://unpkg.com/@openclaw/gateway-protocol/protocol.schema.json)
machine-readable contract.
- [`@openclaw/gateway-client`](https://www.npmjs.com/package/@openclaw/gateway-client)
publishes the reference Node client and a browser-safe entry at
`@openclaw/gateway-client/browser`.
For application lifecycle guidance, see
[Building a Gateway client](https://docs.openclaw.ai/gateway/clients). For apps
that supervise the Gateway as a child process, see
[Embedding OpenClaw](https://docs.openclaw.ai/gateway/embedding).
## Transport and framing
- WebSocket, text frames, JSON payloads.
@@ -1147,5 +1166,7 @@ the TypeBox schemas re-exported from `packages/gateway-protocol/src/schema.ts`.
## Related
- [Building a Gateway client](https://docs.openclaw.ai/gateway/clients)
- [Embedding OpenClaw](https://docs.openclaw.ai/gateway/embedding)
- [Bridge protocol](/gateway/bridge-protocol)
- [Gateway runbook](/gateway)