Admin HTTP RPC Plugin: Expose Gateway Control-Plane Methods
Learn how the opt-in admin-http-rpc plugin exposes selected Gateway control-plane methods via HTTP for trusted automation. This page covers activation, security requirements, and when to use it.
Read this when
- Building host tooling that cannot use the Gateway WebSocket RPC client
- Exposing Gateway admin automation behind a private trusted ingress
- Auditing the security model for HTTP access to Gateway methods
The bundled admin-http-rpc plugin exposes a curated set of Gateway control-plane methods through HTTP, aimed at trusted host automation that cannot sustain an open Gateway WebSocket connection.
OpenClaw includes this plugin, but it starts out inactive; when inactive, the route never gets registered. Activating it introduces POST /api/v1/admin/rpc on the same listener used by the Gateway (http://<gateway-host>:<port>/api/v1/admin/rpc).
Reserve this for private host tooling, tailnet automation, or a trusted internal ingress. Keep the route away from the public internet at all times.
Before you enable it
Admin HTTP RPC acts as a complete operator control-plane interface: anyone who passes Gateway HTTP auth can call the methods listed below. Turn it on only when every condition here holds:
- The caller is authorized to manage the Gateway.
- The caller has no way to use the WebSocket RPC client.
- The route is confined to loopback, a tailnet, or a private authenticated ingress.
- You have gone through the allowed methods and they fit the automation you intend to run.
For OpenClaw clients and interactive tools that can hold a Gateway WebSocket connection open, prefer WebSocket RPC.
Enable
Activate the bundled plugin:
CLI
openclaw plugins enable admin-http-rpc
openclaw gateway restart
Config
{
plugins: {
entries: {
"admin-http-rpc": { enabled: true },
},
},
}
Plugin startup is when the route gets registered, so restart the Gateway after you change plugin config.
To remove the HTTP surface when it is no longer needed:
openclaw plugins disable admin-http-rpc
openclaw gateway restart
Verify the route
Send health as the minimal safe request:
curl -sS http://<gateway-host>:<port>/api/v1/admin/rpc \
-H 'Authorization: Bearer <gateway-token>' \
-H 'Content-Type: application/json' \
-d '{"method":"health","params":{}}'
A successful reply carries ok: true:
{
"id": "generated-request-id",
"ok": true,
"payload": {
"status": "ok"
}
}
When the plugin is off, the route answers with 404 because no registration exists for it.
Authentication
Gateway HTTP auth guards the plugin route.
Typical authentication setups:
- shared-secret auth (
gateway.auth.mode="token"or"password"): passAuthorization: Bearer <token-or-password> - trusted identity-bearing HTTP auth (
gateway.auth.mode="trusted-proxy"): send traffic through the configured identity-aware proxy and let it add the required identity headers - private-ingress open auth (
gateway.auth.mode="none"): omit the auth header entirely
Security model
Think of this plugin as a full Gateway operator surface.
- Switching it on deliberately opens the allowlisted admin RPC methods at
/api/v1/admin/rpc. - The plugin declares the reserved
contracts.gatewayMethodDispatch: ["authenticated-request"]manifest contract, which is what allows its Gateway-authenticated HTTP route to dispatch control-plane methods in process. This is not a sandbox: the contract stops accidental use of reserved SDK helpers, yet trusted plugins still execute inside the Gateway process. - Shared-secret bearer auth (
token/passwordmodes) demonstrates ownership of the gateway operator secret; narrowerx-openclaw-scopesheaders get ignored on that path and normal full operator defaults come back. - Trusted identity-bearing HTTP auth (
trusted-proxymode) respectsx-openclaw-scopeswhen it is present. gateway.auth.mode="none"means the route has no authentication once the plugin is enabled. Put that only behind a private ingress you fully trust.- After plugin route auth succeeds, requests go through the same Gateway method handlers and scope checks as WebSocket RPC.
- The route stays reachable while a prepared suspension lease is active. Bounded request validation and the local
commands.listdiscovery response remain available. Among the methods dispatched into the Gateway,gateway.suspend.prepare,gateway.suspend.status,gateway.suspend.resume, and an exact targeted non-safegateway.restart.requestmay run while admission is closed; safe, untargeted, and other allowlisted methods respond with the normal retryable GatewayUNAVAILABLEresponse. - Keep this route on loopback, tailnet, or a private trusted ingress. Do not put it directly on the public internet. Use separate gateways when callers cross trust boundaries.
Request
POST /api/v1/admin/rpc
Authorization: Bearer <gateway-token>
Content-Type: application/json
{
"id": "optional-request-id",
"method": "health",
"params": {}
}
Fields:
id(string, optional): echoed back in the response. A UUID is generated when it is absent.method(string, required): allowed Gateway method name.params(any, optional): method-specific params.
The default cap for request body size is 1 MB.
Response
Success responses follow the Gateway RPC shape:
{
"id": "optional-request-id",
"ok": true,
"payload": {}
}
Gateway method errors use:
{
"id": "optional-request-id",
"ok": false,
"error": {
"code": "INVALID_REQUEST",
"message": "bad params"
}
}
HTTP status maps from the error code:
| Error code | HTTP status |
|---|---|
INVALID_REQUEST | 400 |
APPROVAL_NOT_FOUND | 404 |
NOT_LINKED, NOT_PAIRED | 409 |
UNAVAILABLE | 503 |
AGENT_TIMEOUT | 504 |
| any other code | 500 |
Allowed methods
- discovery:
commands.listProvides the list of HTTP RPC method names that this plugin permits. - gateway:
health,status,logs.tail,usage.status,usage.cost,gateway.restart.request,gateway.suspend.prepare,gateway.suspend.status,gateway.suspend.resume - config:
config.get,config.schema,config.schema.lookup,config.set,config.patch,config.apply - channels:
channels.status,channels.start,channels.stop,channels.logout - web:
web.login.start,web.login.wait - models:
models.list,models.authStatus - agents:
agents.list,agents.create,agents.update,agents.delete - approvals:
exec.approvals.get,exec.approvals.set,exec.approvals.node.get,exec.approvals.node.set - cron:
cron.status,cron.list,cron.get,cron.runs,cron.add,cron.update,cron.remove,cron.run - devices:
device.pair.list,device.pair.approve,device.pair.reject,device.pair.remove - nodes:
node.list,node.describe,node.pair.list,node.pair.approve,node.pair.reject,node.pair.remove,node.rename - tasks:
tasks.list,tasks.get,tasks.cancel - diagnostics:
doctor.memory.status,update.status
Any other Gateway methods stay inaccessible unless you add them on purpose.
WebSocket comparison
For OpenClaw clients, the standard Gateway WebSocket RPC channel continues to be the recommended control-plane API. Reserve admin HTTP RPC for host-side utilities that require an HTTP request/response interface.
WebSocket clients using a shared token, which lack a verified device identity, cannot assign admin scopes to themselves during the connection phase. Admin HTTP RPC intentionally mirrors the established trusted HTTP operator approach: with the plugin active, bearer authentication via shared secret is interpreted as complete operator privileges for this admin interface.
Troubleshooting
404 Not Found
: Either the plugin is turned off, the Gateway has not been restarted after activation, or the request targets a separate Gateway instance.
401 Unauthorized
: The request failed Gateway HTTP authentication. Verify the bearer token or the trusted-proxy identity headers.
405 Method Not Allowed
: A method other than POST was used in the request.
413 Payload Too Large
: The request body went past the 1 MB cap.
400 INVALID_REQUEST
: The body is not valid JSON, the method field is absent, the method falls outside the plugin allowlist, or a suspension resume ID does not match the active lease.
503 UNAVAILABLE
: The Gateway method is starting, rate-limited, suspended, or blocked on a competing suspension/resume operation. When present, check error.details and respect error.retryAfterMs before trying again.