OpenClaw’s Gateway can serve a small OpenAI-compatible Chat Completions endpoint. This endpoint is disabled by default. Enable it in config first.Documentation Index
Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
POST /v1/chat/completions- Same port as the Gateway (WS + HTTP multiplex):
http://<gateway-host>:<port>/v1/chat/completions
GET /v1/modelsGET /v1/models/{id}POST /v1/embeddingsPOST /v1/responses
openclaw agent), so routing/permissions/config match your Gateway.
Authentication
Uses the Gateway auth configuration. Common HTTP auth paths:- shared-secret auth (
gateway.auth.mode="token"or"password"):Authorization: Bearer <token-or-password> - trusted identity-bearing HTTP auth (
gateway.auth.mode="trusted-proxy"): route through the configured identity-aware proxy and let it inject the required identity headers - private-ingress open auth (
gateway.auth.mode="none"): no auth header required
- When
gateway.auth.mode="token", usegateway.auth.token(orOPENCLAW_GATEWAY_TOKEN). - When
gateway.auth.mode="password", usegateway.auth.password(orOPENCLAW_GATEWAY_PASSWORD). - When
gateway.auth.mode="trusted-proxy", the HTTP request must come from a configured trusted proxy source; same-host loopback proxies require explicitgateway.auth.trustedProxy.allowLoopback = true. - Internal same-host callers that bypass the proxy can use
gateway.auth.password/OPENCLAW_GATEWAY_PASSWORDas a local direct fallback. AnyForwarded,X-Forwarded-*, orX-Real-IPheader evidence keeps the request on the trusted-proxy path instead. - If
gateway.auth.rateLimitis configured and too many auth failures occur, the endpoint returns429withRetry-After.
Security boundary (important)
Treat this endpoint as a full operator-access surface for the gateway instance.- HTTP bearer auth here is not a narrow per-user scope model.
- A valid Gateway token/password for this endpoint should be treated like an owner/operator credential.
- Requests run through the same control-plane agent path as trusted operator actions.
- There is no separate non-owner/per-user tool boundary on this endpoint; once a caller passes Gateway auth here, OpenClaw treats that caller as a trusted operator for this gateway.
- For shared-secret auth modes (
tokenandpassword), the endpoint restores the normal full operator defaults even if the caller sends a narrowerx-openclaw-scopesheader. - Trusted identity-bearing HTTP modes (for example trusted proxy auth or
gateway.auth.mode="none") honorx-openclaw-scopeswhen present and otherwise fall back to the normal operator default scope set. - If the target agent policy allows sensitive tools, this endpoint can use them.
- Keep this endpoint on loopback/tailnet/private ingress only; do not expose it directly to the public internet.
gateway.auth.mode="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 chat turns on this endpoint as owner-sender turns
- trusted identity-bearing HTTP modes (for example trusted proxy auth, or
gateway.auth.mode="none"on private ingress)- authenticate some outer trusted identity or deployment boundary
- honor
x-openclaw-scopeswhen the header is present - fall back to the normal operator default scope set when the header is absent
- only lose owner semantics when the caller explicitly narrows scopes and omits
operator.admin
When to use this endpoint
Use/v1/chat/completions when you are integrating tooling or a trusted app-side backend with an existing gateway and can safely hold gateway operator credentials.
- 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 and implement the paired-device bootstrap/device-token flow so the device does not need a shared HTTP token/password.
- Build a channel plugin instead when you are 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 OpenAImodel field as an agent target, not a raw provider model id.
model: "openclaw"routes to the configured default agent.model: "openclaw/default"also routes to the configured default agent.model: "openclaw/<agentId>"routes to a specific agent.
x-openclaw-model: <provider/model-or-bare-id>overrides the backend model for the selected agent.x-openclaw-agent-id: <agentId>remains supported as a compatibility override.x-openclaw-session-key: <sessionKey>fully controls session routing.x-openclaw-message-channel: <channel>sets the synthetic ingress channel context for channel-aware prompts and policies.
model: "openclaw:<agentId>"model: "agent:<agentId>"
Enabling the endpoint
Setgateway.http.endpoints.chatCompletions.enabled to true:
Disabling the endpoint
Setgateway.http.endpoints.chatCompletions.enabled to false:
Session behavior
By default the endpoint is stateless per request (a new session key is generated each call). If the request includes an OpenAIuser string, the Gateway derives a stable session key from it, so repeated calls can share an agent session.
For custom apps, the safest default is to reuse the same user value per conversation thread. Avoid account-level identifiers unless you explicitly want multiple conversations or devices to share one OpenClaw session. Use x-openclaw-session-key when you need explicit routing control across multiple clients or threads.
Why this surface matters
This is the highest-leverage compatibility set for self-hosted frontends and tooling:- Most Open WebUI, LobeChat, and LibreChat setups expect
/v1/models. - Many RAG systems expect
/v1/embeddings. - Existing OpenAI chat clients can usually start with
/v1/chat/completions. - More agent-native clients increasingly prefer
/v1/responses.
Model list and agent routing
What does `/v1/models` return?
What does `/v1/models` return?
An OpenClaw agent-target list.The returned ids are
openclaw, openclaw/default, and openclaw/<agentId> entries.
Use them directly as OpenAI model values.Does `/v1/models` list agents or sub-agents?
Does `/v1/models` list agents or sub-agents?
It lists top-level agent targets, not backend provider models and not sub-agents.Sub-agents remain internal execution topology. They do not appear as pseudo-models.
Why is `openclaw/default` included?
Why is `openclaw/default` included?
openclaw/default is the stable alias for the configured default agent.That means clients can keep using one predictable id even if the real default agent id changes between environments.How do I override the backend model?
How do I override the backend model?
Use
x-openclaw-model.Examples:
x-openclaw-model: openai/gpt-5.4
x-openclaw-model: gpt-5.5If you omit it, the selected agent runs with its normal configured model choice.How do embeddings fit this contract?
How do embeddings fit this contract?
/v1/embeddings uses the same agent-target model ids.Use model: "openclaw/default" or model: "openclaw/<agentId>".
When you need a specific embedding model, send it in x-openclaw-model.
Without that header, the request passes through to the selected agent’s normal embedding setup.Streaming (SSE)
Setstream: true to receive Server-Sent Events (SSE):
Content-Type: text/event-stream- Each event line is
data: <json> - Stream ends with
data: [DONE]
Chat tool contract
/v1/chat/completions supports a function-tool subset compatible with common OpenAI Chat clients.
Supported request fields
tools: array of{ "type": "function", "function": { ... } }tool_choice:"auto","none"messages[*].role: "tool"follow-up turnsmessages[*].tool_call_idfor binding tool results back to a prior tool callmax_completion_tokens: number; per-call cap for total completion tokens (reasoning tokens included). Current OpenAI Chat Completions field name; preferred when bothmax_completion_tokensandmax_tokensare sent.max_tokens: number; legacy alias accepted for backwards compatibility. Ignored whenmax_completion_tokensis also present.temperature: number; best-effort sampling temperature forwarded to the upstream provider via the agent stream-param channel.top_p: number; best-effort nucleus sampling forwarded to the upstream provider via the agent stream-param channel.
max_completion_tokens for OpenAI-family endpoints, and max_tokens for providers that only accept the legacy name (such as Mistral and Chutes). Sampling fields (temperature, top_p) follow the same stream-param channel; the ChatGPT-based Codex Responses backend strips them server-side since it uses fixed sampling.
Unsupported variants
The endpoint returns400 invalid_request_error for unsupported tool variants, including:
- non-array
tools - non-function tool entries
- missing
tool.function.name tool_choicevariants such asallowed_toolsandcustomtool_choice: "required"(not yet enforced at runtime; will be supported once hard enforcement is implemented)tool_choice: { "type": "function", "function": { "name": "..." } }(same rationale asrequired)tool_choice.function.namevalues that do not match providedtools
Non-streaming tool response shape
When the agent decides to call tools, the response uses:choices[0].finish_reason = "tool_calls"choices[0].message.tool_calls[]entries with:idtype: "function"function.namefunction.arguments(JSON string)
choices[0].message.content (possibly empty).
Streaming tool response shape
Whenstream: true, tool calls are emitted as incremental SSE chunks:
- initial assistant role delta
- optional assistant commentary deltas
- one or more
delta.tool_callschunks carrying tool identity and argument fragments - final chunk with
finish_reason: "tool_calls" data: [DONE]
stream_options.include_usage=true, a trailing usage chunk is emitted before [DONE].
Tool follow-up loop
After receivingtool_calls, the client should execute the requested function(s) and send a follow-up request that includes:
- prior assistant tool-call message
- one or more
role: "tool"messages with matchingtool_call_id
Open WebUI quick setup
For a basic Open WebUI connection:- 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
GET /v1/modelsshould listopenclaw/default- Open WebUI should use
openclaw/defaultas the chat model id - If you want a specific backend provider/model for that agent, set the agent’s normal default model or send
x-openclaw-model
openclaw/default, most Open WebUI setups can connect with the same base URL and token.
Examples
Stable session for one app conversation:user value on later calls for that conversation to continue the same agent session.
Non-streaming:
/v1/modelsreturns OpenClaw agent targets, not raw provider catalogs.openclaw/defaultis always present so one stable id works across environments.- Backend provider/model overrides belong in
x-openclaw-model, not the OpenAImodelfield. /v1/embeddingssupportsinputas a string or array of strings.