Gateway
API OpenResponses
OpenClaw's Gateway dapat menyediakan endpoint POST /v1/responses yang kompatibel dengan OpenResponses.
Endpoint ini dinonaktifkan secara default. Aktifkan terlebih dahulu di konfigurasi.
POST /v1/responses- Port yang sama dengan Gateway (multipleks WS + HTTP):
http://<gateway-host>:<port>/v1/responses
Di balik layar, permintaan dijalankan sebagai run agent Gateway normal (jalur kode yang sama dengan
openclaw agent), sehingga routing/izin/konfigurasi sesuai dengan Gateway Anda.
Autentikasi, keamanan, dan routing
Perilaku operasional sesuai dengan OpenAI Chat Completions:
- gunakan jalur autentikasi HTTP Gateway yang sesuai:
- autentikasi rahasia bersama (
gateway.auth.mode="token"atau"password"):Authorization: Bearer <token-or-password> - autentikasi proxy tepercaya (
gateway.auth.mode="trusted-proxy"): header proxy sadar-identitas dari sumber proxy tepercaya yang dikonfigurasi; proxy local loopback host yang sama memerlukangateway.auth.trustedProxy.allowLoopback = truesecara eksplisit - autentikasi terbuka private-ingress (
gateway.auth.mode="none"): tanpa header autentikasi
- autentikasi rahasia bersama (
- perlakukan endpoint sebagai akses operator penuh untuk instance gateway
- untuk mode autentikasi rahasia bersama (
tokendanpassword), abaikan nilaix-openclaw-scopeslebih sempit yang dideklarasikan bearer dan pulihkan default operator penuh yang normal - untuk mode HTTP pembawa identitas tepercaya (misalnya autentikasi proxy tepercaya atau
gateway.auth.mode="none"), hormatix-openclaw-scopesjika ada dan jika tidak, kembali ke set scope default operator normal - pilih agent dengan
model: "openclaw",model: "openclaw/default",model: "openclaw/<agentId>", ataux-openclaw-agent-id - gunakan
x-openclaw-modelketika Anda ingin menimpa model backend agent yang dipilih - gunakan
x-openclaw-session-keyuntuk routing sesi eksplisit - gunakan
x-openclaw-message-channelketika Anda menginginkan konteks channel ingress sintetis non-default
Matriks autentikasi:
gateway.auth.mode="token"atau"password"+Authorization: Bearer ...- membuktikan kepemilikan rahasia operator gateway bersama
- mengabaikan
x-openclaw-scopesyang lebih sempit - memulihkan set scope operator default penuh:
operator.admin,operator.approvals,operator.pairing,operator.read,operator.talk.secrets,operator.write - memperlakukan giliran chat pada endpoint ini sebagai giliran owner-sender
- mode HTTP pembawa identitas tepercaya (misalnya autentikasi proxy tepercaya, atau
gateway.auth.mode="none"pada ingress privat)- menghormati
x-openclaw-scopesketika header ada - kembali ke set scope default operator normal ketika header tidak ada
- hanya kehilangan semantik owner ketika pemanggil secara eksplisit mempersempit scope dan menghilangkan
operator.admin
- menghormati
Aktifkan atau nonaktifkan endpoint ini dengan gateway.http.endpoints.responses.enabled.
Permukaan kompatibilitas yang sama juga mencakup:
GET /v1/modelsGET /v1/models/{id}POST /v1/embeddingsPOST /v1/chat/completions
Untuk penjelasan kanonis tentang bagaimana model target-agent, openclaw/default, pass-through embeddings, dan penimpaan model backend bekerja bersama, lihat OpenAI Chat Completions dan Daftar model dan routing agent.
Perilaku sesi
Secara default endpoint ini stateless per permintaan (kunci sesi baru dibuat untuk setiap panggilan).
Jika permintaan menyertakan string user OpenResponses, Gateway menurunkan kunci sesi stabil
darinya, sehingga panggilan berulang dapat berbagi sesi agent.
Bentuk permintaan (didukung)
Permintaan mengikuti API OpenResponses dengan input berbasis item. Dukungan saat ini:
input: string atau array objek item.instructions: digabungkan ke dalam prompt sistem.tools: definisi tool klien (tool fungsi).tool_choice: memfilter atau mewajibkan tool klien.stream: mengaktifkan streaming SSE.max_output_tokens: batas output best-effort (bergantung provider).user: routing sesi stabil.
Diterima tetapi saat ini diabaikan:
max_tool_callsreasoningmetadatastoretruncation
Didukung:
previous_response_id: OpenClaw menggunakan ulang sesi respons sebelumnya ketika permintaan tetap berada dalam scope agent/user/sesi-diminta yang sama.
Item (input)
message
Peran: system, developer, user, assistant.
systemdandeveloperditambahkan ke prompt sistem.- Item
userataufunction_call_outputterbaru menjadi "pesan saat ini." - Pesan user/assistant sebelumnya disertakan sebagai riwayat untuk konteks.
function_call_output (tool berbasis giliran)
Kirim hasil tool kembali ke model:
{
"type": "function_call_output",
"call_id": "call_123",
"output": "{\"temperature\": \"72F\"}"
}
reasoning dan item_reference
Diterima untuk kompatibilitas skema tetapi diabaikan saat membangun prompt.
Tool (tool fungsi sisi klien)
Sediakan tool dengan tools: [{ type: "function", function: { name, description?, parameters? } }].
Jika agent memutuskan untuk memanggil tool, respons mengembalikan item output function_call.
Kemudian Anda mengirim permintaan lanjutan dengan function_call_output untuk melanjutkan giliran.
Gambar (input_image)
Mendukung sumber base64 atau URL:
{
"type": "input_image",
"source": { "type": "url", "url": "https://example.com/image.png" }
}
Jenis MIME yang diizinkan (saat ini): image/jpeg, image/png, image/gif, image/webp, image/heic, image/heif.
Ukuran maksimum (saat ini): 10MB.
File (input_file)
Mendukung sumber base64 atau URL:
{
"type": "input_file",
"source": {
"type": "base64",
"media_type": "text/plain",
"data": "SGVsbG8gV29ybGQh",
"filename": "hello.txt"
}
}
Jenis MIME yang diizinkan (saat ini): text/plain, text/markdown, text/html, text/csv,
application/json, application/pdf.
Ukuran maksimum (saat ini): 5MB.
Perilaku saat ini:
- Konten file didekode dan ditambahkan ke prompt sistem, bukan pesan user, sehingga tetap sementara (tidak dipertahankan dalam riwayat sesi).
- Teks file yang didekode dibungkus sebagai konten eksternal tidak tepercaya sebelum ditambahkan, sehingga byte file diperlakukan sebagai data, bukan instruksi tepercaya.
- Blok yang diinjeksi menggunakan penanda batas eksplisit seperti
<<<EXTERNAL_UNTRUSTED_CONTENT id="...">>>/<<<END_EXTERNAL_UNTRUSTED_CONTENT id="...">>>dan menyertakan baris metadataSource: External. - Jalur input-file ini sengaja menghilangkan banner panjang
SECURITY NOTICE:untuk menjaga anggaran prompt; penanda batas dan metadata tetap ada. - PDF diuraikan untuk teks terlebih dahulu. Jika hanya sedikit teks ditemukan, halaman pertama
dirasterisasi menjadi gambar dan diteruskan ke model, dan blok file yang diinjeksi menggunakan
placeholder
[PDF content rendered to images].
Parsing PDF disediakan oleh Plugin document-extract yang dibundel, yang menggunakan build legacy
pdfjs-dist yang ramah Node (tanpa worker). Build PDF.js modern
mengharapkan worker browser/global DOM, sehingga tidak digunakan di Gateway.
Default fetch URL:
files.allowUrl:trueimages.allowUrl:truemaxUrlParts:8(total bagianinput_file+input_imageberbasis URL per permintaan)- Permintaan dijaga (resolusi DNS, pemblokiran IP privat, batas redirect, timeout).
- Allowlist hostname opsional didukung per jenis input (
files.urlAllowlist,images.urlAllowlist).- Host persis:
"cdn.example.com" - Subdomain wildcard:
"*.assets.example.com"(tidak cocok dengan apex) - Allowlist kosong atau dihilangkan berarti tidak ada pembatasan allowlist hostname.
- Host persis:
- Untuk menonaktifkan fetch berbasis URL sepenuhnya, setel
files.allowUrl: falsedan/atauimages.allowUrl: false.
Batas file + gambar (konfigurasi)
Default dapat disetel di bawah 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,
},
},
},
},
},
}
Default ketika dihilangkan:
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: 10s- Sumber HEIC/HEIF
input_imagediterima dan dinormalisasi menjadi JPEG sebelum dikirim ke provider.
Catatan keamanan:
- Allowlist URL diberlakukan sebelum fetch dan pada hop redirect.
- Memasukkan hostname ke allowlist tidak melewati pemblokiran IP privat/internal.
- Untuk gateway yang terekspos internet, terapkan kontrol egress jaringan selain penjaga tingkat aplikasi. Lihat Keamanan.
Streaming (SSE)
Setel stream: true untuk menerima Server-Sent Events (SSE):
Content-Type: text/event-stream- Setiap baris event adalah
event: <type>dandata: <json> - Stream berakhir dengan
data: [DONE]
Jenis event yang saat ini dipancarkan:
response.createdresponse.in_progressresponse.output_item.addedresponse.content_part.addedresponse.output_text.deltaresponse.output_text.doneresponse.content_part.doneresponse.output_item.doneresponse.completedresponse.failed(saat error)
Penggunaan
usage diisi ketika provider dasar melaporkan jumlah token.
OpenClaw menormalisasi alias umum bergaya OpenAI sebelum counter tersebut mencapai
permukaan status/sesi downstream, termasuk input_tokens / output_tokens
dan prompt_tokens / completion_tokens.
Error
Error menggunakan objek JSON seperti:
{ "error": { "message": "...", "type": "invalid_request_error" } }
Kasus umum:
401autentikasi hilang/tidak valid400body permintaan tidak valid405metode salah
Contoh
Non-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"
}'