docs/gateway/openresponses-http-api.md
OpenClaw’s Gateway can serve an OpenResponses-compatible POST /v1/responses endpoint.
This endpoint is disabled by default. Enable it in config first.
POST /v1/responseshttp://<gateway-host>:<port>/v1/responsesUnder the hood, requests are executed as a normal Gateway agent run (same codepath as
openclaw agent), so routing/permissions/config match your Gateway.
Operational behavior matches OpenAI Chat Completions:
gateway.auth.mode="token" or "password"): Authorization: Bearer <token-or-password>gateway.auth.mode="trusted-proxy"): identity-aware proxy headers from a configured trusted proxy source; same-host loopback proxies require explicit gateway.auth.trustedProxy.allowLoopback = truegateway.auth.mode="none"): no auth headertoken and password), ignore narrower bearer-declared x-openclaw-scopes values and restore the normal full operator defaultsgateway.auth.mode="none"), honor x-openclaw-scopes when present and otherwise fall back to the normal operator default scope setmodel: "openclaw", model: "openclaw/default", model: "openclaw/<agentId>", or x-openclaw-agent-idx-openclaw-model when you want to override the selected agent's backend modelx-openclaw-session-key for explicit session routingx-openclaw-message-channel when you want a non-default synthetic ingress channel contextAuth matrix:
gateway.auth.mode="token" or "password" + Authorization: Bearer ...
x-openclaw-scopesoperator.admin, operator.approvals, operator.pairing,
operator.read, operator.talk.secrets, operator.writegateway.auth.mode="none" on private ingress)
x-openclaw-scopes when the header is presentoperator.adminEnable or disable this endpoint with gateway.http.endpoints.responses.enabled.
The same compatibility surface also includes:
GET /v1/modelsGET /v1/models/{id}POST /v1/embeddingsPOST /v1/chat/completionsFor the canonical explanation of how agent-target models, openclaw/default, embeddings pass-through, and backend model overrides fit together, see OpenAI Chat Completions and Model list and agent routing.
By default the endpoint is stateless per request (a new session key is generated each call).
If the request includes an OpenResponses user string, the Gateway derives a stable session key
from it, so repeated calls can share an agent session.
The request follows the OpenResponses API with item-based input. Current support:
input: string or array of item objects.instructions: merged into the system prompt.tools: client tool definitions (function tools).tool_choice: filter or require client tools.stream: enables SSE streaming.max_output_tokens: best-effort output limit (provider dependent).user: stable session routing.Accepted but currently ignored:
max_tool_callsreasoningmetadatastoretruncationSupported:
previous_response_id: OpenClaw reuses the earlier response session when the request stays within the same agent/user/requested-session scope.messageRoles: system, developer, user, assistant.
system and developer are appended to the system prompt.user or function_call_output item becomes the “current message.”function_call_output (turn-based tools)Send tool results back to the model:
{
"type": "function_call_output",
"call_id": "call_123",
"output": "{\"temperature\": \"72F\"}"
}
reasoning and item_referenceAccepted for schema compatibility but ignored when building the prompt.
Provide tools with tools: [{ type: "function", function: { name, description?, parameters? } }].
If the agent decides to call a tool, the response returns a function_call output item.
You then send a follow-up request with function_call_output to continue the turn.
input_image)Supports base64 or URL sources:
{
"type": "input_image",
"source": { "type": "url", "url": "https://example.com/image.png" }
}
Allowed MIME types (current): image/jpeg, image/png, image/gif, image/webp, image/heic, image/heif.
Max size (current): 10MB.
input_file)Supports base64 or URL sources:
{
"type": "input_file",
"source": {
"type": "base64",
"media_type": "text/plain",
"data": "SGVsbG8gV29ybGQh",
"filename": "hello.txt"
}
}
Allowed MIME types (current): text/plain, text/markdown, text/html, text/csv,
application/json, application/pdf.
Max size (current): 5MB.
Current behavior:
<<<EXTERNAL_UNTRUSTED_CONTENT id="...">>> /
<<<END_EXTERNAL_UNTRUSTED_CONTENT id="...">>> and includes a
Source: External metadata line.SECURITY NOTICE: banner to
preserve prompt budget; the boundary markers and metadata still stay in place.[PDF content rendered to images].PDF parsing is provided by the bundled document-extract plugin, which uses the
Node-friendly pdfjs-dist legacy build (no worker). The modern PDF.js build
expects browser workers/DOM globals, so it is not used in the Gateway.
URL fetch defaults:
files.allowUrl: trueimages.allowUrl: truemaxUrlParts: 8 (total URL-based input_file + input_image parts per request)files.urlAllowlist, images.urlAllowlist).
"cdn.example.com""*.assets.example.com" (does not match apex)files.allowUrl: false and/or images.allowUrl: false.Defaults can be tuned under gateway.http.endpoints.responses:
{
gateway: {
http: {
endpoints: {
responses: {
enabled: true,
maxBodyBytes: 20000000,
maxUrlParts: 8,
files: {
allowUrl: true,
urlAllowlist: ["cdn.example.com", "*.assets.example.com"],
allowedMimes: [
"text/plain",
"text/markdown",
"text/html",
"text/csv",
"application/json",
"application/pdf",
],
maxBytes: 5242880,
maxChars: 200000,
maxRedirects: 3,
timeoutMs: 10000,
pdf: {
maxPages: 4,
maxPixels: 4000000,
minTextChars: 200,
},
},
images: {
allowUrl: true,
urlAllowlist: ["images.example.com"],
allowedMimes: [
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/heic",
"image/heif",
],
maxBytes: 10485760,
maxRedirects: 3,
timeoutMs: 10000,
},
},
},
},
},
}
Defaults when omitted:
maxBodyBytes: 20MBmaxUrlParts: 8files.maxBytes: 5MBfiles.maxChars: 200kfiles.maxRedirects: 3files.timeoutMs: 10sfiles.pdf.maxPages: 4files.pdf.maxPixels: 4,000,000files.pdf.minTextChars: 200images.maxBytes: 10MBimages.maxRedirects: 3images.timeoutMs: 10sinput_image sources are accepted and normalized to JPEG before provider delivery.Security note:
Set stream: true to receive Server-Sent Events (SSE):
Content-Type: text/event-streamevent: <type> and data: <json>data: [DONE]Event types currently emitted:
response.createdresponse.in_progressresponse.output_item.addedresponse.content_part.addedresponse.output_text.deltaresponse.output_text.doneresponse.content_part.doneresponse.output_item.doneresponse.completedresponse.failed (on error)usage is populated when the underlying provider reports token counts.
OpenClaw normalizes common OpenAI-style aliases before those counters reach
downstream status/session surfaces, including input_tokens / output_tokens
and prompt_tokens / completion_tokens.
Errors use a JSON object like:
{ "error": { "message": "...", "type": "invalid_request_error" } }
Common cases:
401 missing/invalid auth400 invalid request body405 wrong methodNon-streaming:
curl -sS http://127.0.0.1:18789/v1/responses \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'x-openclaw-agent-id: main' \
-d '{
"model": "openclaw",
"input": "hi"
}'
Streaming:
curl -N http://127.0.0.1:18789/v1/responses \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'x-openclaw-agent-id: main' \
-d '{
"model": "openclaw",
"stream": true,
"input": "hi"
}'