Gateway
API ของ OpenResponses
OpenClaw의 Gateway สามารถให้บริการปลายทาง POST /v1/responses ที่เข้ากันได้กับ OpenResponses
ปลายทางนี้ถูกปิดใช้งานโดยค่าเริ่มต้น เปิดใช้งานใน config ก่อน
POST /v1/responses- พอร์ตเดียวกับ Gateway (มัลติเพล็กซ์ WS + HTTP):
http://<gateway-host>:<port>/v1/responses
ภายใน คำขอจะถูกดำเนินการเหมือนการรันเอเจนต์ Gateway ตามปกติ (เส้นทางโค้ดเดียวกับ
openclaw agent) ดังนั้นการกำหนดเส้นทาง/สิทธิ์/config จะตรงกับ Gateway ของคุณ
การยืนยันตัวตน ความปลอดภัย และการกำหนดเส้นทาง
ลักษณะการทำงานด้านปฏิบัติการตรงกับ การเติมเต็มแชตของ OpenAI:
- ใช้เส้นทางยืนยันตัวตน HTTP ของ Gateway ที่ตรงกัน:
- การยืนยันตัวตนด้วยความลับร่วม (
gateway.auth.mode="token"หรือ"password"):Authorization: Bearer <token-or-password> - การยืนยันตัวตนแบบพร็อกซีที่เชื่อถือได้ (
gateway.auth.mode="trusted-proxy"): ส่วนหัวพร็อกซีที่รับรู้ตัวตนจากแหล่งพร็อกซีที่เชื่อถือได้ที่กำหนดค่าไว้ พร็อกซี loopback บนโฮสต์เดียวกันต้องตั้งค่าgateway.auth.trustedProxy.allowLoopback = trueอย่างชัดเจน - การยืนยันตัวตนแบบเปิดสำหรับช่องทางเข้าแบบส่วนตัว (
gateway.auth.mode="none"): ไม่มีส่วนหัวการยืนยันตัวตน
- การยืนยันตัวตนด้วยความลับร่วม (
- ถือว่าปลายทางนี้เป็นสิทธิ์ผู้ปฏิบัติการเต็มรูปแบบสำหรับอินสแตนซ์ Gateway
- สำหรับโหมดการยืนยันตัวตนด้วยความลับร่วม (
tokenและpassword) ให้ละเว้นค่าx-openclaw-scopesที่ bearer ระบุให้แคบลง และคืนค่าค่าเริ่มต้นผู้ปฏิบัติการเต็มรูปแบบตามปกติ - สำหรับโหมด HTTP ที่มีตัวตนที่เชื่อถือได้ (เช่น การยืนยันตัวตนแบบพร็อกซีที่เชื่อถือได้ หรือ
gateway.auth.mode="none") ให้เคารพx-openclaw-scopesเมื่อมี และหากไม่มีให้ย้อนกลับไปใช้ชุด scope เริ่มต้นปกติของผู้ปฏิบัติการ - เลือกเอเจนต์ด้วย
model: "openclaw",model: "openclaw/default",model: "openclaw/<agentId>"หรือx-openclaw-agent-id - ใช้
x-openclaw-modelเมื่อคุณต้องการแทนที่โมเดลแบ็กเอนด์ของเอเจนต์ที่เลือก - ใช้
x-openclaw-session-keyสำหรับการกำหนดเส้นทางเซสชันแบบชัดเจน - ใช้
x-openclaw-message-channelเมื่อคุณต้องการบริบทช่องทางเข้าแบบสังเคราะห์ที่ไม่ใช่ค่าเริ่มต้น
ตารางการยืนยันตัวตน:
gateway.auth.mode="token"หรือ"password"+Authorization: Bearer ...- พิสูจน์การครอบครองความลับผู้ปฏิบัติการ Gateway ที่ใช้ร่วมกัน
- ละเว้น
x-openclaw-scopesที่แคบลง - คืนค่าชุด scope เริ่มต้นเต็มรูปแบบของผู้ปฏิบัติการ:
operator.admin,operator.approvals,operator.pairing,operator.read,operator.talk.secrets,operator.write - ถือว่า turn แชตบนปลายทางนี้เป็น turn จากผู้ส่งที่เป็นเจ้าของ
- โหมด HTTP ที่มีตัวตนที่เชื่อถือได้ (เช่น การยืนยันตัวตนแบบพร็อกซีที่เชื่อถือได้ หรือ
gateway.auth.mode="none"บนช่องทางเข้าแบบส่วนตัว)- เคารพ
x-openclaw-scopesเมื่อมีส่วนหัวนี้ - ย้อนกลับไปใช้ชุด scope เริ่มต้นปกติของผู้ปฏิบัติการเมื่อไม่มีส่วนหัวนี้
- จะเสียความหมายของเจ้าของก็ต่อเมื่อผู้เรียกจำกัด scope ให้แคบลงอย่างชัดเจนและละเว้น
operator.admin
- เคารพ
เปิดหรือปิดปลายทางนี้ด้วย gateway.http.endpoints.responses.enabled
พื้นผิวความเข้ากันได้เดียวกันยังรวมถึง:
GET /v1/modelsGET /v1/models/{id}POST /v1/embeddingsPOST /v1/chat/completions
สำหรับคำอธิบายมาตรฐานว่าโมเดลที่กำหนดเป้าหมายเอเจนต์, openclaw/default, การส่งต่อ embeddings และการแทนที่โมเดลแบ็กเอนด์ทำงานร่วมกันอย่างไร โปรดดู การเติมเต็มแชตของ OpenAI และ รายการโมเดลและการกำหนดเส้นทางเอเจนต์
ลักษณะการทำงานของเซสชัน
โดยค่าเริ่มต้น ปลายทางนี้เป็นแบบไม่มีสถานะต่อคำขอ (สร้างคีย์เซสชันใหม่ในการเรียกแต่ละครั้ง)
หากคำขอมีสตริง user ของ OpenResponses Gateway จะสร้างคีย์เซสชันที่เสถียร
จากค่านั้น เพื่อให้การเรียกซ้ำสามารถใช้เซสชันเอเจนต์ร่วมกันได้
รูปแบบคำขอ (ที่รองรับ)
คำขอทำตาม API OpenResponses ด้วยอินพุตแบบรายการ การรองรับปัจจุบัน:
input: สตริงหรืออาร์เรย์ของอ็อบเจ็กต์รายการinstructions: รวมเข้าในพรอมป์ระบบtools: นิยามเครื่องมือของไคลเอนต์ (เครื่องมือฟังก์ชัน)tool_choice: กรองหรือบังคับใช้เครื่องมือของไคลเอนต์stream: เปิดใช้งานการสตรีม SSEmax_output_tokens: ขีดจำกัดเอาต์พุตแบบพยายามดีที่สุด (ขึ้นกับผู้ให้บริการ)user: การกำหนดเส้นทางเซสชันที่เสถียร
รับได้แต่ปัจจุบันถูกละเว้น:
max_tool_callsreasoningmetadatastoretruncation
รองรับ:
previous_response_id: OpenClaw ใช้เซสชันคำตอบก่อนหน้าซ้ำเมื่อคำขอยังคงอยู่ในขอบเขตเอเจนต์/ผู้ใช้/เซสชันที่ร้องขอเดียวกัน
รายการ (input)
message
บทบาท: system, developer, user, assistant
systemและdeveloperจะถูกต่อท้ายในพรอมป์ระบบ- รายการ
userหรือfunction_call_outputล่าสุดจะกลายเป็น “ข้อความปัจจุบัน” - ข้อความ user/assistant ก่อนหน้าจะถูกรวมเป็นประวัติเพื่อใช้เป็นบริบท
function_call_output (เครื่องมือแบบอิง turn)
ส่งผลลัพธ์เครื่องมือกลับไปยังโมเดล:
{ "type": "function_call_output", "call_id": "call_123", "output": "{\"temperature\": \"72F\"}"}reasoning และ item_reference
รับเพื่อความเข้ากันได้ของสคีมา แต่ละเว้นเมื่อสร้างพรอมป์
เครื่องมือ (เครื่องมือฟังก์ชันฝั่งไคลเอนต์)
ให้เครื่องมือด้วย tools: [{ type: "function", function: { name, description?, parameters? } }]
หากเอเจนต์ตัดสินใจเรียกเครื่องมือ คำตอบจะส่งคืนรายการเอาต์พุต function_call
จากนั้นคุณส่งคำขอติดตามผลด้วย function_call_output เพื่อดำเนิน turn ต่อ
รูปภาพ (input_image)
รองรับแหล่งที่มาแบบ base64 หรือ URL:
{ "type": "input_image", "source": { "type": "url", "url": "https://example.com/image.png" }}ชนิด MIME ที่อนุญาต (ปัจจุบัน): image/jpeg, image/png, image/gif, image/webp, image/heic, image/heif
ขนาดสูงสุด (ปัจจุบัน): 10MB
ไฟล์ (input_file)
รองรับแหล่งที่มาแบบ base64 หรือ URL:
{ "type": "input_file", "source": { "type": "base64", "media_type": "text/plain", "data": "SGVsbG8gV29ybGQh", "filename": "hello.txt" }}ชนิด MIME ที่อนุญาต (ปัจจุบัน): text/plain, text/markdown, text/html, text/csv,
application/json, application/pdf
ขนาดสูงสุด (ปัจจุบัน): 5MB
ลักษณะการทำงานปัจจุบัน:
- เนื้อหาไฟล์จะถูกถอดรหัสและเพิ่มเข้าในพรอมป์ระบบ ไม่ใช่ข้อความผู้ใช้ ดังนั้นจึงคงเป็นแบบชั่วคราว (ไม่ถูกเก็บถาวรในประวัติเซสชัน)
- ข้อความไฟล์ที่ถอดรหัสแล้วจะถูกห่อเป็นเนื้อหาภายนอกที่ไม่น่าเชื่อถือก่อนเพิ่มเข้าไป ดังนั้นไบต์ของไฟล์จะถูกถือเป็นข้อมูล ไม่ใช่คำสั่งที่เชื่อถือได้
- บล็อกที่แทรกใช้เครื่องหมายขอบเขตที่ชัดเจน เช่น
<<<EXTERNAL_UNTRUSTED_CONTENT id="...">>>/<<<END_EXTERNAL_UNTRUSTED_CONTENT id="...">>>และมีบรรทัดเมทาดาทาSource: External - เส้นทางอินพุตไฟล์นี้จงใจละเว้นแบนเนอร์
SECURITY NOTICE:แบบยาวเพื่อ รักษางบประมาณพรอมป์ เครื่องหมายขอบเขตและเมทาดาทายังคงอยู่ครบ - PDF จะถูกแยกข้อความก่อน หากพบข้อความน้อย หน้าแรก ๆ จะถูก
แปลงเป็นภาพแรสเตอร์และส่งต่อให้โมเดล และบล็อกไฟล์ที่แทรกจะใช้
ตัวแทนข้อความ
[PDF content rendered to images]
การแยกวิเคราะห์ PDF จัดทำโดย Plugin document-extract ที่บันเดิลมา ซึ่งใช้บิลด์ legacy ของ pdfjs-dist ที่ใช้งานกับ Node ได้ดี (ไม่มีเวิร์กเกอร์) บิลด์ PDF.js สมัยใหม่คาดหวังเวิร์กเกอร์ของเบราว์เซอร์/ตัวแปรโกลบอล DOM จึงไม่ได้ใช้ใน Gateway
ค่าเริ่มต้นของการดึงข้อมูลจาก URL:
files.allowUrl:trueimages.allowUrl:truemaxUrlParts:8(จำนวนส่วนinput_file+input_imageที่อิง URL ทั้งหมดต่อคำขอ)- คำขอมีการป้องกัน (การแปลงชื่อ DNS, การบล็อก IP ส่วนตัว, เพดานการเปลี่ยนเส้นทาง, หมดเวลา)
- รองรับรายการอนุญาตชื่อโฮสต์แบบไม่บังคับตามชนิดอินพุต (
files.urlAllowlist,images.urlAllowlist)- โฮสต์แบบตรงตัว:
"cdn.example.com" - โดเมนย่อยแบบไวลด์การ์ด:
"*.assets.example.com"(ไม่ตรงกับโดเมนราก) - รายการอนุญาตที่ว่างหรือไม่ได้ระบุหมายถึงไม่มีข้อจำกัดรายการอนุญาตชื่อโฮสต์
- โฮสต์แบบตรงตัว:
- หากต้องการปิดการดึงข้อมูลที่อิง URL ทั้งหมด ให้ตั้งค่า
files.allowUrl: falseและ/หรือimages.allowUrl: false
ขีดจำกัดไฟล์ + รูปภาพ (การกำหนดค่า)
ปรับค่าเริ่มต้นได้ภายใต้ 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, }, }, }, }, },}ค่าเริ่มต้นเมื่อไม่ระบุ:
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- แหล่งที่มา HEIC/HEIF
input_imageจะถูกรับและทำให้เป็น JPEG ก่อนส่งให้ผู้ให้บริการ
หมายเหตุด้านความปลอดภัย:
- รายการอนุญาต URL จะถูกบังคับใช้ก่อนการดึงข้อมูลและในแต่ละขั้นของการเปลี่ยนเส้นทาง
- การใส่ชื่อโฮสต์ไว้ในรายการอนุญาตไม่ได้ข้ามการบล็อก IP ส่วนตัว/ภายใน
- สำหรับ Gateway ที่เปิดสู่อินเทอร์เน็ต ให้ใช้การควบคุมการออกเครือข่ายเพิ่มเติมจากการป้องกันระดับแอป ดู ความปลอดภัย
การสตรีม (SSE)
ตั้งค่า stream: true เพื่อรับ Server-Sent Events (SSE):
Content-Type: text/event-stream- แต่ละบรรทัดเหตุการณ์คือ
event: <type>และdata: <json> - สตรีมจบด้วย
data: [DONE]
ชนิดเหตุการณ์ที่ส่งออกในปัจจุบัน:
response.createdresponse.in_progressresponse.output_item.addedresponse.content_part.addedresponse.output_text.deltaresponse.output_text.doneresponse.content_part.doneresponse.output_item.doneresponse.completedresponse.failed(เมื่อเกิดข้อผิดพลาด)
การใช้งาน
usage จะถูกเติมค่าเมื่อผู้ให้บริการเบื้องหลังรายงานจำนวนโทเค็น
OpenClaw ทำให้นามแฝงทั่วไปแบบ OpenAI อยู่ในรูปแบบมาตรฐานก่อนที่ตัวนับเหล่านั้นจะไปถึง
พื้นผิวสถานะ/เซสชันปลายทาง รวมถึง input_tokens / output_tokens
และ prompt_tokens / completion_tokens
ข้อผิดพลาด
ข้อผิดพลาดใช้อ็อบเจ็กต์ JSON ลักษณะนี้:
{ "error": { "message": "...", "type": "invalid_request_error" } }กรณีทั่วไป:
401ไม่มี/การยืนยันตัวตนไม่ถูกต้อง400เนื้อหาคำขอไม่ถูกต้อง405เมธอดผิด
ตัวอย่าง
ไม่สตรีม:
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" }'สตรีม:
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" }'