openclaw/docs/gateway/openai-http-api.md
Alex Alaniz d5ccc3dd41 feat: add publicMode for public-facing agents
Add per-agent `publicMode` configuration that suppresses local runtime
details (hostname, OS, architecture, workspace paths, skills snapshot)
from the system prompt when serving public-facing agents via the HTTP API.

- New `publicMode?: boolean` field in agent config schema
- `resolveAgentPublicMode()` in agent-scope for config lookup
- System prompt emits `"Runtime: public-facing agent"` instead of
  host/OS/arch details when publicMode is active
- Skills snapshot suppressed for publicMode agents
- New `X-OpenClaw-Sender-Is-Owner` HTTP header for both chat completions
  and OpenResponses endpoints, replacing the hardcoded `senderIsOwner: true`
- For publicMode agents, missing header defaults to non-owner semantics;
  for normal agents, missing header defaults to owner semantics
- `resolveIngressSenderIsOwner()` utility in http-utils
- Documentation updates for security boundary, header usage, and config
- Tests for system prompt suppression, param redaction, and header parsing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 00:20:01 -04:00

135 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
summary: "Expose an OpenAI-compatible /v1/chat/completions HTTP endpoint from the Gateway"
read_when:
- Integrating tools that expect OpenAI Chat Completions
title: "OpenAI Chat Completions"
---
# OpenAI Chat Completions (HTTP)
OpenClaws Gateway can serve a small OpenAI-compatible Chat Completions endpoint.
This endpoint is **disabled by default**. Enable it in config first.
- `POST /v1/chat/completions`
- Same port as the Gateway (WS + HTTP multiplex): `http://<gateway-host>:<port>/v1/chat/completions`
Under the hood, requests are executed as a normal Gateway agent run (same codepath as `openclaw agent`), so routing/permissions/config match your Gateway.
## Authentication
Uses the Gateway auth configuration. Send a bearer token:
- `Authorization: Bearer <token>`
Notes:
- When `gateway.auth.mode="token"`, use `gateway.auth.token` (or `OPENCLAW_GATEWAY_TOKEN`).
- When `gateway.auth.mode="password"`, use `gateway.auth.password` (or `OPENCLAW_GATEWAY_PASSWORD`).
- If `gateway.auth.rateLimit` is configured and too many auth failures occur, the endpoint returns `429` with `Retry-After`.
## Security boundary (important)
Treat this endpoint as an **operator-access** surface for the gateway instance unless you
intentionally target a `publicMode` agent through a trusted upstream.
- HTTP bearer auth here is not a narrow per-user scope model.
- A valid Gateway token/password for this endpoint should still be treated like an owner/operator credential.
- Requests run through the same control-plane agent path as trusted operator actions.
- For normal agents, missing `x-openclaw-sender-is-owner` defaults to owner semantics.
- For agents with `publicMode: true`, missing `x-openclaw-sender-is-owner` defaults to non-owner semantics; only an explicit `x-openclaw-sender-is-owner: true` restores owner access.
- `publicMode` is not a full per-user sandbox. It redacts local runtime details in prompts and strips owner-only tools, but any non-owner tools still allowed by the target agent remain callable.
- Keep this endpoint on loopback/tailnet/private ingress only; do not expose it directly to the public internet.
See [Security](/gateway/security) and [Remote access](/gateway/remote).
## Choosing an agent
No custom headers required: encode the agent id in the OpenAI `model` field:
- `model: "openclaw:<agentId>"` (example: `"openclaw:main"`, `"openclaw:beta"`)
- `model: "agent:<agentId>"` (alias)
Or target a specific OpenClaw agent by header:
- `x-openclaw-agent-id: <agentId>` (default: `main`)
Advanced:
- `x-openclaw-session-key: <sessionKey>` to fully control session routing.
## Enabling the endpoint
Set `gateway.http.endpoints.chatCompletions.enabled` to `true`:
```json5
{
gateway: {
http: {
endpoints: {
chatCompletions: { enabled: true },
},
},
},
}
```
## Disabling the endpoint
Set `gateway.http.endpoints.chatCompletions.enabled` to `false`:
```json5
{
gateway: {
http: {
endpoints: {
chatCompletions: { enabled: false },
},
},
},
}
```
## 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.
## Streaming (SSE)
Set `stream: true` to receive Server-Sent Events (SSE):
- `Content-Type: text/event-stream`
- Each event line is `data: <json>`
- Stream ends with `data: [DONE]`
## Examples
Non-streaming:
```bash
curl -sS http://127.0.0.1:18789/v1/chat/completions \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'x-openclaw-agent-id: main' \
-d '{
"model": "openclaw",
"messages": [{"role":"user","content":"hi"}]
}'
```
Streaming:
```bash
curl -N http://127.0.0.1:18789/v1/chat/completions \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'x-openclaw-agent-id: main' \
-d '{
"model": "openclaw",
"stream": true,
"messages": [{"role":"user","content":"hi"}]
}'
```