docs/gateway/tools-invoke-http-api.md
OpenClaw's Gateway exposes an HTTP endpoint for invoking a single tool directly. It is always enabled and uses Gateway auth plus tool policy. Like the OpenAI-compatible /v1/* surface, shared-secret bearer auth is treated as trusted operator access for the whole gateway.
POST /tools/invokehttp://<gateway-host>:<port>/tools/invokeUses the Gateway auth configuration.
Common HTTP auth paths:
gateway.auth.mode="token" or "password"): Authorization: Bearer <token-or-password>gateway.auth.mode="trusted-proxy"): route through the configured identity-aware proxy and let it inject the required identity headersgateway.auth.mode="none"): no auth header requiredNotes:
mode="token" uses gateway.auth.token (or OPENCLAW_GATEWAY_TOKEN).mode="password" uses gateway.auth.password (or OPENCLAW_GATEWAY_PASSWORD).mode="trusted-proxy" requires the HTTP request to come from a configured trusted proxy source; same-host loopback proxies require explicit gateway.auth.trustedProxy.allowLoopback = true.gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD as a local direct fallback. Any Forwarded, X-Forwarded-*, or X-Real-IP header evidence keeps the request on the trusted-proxy path instead.gateway.auth.rateLimit is configured and too many auth failures occur, the endpoint returns 429 with Retry-After.Treat this endpoint as a full operator-access surface for the gateway instance.
token and password), the endpoint restores the normal full operator defaults even if the caller sends a narrower x-openclaw-scopes header.gateway.auth.mode="none" on a private ingress) honor x-openclaw-scopes when present and otherwise fall back to the normal operator default scope set.Auth matrix:
| Auth mode | Behavior |
|---|---|
token or password + Authorization: Bearer ... | Proves possession of the shared gateway operator secret. Ignores narrower x-openclaw-scopes. Restores the full default operator scope set: operator.admin, operator.approvals, operator.pairing, operator.read, operator.talk.secrets, operator.write. Treats direct tool invokes as owner-sender turns. |
Trusted identity-bearing HTTP (trusted proxy auth, or mode="none" on private ingress) | Authenticates an outer trusted identity or deployment boundary. Honors x-openclaw-scopes when present. Falls back to the normal operator default scope set when the header is absent. Only loses owner semantics when the caller explicitly narrows scopes and omits operator.admin. |
{
"tool": "sessions_list",
"action": "json",
"args": {},
"sessionKey": "main",
"dryRun": false
}
Fields:
tool / name (string, required): tool name to invoke. name takes precedence if both are sent.action (string, optional): merged into args.action if the tool schema supports an action property and args did not already set one.args (object, optional): tool-specific arguments.sessionKey (string, optional): target session key. If omitted or "main", the Gateway uses the configured main session key (honors session.mainKey and the default agent, or global in global session scope).agentId (string, optional): resolves the session key for that agent. Errors with 400 if it conflicts with an explicit sessionKey that already maps to a different agent.idempotencyKey (string, optional): used to derive a stable tool-call id for the invocation.dryRun (boolean, optional): reserved for future use; currently ignored.Tool availability is filtered through the same policy chain used by Gateway agents:
tools.profile / tools.byProvider.profiletools.allow / tools.byProvider.allowagents.<id>.tools.allow / agents.<id>.tools.byProvider.allowIf a tool is not allowed by policy, the endpoint returns 404.
Important boundary notes:
/tools/invoke does not add an extra per-call approval prompt.exec is reachable here, treat it as a mutating shell surface. Denying write, edit, apply_patch, or HTTP filesystem-write tools does not make shell execution read-only.Gateway HTTP also applies a hard deny list by default (even if session policy allows the tool):
| Tool | Reason |
|---|---|
exec | Direct command execution (RCE surface) |
spawn | Arbitrary child process creation (RCE surface) |
shell | Shell command execution (RCE surface) |
fs_write | Arbitrary file mutation on the host |
fs_delete | Arbitrary file deletion on the host |
fs_move | Arbitrary file move/rename on the host |
apply_patch | Patch application can rewrite arbitrary files |
sessions_spawn | Session orchestration; spawning agents remotely is RCE |
sessions_send | Cross-session message injection |
cron | Persistent automation control plane |
gateway | Gateway control plane; prevents reconfiguration via HTTP |
nodes | Node command relay can reach system.run on paired hosts |
cron, gateway, and nodes are also owner-only: even outside this default deny list, non-owner callers cannot invoke them on this surface.
Customize the general deny list via gateway.tools:
{
gateway: {
tools: {
// Additional tools to block over HTTP /tools/invoke
deny: ["browser"],
// Remove tools from the default deny list for owner/admin callers
allow: ["gateway"],
},
},
}
gateway.tools.allow is an exposure override, not a scope upgrade. In identity-bearing HTTP modes, cron, gateway, and nodes remain unavailable to callers without owner/admin identity (operator.admin) even when listed in gateway.tools.allow. Shared-secret bearer auth still follows the full trusted-operator rule above.
To help group policies resolve context, you can optionally set:
x-openclaw-message-channel: <channel> (example: slack, telegram)x-openclaw-account-id: <accountId> (when multiple accounts exist)x-openclaw-message-to: <target> (delivery target for message-tool policy)x-openclaw-thread-id: <threadId> (thread context for message-tool policy)| Status | Meaning |
|---|---|
200 | { ok: true, result } |
400 | { ok: false, error: { type, message } } (invalid request or tool input error) |
401 | Unauthorized |
403 | { ok: false, error: { type, message, requiresApproval? } } (tool call blocked by policy) |
404 | Tool not available (not found or not allowlisted) |
405 | Method not allowed |
408 | Request body read timed out |
413 | Request body exceeded the max payload size |
429 | Auth rate-limited (Retry-After set) |
500 | { ok: false, error: { type, message } } (unexpected tool execution error; sanitized message) |
curl -sS http://127.0.0.1:18789/tools/invoke \
-H 'Authorization: Bearer secret' \
-H 'Content-Type: application/json' \
-d '{
"tool": "sessions_list",
"action": "json",
"args": {}
}'