Skip to main content
The Gateway can serve a small OpenAI-compatible Chat Completions surface. It is disabled by default. Once enabled, it serves all of these on the same port as the Gateway (WS + HTTP multiplex): Requests run as a normal Gateway agent run (same codepath as openclaw agent), so routing, permissions, and config match your Gateway.

Enabling the endpoint

Set enabled: false (or omit it) to disable.

Security boundary (important)

Treat this endpoint as full operator access to the gateway instance:
  • A valid Gateway token/password for this endpoint is equivalent to an owner/operator credential, not a narrow per-user scope.
  • Requests run through the same control-plane agent path as trusted operator actions, so if the target agent’s policy allows sensitive tools, this endpoint can use them.
  • Keep it on loopback/tailnet/private ingress only. Do not expose it to the public internet.
Auth matrix: See Operator scopes, Security, and Remote access.

Authentication

Uses the Gateway auth configuration (see Trusted proxy auth for that mode’s details): Notes:
  • Same-host callers that bypass the proxy on a trusted-proxy gateway can fall back to gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD directly. Any Forwarded, X-Forwarded-*, or X-Real-IP header evidence keeps the request on the trusted-proxy path instead.
  • If gateway.auth.rateLimit is configured and too many auth attempts fail, the endpoint returns 429 with a Retry-After header.

When to use this endpoint

  • Prefer this over adding a new built-in channel when your integration is just another operator/client surface for the same gateway.
  • For native mobile clients that connect directly to a remote gateway, prefer WebChat or the Gateway Protocol with the paired-device bootstrap/device-token flow, so the device does not need a shared HTTP token/password.
  • Build a channel plugin instead when integrating an external messaging network with its own users, rooms, webhook delivery, or outbound transport. See Building plugins.

Agent-first model contract

OpenClaw treats the OpenAI model field as an agent target, not a raw provider model id. Optional request headers: /v1/models lists top-level agent targets (openclaw, openclaw/default, openclaw/<agentId>), not backend provider models and not sub-agents; sub-agents stay internal execution topology. If you omit x-openclaw-model, the selected agent runs with its normal configured model. /v1/embeddings uses the same agent-target model ids. Send x-openclaw-model (from a shared-secret caller, or an identity-bearing caller with operator.admin) to pick a specific embedding model; otherwise the request uses the selected agent’s normal embedding setup.

Session behavior

By default the endpoint is stateless per request (a new session key is generated each call). If the request includes an OpenAI user string, the Gateway derives a stable session key from it so repeated calls can share an agent session. For custom apps, reuse the same user value per conversation thread; avoid account-level identifiers unless you want multiple conversations/devices to share one OpenClaw session. Use x-openclaw-session-key only when you need explicit routing control across multiple clients/threads, with application-owned keys that avoid the reserved namespaces above.

Request limits (config)

Defaults can be tuned under gateway.http.endpoints.chatCompletions:
Defaults when omitted: HEIC/HEIF image_url sources are accepted and normalized to JPEG before provider delivery through the shared OpenClaw image processor (Rastermill), which falls back to a system converter (sips, ImageMagick, GraphicsMagick, or ffmpeg) for formats needing external codec support. Security note: allowlisting a hostname does not bypass private/internal IP blocking. For internet-exposed gateways, apply network egress controls in addition to app-level guards. See Security.

Chat tool contract

/v1/chat/completions supports a function-tool subset compatible with common OpenAI Chat clients.

Supported request fields

All sampling and token-cap fields ride the same agent stream-param channel and are forwarded best-effort:
  • Token cap: the wire field name is chosen by the provider transport: max_completion_tokens for OpenAI-family endpoints, max_tokens for providers that only accept the legacy name (Mistral, Chutes).
  • stop maps to the transport’s stop field: stop for Chat Completions backends, stop_sequences for Anthropic. The OpenAI Responses API has no stop parameter, so stop is not applied on Responses-backed models.
  • The ChatGPT-based Codex Responses backend uses fixed server-side sampling and strips temperature/top_p (along with max_output_tokens, metadata, prompt_cache_retention, service_tier) before the request reaches that backend.

Unsupported variants

Returns 400 invalid_request_error for:
  • non-array tools, non-function tool entries, or missing tool.function.name
  • tool_choice variants such as allowed_tools and custom
  • tool_choice.function.name values that do not match a provided tool
For tool_choice: "required" and function-pinned tool_choice, the endpoint narrows the exposed client function-tool set, instructs the runtime to call a client tool before responding, and errors if the agent response has no matching structured client-tool call. This applies to the caller-supplied HTTP tools list, not every internal OpenClaw agent tool.

Non-streaming tool response shape

When the agent calls tools, the response uses:
  • choices[0].finish_reason = "tool_calls"
  • choices[0].message.tool_calls[] entries with id, type: "function", function.name, function.arguments (JSON string)
  • Assistant commentary before the tool call, in choices[0].message.content (possibly empty)

Streaming tool response shape

When stream: true, tool calls arrive as incremental SSE chunks: an initial assistant role delta, optional assistant commentary deltas, one or more delta.tool_calls chunks carrying tool identity and argument fragments, then a final chunk with finish_reason: "tool_calls" and data: [DONE]. If stream_options.include_usage=true, a trailing usage chunk is emitted before [DONE].

Tool follow-up loop

After receiving tool_calls, execute the requested function(s) and send a follow-up request that includes the prior assistant tool-call message plus one or more role: "tool" messages with matching tool_call_id. This continues the same agent reasoning loop to produce the final answer.

Streaming (SSE)

Set stream: true to receive Server-Sent Events:
  • Content-Type: text/event-stream
  • Each event line is data: <json>
  • Stream ends with data: [DONE]

Open WebUI quick setup

  • Base URL: http://127.0.0.1:18789/v1
  • Docker on macOS base URL: http://host.docker.internal:18789/v1
  • API key: your Gateway bearer token
  • Model: openclaw/default
Expected behavior: GET /v1/models lists openclaw/default, and Open WebUI uses it as the chat model id. For a specific backend provider/model, set the agent’s normal default model, or send x-openclaw-model (shared-secret caller, or identity-bearing caller with operator.admin). Quick smoke test:
If that returns openclaw/default, most Open WebUI setups can connect with the same base URL and token.

Examples

Stable session for one app conversation:
Reuse the same user value on later calls for that conversation to continue the same agent session. Non-streaming:
Streaming:
List models:
Fetch one model:
Create embeddings:
/v1/embeddings supports input as a string or array of strings.