Gateway protocol operator methods
Operator helper methods, exec approvals, and agent delivery fallback
Methods an operator client calls on behalf of a person: helper reads, exec approval resolution, and delivery behavior for agent runs.
Operator helper methods
commands.list(operator.read) fetches the runtime command inventory for an agent.agentIdis optional; omit it to read the default agent workspace.scopecontrols which surface the primarynametargets:textreturns the primary text command token without the leading/;nativeand the defaultbothpath return provider-aware native names when available.textAliasescarries exact slash aliases such as/modeland/m.nativeNamecarries the provider-aware native command name when one exists.provideris optional and only affects native naming plus native plugin command availability.includeArgs=falseomits serialized argument metadata from the response.
tools.catalog(operator.read) fetches the runtime tool catalog for an agent. The response includes grouped tools and provenance metadata:source:coreorpluginpluginId: plugin owner whensource="plugin"optional: whether a plugin tool is optional
tools.effective(operator.read) fetches a prospective tool preview for a session.sessionKeyis required.- The gateway derives trusted runtime context from the session server-side instead of accepting caller-supplied auth or delivery context.
- The response is a session-scoped server-derived projection from saved settings, including core, plugin, channel, and already-discovered MCP server tools. It is not the exact tool inventory of an active run: run authority, credentials, discovery, and final run policy can change which tools are offered. Absence from this preview does not establish that a tool is disabled, and inclusion does not guarantee execution access.
- The projection can use cached inventory while refreshing it. Unsaved UI edits are not inputs, and saved or runtime changes may not appear immediately.
tools.effectiveis read-only for MCP: it may project a warm session MCP catalog through the final tool policy, but does not create MCP runtimes, connect transports, or issuetools/list. If no matching warm catalog exists, the response may include a notice such asmcp-not-yet-connected,mcp-not-yet-listed, ormcp-stale-catalog.- Effective tool entries use
source="core",source="plugin",source="channel", orsource="mcp".
tools.invoke(operator.write) invokes one available tool through the same gateway policy path as/tools/invoke.nameis required.args,sessionKey,agentId,confirm, andidempotencyKeyare optional.- If both
sessionKeyandagentIdare present, the resolved session agent must matchagentId. - Owner-only core wrappers such as
cron,gateway, andnodesrequire owner/admin identity (operator.admin) even thoughtools.invokeitself isoperator.write. - The response is an SDK-facing envelope with
ok,toolName, optionaloutput, and typederrorfields. Approval or policy refusals returnok:falsein the payload rather than bypassing the gateway tool policy pipeline.
skills.status(operator.read) fetches the visible skill inventory for an agent.agentIdis optional; omit it to read the default agent workspace.- The response includes eligibility, missing requirements, config checks, and sanitized install options without exposing raw secret values.
skills.searchandskills.detail(operator.read) return ClawHub discovery metadata.skills.detail({ slug, version? })accepts the publisher-qualifiedinstallReffrom search and reads that release's card and scan summary. See Skill registry details.skills.upload.begin,skills.upload.chunk, andskills.upload.commit(operator.admin) stage a private skill archive before installing it. This is a separate admin upload path for trusted clients, not the normal ClawHub skill install flow, and is disabled by default unlessskills.install.allowUploadedArchivesis enabled.skills.upload.begin({ kind: "skill-archive", slug, sizeBytes, sha256?, force?, idempotencyKey? })creates an upload bound to that slug and force value.skills.upload.chunk({ uploadId, offset, dataBase64 })appends bytes at the exact decoded offset.skills.upload.commit({ uploadId, sha256? })verifies the final size and SHA-256. Commit only finalizes the upload; it does not install the skill.- Uploaded skill archives are zip archives containing a
SKILL.mdroot. The archive's internal directory name never selects the install target.
skills.install(operator.admin) has three modes:- ClawHub mode:
{ source: "clawhub", slug, version?, force? }installs a skill folder into the default agent workspaceskills/directory. - Upload mode:
{ source: "upload", uploadId, slug, force?, sha256?, timeoutMs? }installs a committed upload into the default agent workspaceskills/<slug>directory. The slug and force value must match the originalskills.upload.beginrequest. Rejected unlessskills.install.allowUploadedArchivesis enabled; the setting does not affect ClawHub installs. - Gateway installer mode:
{ name, installId, timeoutMs? }runs a declaredmetadata.openclaw.installaction on the gateway host. Older clients may still senddangerouslyForceUnsafeInstall; this field is deprecated, accepted only for protocol compatibility, and ignored. Usesecurity.installPolicyfor operator-owned install decisions.
- ClawHub mode:
skills.update(operator.admin) has two modes:- ClawHub mode updates one tracked slug or all tracked ClawHub installs in
the default agent workspace. Updates that would replace a skill directory
whose installed files no longer match the recorded install digests are
refused; the per-skill failure in
details.resultscarriescode: "force_required". Retry with the optionalforce: trueparameter to replace such a skill anyway. - Config mode patches
skills.entries.<skillKey>values such asenabled,apiKey, andenv.
- ClawHub mode updates one tracked slug or all tracked ClawHub installs in
the default agent workspace. Updates that would replace a skill directory
whose installed files no longer match the recorded install digests are
refused; the per-skill failure in
models.list views
models.list accepts an optional view parameter
(src/agents/model-catalog-visibility.ts):
- Omitted or
"default": ifagents.defaults.modelPolicy.allowis configured, the response is the allowed catalog, including dynamically discovered models forprovider/*entries. Otherwise the response is the full gateway catalog. "configured": a compact catalog that also retains configured defaults and fallbacks for current-model controls. These metadata rows are not necessarily permitted manual choices. Published rows matched byprovider/*remain included. Without an allowlist, configured and authenticated rows remain visible."provider-config": source-authoredmodels.providers.*.modelsinventory, independent of picker allowlists. Rows include public model capabilities and route-aware availability, but omit provider endpoints, auth material, and runtime request configuration."all": full gateway catalog, bypassingagents.defaults.modelPolicy.allow. Use for diagnostics/discovery UIs, not normal model pickers.
Outside the "provider-config" view, rows that the
recommended models list names for their provider
carry recommended: true. Each provider's recommended rows come before its other
rows, in list order, after the session's selected model. Pickers may collapse the
remaining rows behind an "All models" control.
Clients that advertise model-selection-policy in connect caps receive
manualSelectionAllowed on every models.list row. The same fact appears in
their initial models.snapshot. Filter rows with false only when deriving
manual choices; keep the complete catalog for current-model capabilities and
readiness. Scoped configured reads also retain known metadata for the current
session model, without changing its selection or granting permission.
The fact is independent of available and does not authorize a session write.
The server checks the current policy again when a model is selected. Capless
connections retain the previous row shape. Generic client libraries do not opt
in: a proxy forwarding a capable connection must support its negotiated row
shape, or use a capless context for an older closed-schema consumer.
Ordinary requests read the published catalog without starting provider discovery.
Views select rows; they do not decide whether discovery runs. If the owner is not
published yet, the request reports that the model catalog is not ready. A result
whose owner becomes stale during projection is rejected with UNAVAILABLE,
retryable: true, and retryAfterMs: 0. The Control UI shares one retry across
catalog consumers, retaining cancellation and any explicit request deadline.
preparedOnly: trueremains supported for automatic clients. Ordinary reads are passive with or without this flag.refresh: truerequests provider acquisition before reading the new published generation. Concurrent refreshes share the owner build. A failed acquisition retains compatible rows and reports itsproviderOutcomes; successful empty acquisition remains empty.provider: "<id>"filters the published result through the captured provider aliases. Unknown provider IDs returnINVALID_REQUESTwith the rejected ID. Omit the filter or runopenclaw models list --allto list models and their provider IDs.includeDetails: trueincludes available input modalities, effectivecontextTokens, and alocalendpoint classification. It does not expose endpoint URLs, headers, credentials, costs or runtime request parameters.
For a conversation picker, pass sessionKey to read the session's canonical
agent and saved account selection. A conflicting agentId is rejected. The
viewer's current account default does not replace a saved session's selection.
For a new draft, authProfileId previews a retained account owned by the
identified caller with operator.read access. It does not save an account
default. sessionKey and authProfileId are mutually exclusive.
Saved-session metadata and draft previews stay current across unrelated session
creations and writes. Before publishing, the Gateway rechecks the selected
session's identity and canonical metadata, runtime configuration, and current
access authority. Recreating a row with identical session facts does not invalidate
the read. chat.metadata also tolerates title, activity, and ordinary preference
updates to the selected row when its metadata inputs and access facts remain
unchanged. Account, model, runtime, lifecycle, and access changes still invalidate
an in-flight metadata read.
Session and identified-account results include accountSelection display facts
with the models. Collaborators do not receive another person's private account
locator. The provider-config view remains shared authored inventory and omits
account selection. refreshFailed: true reports a failed acquisition while
compatible rows remain usable; recovery clears it. A successful empty catalog
remains empty.
The Gateway advertises session-scoped-model-catalog for this contract.
chat.metadata remains available to legacy clients. Clients that read models
directly can pass includeModels: false to skip the duplicate catalog, account
selection, and runtime-selection projection. Commands and swarm availability
remain available. Compact responses include an opaque revision; pass it as
ifRevision on a later compact read to receive unchanged: true instead of
another command list. The revision describes prepared command and swarm facts.
The bundled Control UI reads these agent-scoped facts without a session or
account selection and retains them across session activity. Session-scoped model
results and full session rows can carry sessionModelRevision, an opaque token
for the saved model, account, runtime, and lifecycle inputs. The UI keeps its
catalog when that token matches; missing tokens and explicit catalogChanged
notifications retain an authoritative read. Shared catalog, auth, config, and
connection changes invalidate independently. Harness-owned, model-locked sessions
omit this token because their native owner can replace a private model binding
independently of the saved row. Native clients that also support older Gateways retain the default
request shape. Opening a conversation picker
performs a passive read, without a model-cache timer or implicit provider refresh.
Metadata refresh publishes model-owner facts without preparing every agent's
commands and model projections. Requests prepare their agent's metadata on demand;
a slow agent does not delay other agents. Retained commands and projections are
bounded and do not retain completed requests' session documents. Account selection
is projected for the current session even when its model catalog is shared.
Provider renewal with unchanged inventory and auth metadata preserves cached metadata
without broadcasting chat.metadata.changed. Discovery progress alone does not
invalidate metadata; catalog changes and refreshFailed transitions still do.
Discovery progress retires shared RPC response bytes without rebuilding metadata
or sending another client broadcast.
Shared model or account replacement still gates these reads, and history
uses only already-prepared catalogs without starting or waiting for preparation.
The Models settings page uses preparedOnly: true for its initial load, then
requests refresh: true the first time a primary, utility, or fallback model
picker opens for the current core-data snapshot. Pending opens share that page's request; completed reopens read the
current published catalog without acquiring providers again. Explicit Retry
requests a new acquisition. Replacing core settings data, the page, agent, or
Gateway resets this request state. Core data reloads after configuration changes,
so the next picker open can discover models from newly configured providers.
Usable choices remain available when refresh fails.
This replaces the former five-minute automatic refresh policy; elapsed time alone
does not make a reopened Settings picker refresh. The Gateway shares concurrent
provider acquisition.
preparedOnly: true and refresh: true remain mutually exclusive.
The WebSocket dispatcher shares identical cron.list, cron.status, sessions.list,
models.list, and chat.metadata responses between eligible human connections.
Each request still checks its own current authority. Sharing keys separate user
and profile identity, scopes, client capabilities, and request parameters,
including agent, session, and account selection. Explicit model refreshes,
synthetic callers, and cron reads with restricted session visibility do not share.
Session, cron, and model metadata broadcasts retire the relevant responses before
clients can refetch. Config, access, and session-row revisions also fence reuse.
These methods currently use a one-second absolute ceiling; this bounds
personal model metadata changes that do not publish a broadcast. This adds no
client polling or provider refresh. Session catalogs and workboard reads do not use this response-sharing owner.
The running cron owner retains immutable job read views and aggregate status until a committed revision, loaded store replacement, or scheduler mutation changes them. Each list request still applies its current visibility filters. Delivery previews keep their session and configuration dependencies; a cron revision alone does not make them reusable. Passive cron readers retain their store refresh behavior.
The Gateway advertises these published-read and details controls as
published-model-catalog. Clients that require this contract must check the
capability before sending the new fields; an older Gateway requires an update
or restart, not a silent local fallback. The model CLI uses this contract for
models list and models list --refresh.
Skill registry details
Use the exact installRef from skills.search when requesting details. For example:
{ "slug": "@example-publisher/example-skill", "version": "1.2.0" }Omitting version selects the latest published release. The response retains
skill, latestVersion, metadata, and owner, and adds registry, source,
installRef, and selectedRelease. latestVersion and metadata always describe
the listing's latest release; selectedRelease, card, and security describe
the requested release. Publisher and release mismatches never substitute another
skill or version.
card contains full card text when its status is available. Otherwise it has
status: "unavailable" and a reason. security reports scanStatus,
hasWarnings, hasScanResult, and any scan time, summary, or VirusTotal URL.
Missing scans are explicitly unavailable. Optional release or card failures leave
basic listing metadata readable and appear in the affected section or warnings.
requirements reports the latest release's registry setup keys, operating
systems, and systems when available. Its scope: "registry-setup" and note
explain that setup keys combine environment and configuration requirements and do
not include binary requirements. Structured requirements for older releases are
unavailable because ClawHub only publishes these facts for latest. These are
registry declarations, not checks of a local agent's eligibility; use
skills.status for local requirements and configuration checks.
downloadability is independent of card availability, listing visibility, and
scan results. Missing or removed releases are unavailable; other skill releases
are unknown because ClawHub does not publish an exact-release artifact
availability assertion. Both states include a reason. Installation still performs
its own resolution, integrity, and policy checks.
External skills-sh: references remain install-only. skills.detail rejects
them rather than returning a native registry skill with the same slug.
Exec approvals
- When an exec request needs approval, the gateway broadcasts
exec.approval.requested. - Operator clients resolve by calling
exec.approval.resolve(requiresoperator.approvals). - For
host=node,exec.approval.requestmust includesystemRunPlan(canonicalargv/cwd/rawCommand/session metadata). Requests missingsystemRunPlanare rejected. - After approval, forwarded
node.invoke system.runcalls reuse that canonicalsystemRunPlanas the authoritative command/cwd/session context. - If a caller mutates
command,rawCommand,cwd,agentId, orsessionKeybetween prepare and the final approvedsystem.runforward, the gateway rejects the run instead of trusting the mutated payload.
Agent delivery fallback
agentrequests can includedeliver=trueto request outbound delivery.bestEffortDeliver=false(the default) keeps strict behavior: unresolved or internal-only delivery targets returnINVALID_REQUEST.bestEffortDeliver=trueallows fallback to session-only execution when no external deliverable route can be resolved (for example internal/webchat sessions or ambiguous multi-channel configs).- Final
agentresults may includeresult.deliveryStatuswhen delivery was requested, using the samesent,suppressed,partial_failed, andfailedstatuses documented foropenclaw agent --json --deliver.