Operator Scopes for Gateway Clients
Learn how operator scopes control what Gateway clients can do after authentication. Essential for operators managing control-plane and node roles.
Read this when
- Debugging missing operator scope errors
- Reviewing device or node pairing approvals
- Adding or classifying Gateway RPC methods
Operator scopes determine what a Gateway client is permitted to do once authentication succeeds. They act as a control-plane safeguard within a single trusted Gateway operator domain, not as defense against hostile multi-tenant environments. To achieve strong isolation among users, teams, or automated agents, deploy separate Gateways under distinct OS accounts or on separate hosts.
See also: Security, Gateway protocol, Gateway pairing, Devices CLI.
Roles
A Gateway WebSocket client always attaches with exactly one role:
operator: control-plane clients, including the CLI, Control UI, automation scripts, and trusted auxiliary processes.node: capability hosts (macOS, iOS, Android, headless) that surface commands vianode.invoke.
The operator role is mandatory for Operator RPC methods; methods originating from nodes demand the node role instead.
Scope levels
| Scope | Meaning |
|---|---|
operator.read | Non-mutating operations only: status queries, listing, catalog access, log retrieval, session reads, stored audit and execution-identity diagnostics, plus similar read-only calls. |
operator.write | Mutating operator actions: dispatching messages, invoking tools, adjusting talk/voice preferences, relaying node commands. Also covers everything in operator.read. |
operator.admin | Full administrative control. Grants every operator.* scope. Mandatory for configuration changes, updates, native hooks, reserved namespaces, and approvals that carry elevated risk. |
operator.pairing | Managing device and node pairing: listing, approving, rejecting, removing, rotating, and revoking credentials. |
operator.approvals | APIs for approving exec requests and plugins. |
operator.questions | Handling interactive questions: listing, reading, answering, and resolving them. |
operator.talk | Creating, directing, and terminating Talk sessions without needing broad Gateway write permissions. operator.write also covers this scope. |
operator.talk.secrets | Viewing Talk configuration, including embedded secrets. |
Any future operator.* scope not yet defined requires an exact match unless the requester already possesses operator.admin.
Identity scope grants
gateway.auth.identityScopes assigns operator scopes to verified user
identities coming from trusted-proxy authentication or Tailscale WhoIs:
{
gateway: {
auth: {
identityScopes: {
"admin@example.com": ["operator.admin"],
"operator@example.com": ["operator.read", "operator.write"],
},
},
},
}
The key corresponds to the verified proxy identity or the Tailscale WhoIs login. Email-based keys are matched without case sensitivity; non-email identities require an exact match. Configuration validation refuses any scope name that falls outside the closed set listed above.
Connection authority gets resolved in this sequence:
- For Control UI connections through a trusted proxy,
x-openclaw-scopesfirst limits device enrollment or upgrade requests. Device authorization then fixes the persistent scopes; a session without a device contributes no self-declared scopes. - OpenClaw merges a matching server-side identity grant into those scopes.
- OpenClaw applies
x-openclaw-scopesto the combined result as the session cap. An absent header means no cap; a header that exists but is empty yields no scopes.
The outcome drives both hello.auth.scopes and Gateway method
authorization. Identity grants last only for the session: they neither create nor alter
pairing records, nor do they request a device scope upgrade. Token, password, and no-auth
connections carry no verified identity and therefore receive no grant.
Identity grants apply exclusively to operator-role connections; node-role connections never receive them.
Method scope is only the first gate
Every Gateway RPC carries a least-privilege method scope that governs whether a request reaches its handler. Methods that are params-aware compute that scope before dispatch, so authorization failures always produce one canonical structured response:
- For standard turns,
agentrequiresoperator.write, whileoperator.adminis needed for/newor/resetsession lifecycle commands. - Ordinary relay commands demand
operator.writefornode.invoke, butoperator.adminbecomes necessary whenbrowser.proxy,browser.proxy.upload.v1,fs.listDir, orterminal.uploadare relayed to a node. - The top-level
fs.listDirRPC depends onoperator.writefor Gateway-host requests and onoperator.adminwhennodeIdis directed at a node. Its handler restricts non-admin Gateway-host browsing to the agent workspaces that are configured. - For typical creation,
sessions.createrequiresoperator.write, including aprojectId, andoperator.adminapplies to incognito sessions or anyexecNoderequest. When the caller is not an admin, the handler confinescwdto configured agent workspaces; combiningprojectIdwithcwdorexecNodeis not allowed. environments.listcalls foroperator.read. Before schema validation, session placement methods determine their scope from the requested target:sessions.dispatchneedsoperator.writefordeviceIdandoperator.adminforprofileIdor a target-lesscloudWorkers.projectProfileslookup;sessions.moverequiresoperator.writefor Gateway or device targets andoperator.adminfor profile targets;abandonSource: truestaysoperator.write, but it only passes schema validation with a Gateway target and runtime validation for an exact offline device source;sessions.reclaimremainsoperator.write. Malformed dispatch parameters or a malformed move target triggeroperator.write, letting the handler return the exact schema error. All three methods keep session ownership, participation, and commit-time revalidation fences. Starting, stopping, or moving a session cannot be done withoperator.readalone. Cloud profile allocation and mutation, pairing and Connect machine, rawenvironments.createorenvironments.destroy, incognito sessions, directexecNodeexecution, and arbitrary host or node paths all stayoperator.admin.worktrees.branchesrequiresoperator.write. Its handler limits non-admin callers to paths within workspaces or roots of registered projects; other host paths needoperator.admin.talk.configrequiresoperator.read;includeSecrets: truealso requiresoperator.talk.secrets.talk.client.*,talk.session.*,talk.speak, andtalk.modeeach requireoperator.talk(or the compatible broaderoperator.write).sessions.patchrequiresoperator.writefor session organization fields and the per-sessionmodeloverride. Additional runtime overrides, such as thinking, fast, verbose, trace, and reasoning levels, demandoperator.admin. Setting a chosen model as the configured agent default is likewise restricted to admins.
Project RPCs are governed by these scopes:
| Method | Required scope and additional gate |
|---|---|
projects.list | operator.read; only callers meeting operator.write get repoRoot and originUrl. |
projects.add | operator.write plus the controlPlaneWrite method flag. |
projects.register, projects.remove | operator.admin. |
projects.searchRemote | operator.read. |
Certain handlers then impose tighter checks based on the specific item being approved or modified:
- With
operator.pairing,device.pair.approveis accessible, but approving an operator device can only create or preserve scopes the caller already possesses. node.pair.approveis reachable viaoperator.pairing, and then derives additional approval scopes from the command list declared by the pending node.chat.sendis a write-scoped method, yet the/config setand/config unsetchat commands requireoperator.adminin addition, irrespective of the caller's chat-send scope.
This arrangement lets lower-scope operators perform low-risk pairing actions without making all pairing approval admin-only.
Session mutation RPCs are authorized by their negotiated operator scopes, independent of the connecting client's client.id or client.mode. Client identity can still influence connection and device-auth policy, but it neither grants nor removes session mutation authority.
audit.run.inspect deliberately employs operator.read. Any client holding that scope in a Gateway operator domain may receive the retained execution-identity context, including bounded pseudonymized references and secret-redacted display labels. operator.read is not a per-user or hostile multi-tenant privacy boundary. Operators needing to keep this data separate must use separate Gateway trust domains.
Device pairing approvals
Device pairing records serve as the durable source of approved roles and scopes. An already-paired device does not gain broader access silently: a reconnect requesting a broader role or broader scopes generates a new pending upgrade request.
A connected limited Control UI can file that same pending request via its Request admin banner without attempting a broader reconnect. The banner can collapse into a persistent Limited access chip that reopens the action. The request is tied to the signed device identity on the live connection. Approval still originates from device.pair.approve and therefore requires operator.pairing plus authority for every requested scope. After approval rotates the operator token, the Gateway returns the new token only to that device's live waiter; the browser stores it before reconnecting. Canceling the wait or disconnecting before approval falls back to the ordinary pairing repair flow on the next connection.
The explicit exception is the administrator-capable Control UI owner profile issued directly on the Gateway host by openclaw dashboard or graphical onboarding. Its short-lived, single-use bootstrap can approve the exact closed scope set for a fresh browser or upgrade an existing limited credential only when it binds to that same signed browser keypair. Generic Control UI and Telegram handoffs, mobile setup profiles, shared credentials, locality, and caller-selected scopes do not receive this exception.
Approving a device request:
- A request with no operator role does not need operator scope approval.
- A request for a non-operator device role (for example
node) requiresoperator.admin, even thoughdevice.pair.approveitself only needsoperator.pairing. - A request for
operator.read,operator.write,operator.approvals,operator.questions,operator.pairing,operator.talk, oroperator.talk.secretsrequires the caller to already hold that scope, oroperator.admin. - A request for
operator.adminrequiresoperator.admin. - A repair request with no explicit scopes can inherit the existing operator token's scopes; if that token is admin-scoped, approval still requires
operator.admin.
Non-admin shared-secret and trusted-proxy sessions can only approve operator-device requests within their own declared operator scopes; approving non-operator roles is admin-only even when those sessions can otherwise use operator.pairing.
For paired-device token sessions, management is self-scoped unless the caller has operator.admin: a non-admin caller sees only its own pairing entries, and can approve, reject, rotate, revoke, or remove only its own device entry.
Node pairing approvals
node.pair.* capability approvals are stored on the paired device record in the shared SQLite pairing store. Gateways migrate any remaining entries from the retired standalone nodes/paired.json store into those records once at startup. See Gateway pairing for details.
node.pair.approve derives extra required scopes from the pending request's command list:
| Declared commands | Required scopes |
|---|---|
| none | operator.pairing |
| ordinary node commands | operator.pairing + operator.write |
system.run, system.run.prepare, system.which, browser.proxy, browser.proxy.upload.v1, fs.listDir, or system.execApprovals.get/set | operator.pairing + operator.admin |
In this context, fs.listDir refers to the node command declared for relay via node.invoke,
distinct from the top-level Gateway RPC mentioned earlier.
When a node declaration is approved, its command surface gets recorded. For computer.act,
the node only exposes that surface once Computer Control is enabled locally;
after the pairing update receives approval, calling it through node.invoke demands
write scope, though admin scope is not needed for each action. Commands that are
dangerous or privacy-heavy continue to require a persistent
gateway.nodes.commands.allow entry alongside pairing.
Node pairing sets up identity and trust; it does not take the place of a node's own
system.run exec approval policy.
Shared-secret auth
For a given Gateway, shared token/password auth is viewed as trusted operator access.
OpenAI-compatible HTTP surfaces, /tools/invoke, and HTTP
session-history endpoints bring back the complete default operator scope set for
shared-secret bearer auth, even when a caller sends narrower declared scopes.
Modes that carry identity, like trusted proxy auth or private-ingress none,
can still respect explicit declared scopes. For genuine trust boundary separation,
deploy separate Gateways.