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"
}'