เอกสารอ้างอิง API เอเจนต์ Jenova
URL พื้นฐาน: https://api.jenova.ai/v1
การยืนยันตัวตน: Bearer token ใน Authorization header
สารบัญ
- ภาพรวม
- เริ่มต้นใช้งานอย่างรวดเร็ว
- แนวคิดหลัก
- การยืนยันตัวตน
- จุดเชื่อมต่อ API
- การสตรีม (SSE)
- การผสานรวมเซิร์ฟเวอร์ MCP
- การเรียกเก็บเงิน
- การจำกัดอัตราการใช้งาน
- การจัดการข้อผิดพลาด
- การแบ่งหน้า
- การปรับให้เข้ากับท้องถิ่น
- ความเป็นส่วนตัวและข้อมูล
- การสนับสนุน
ภาพรวม
สร้างและรันเอเจนต์ AI ระดับพร้อมใช้งานจริงได้โดยไม่ต้องประกอบสแต็กเบื้องหลังด้วยตัวเอง Jenova Agent API รวมทุกความสามารถหลักไว้ในบริการที่มีการจัดการแบบครบวงจรเดียว:
สแต็กเอเจนต์แบบครบวงจร
- การประสานงานเอเจนต์ (Agent Orchestration): เลเยอร์การประสานงานแบบรวมศูนย์ที่ประสานโมเดล เครื่องมือ หน่วยความจำ และการค้นคืนข้อมูลตลอดเวิร์กโฟลว์ที่ซับซ้อน
- หน่วยความจำและบริบท: หน่วยความจำและบริบทของการสนทนาแบบไม่จำกัดถูกฝังอยู่ในทุกเซสชัน ไม่จำเป็นต้องมีการจัดการสถานะภายนอก
- เครื่องมือและ MCP: การผสานรวมเครื่องมือแบบไม่จำกัดกับเครื่องมือดั้งเดิมของแพลตฟอร์มและเซิร์ฟเวอร์ MCP ระยะไกลใด ๆ พร้อมใช้งานทันที
- ใช้โมเดลใดก็ได้: ขับเคลื่อนเอเจนต์ของคุณด้วยโมเดลจาก OpenAI, Anthropic, Google, xAI, Qwen และอื่น ๆ ผ่านการผสานรวมเพียงจุดเดียว
- พื้นที่จัดเก็บที่มีการจัดการครบวงจร: ฐานข้อมูลเชิงสัมพันธ์และฐานข้อมูลเวกเตอร์ที่มีการจัดการพร้อม RAG ในตัว ไม่ต้องจัดหาหรือปรับขนาดโครงสร้างพื้นฐานเอง
- ระดับพร้อมใช้งานจริง: ใช้งานโดยผู้ใช้หลายแสนคน โครงสร้างพื้นฐานที่มีการจัดการครบวงจร API ที่มีความเสถียร ออกแบบมาเพื่อรองรับทราฟฟิกระดับการใช้งานจริง
เริ่มต้นใช้งานอย่างรวดเร็ว
1. รับคีย์ API ของคุณ
สร้างคีย์ API จากแดชบอร์ดสำหรับนักพัฒนาที่ www.jenova.ai/platform คีย์จะมีรูปแบบ jnv_sk_* และถูกส่งในรูปแบบ Bearer token
2. เลือกหรือสร้างเอเจนต์
เลือกเอเจนต์ที่สร้างไว้ล่วงหน้าจากแพลตฟอร์ม หรือสร้างเอเจนต์แบบกำหนดเองในแดชบอร์ด พร้อมคำสั่ง การตั้งค่าโมเดล ไฟล์ฐานความรู้ เครื่องมือ และเซิร์ฟเวอร์ MCP
3. ส่งข้อความแรกของคุณ
สร้างเซสชันและส่งข้อความในการเรียกครั้งเดียว:
curl -N -X POST https://api.jenova.ai/v1/messages \
-H "Authorization: Bearer jnv_sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"agent": "my-support-agent",
"user": "user_12345",
"content": "What can you help me with?"
}'
การตอบกลับจะถูกสตรีมกลับมาในรูปแบบ Server-Sent Events:
event: stream_started
data: {"session_id":"ses_xyz789","run_id":"run_abc123","agent":"my-support-agent"}
event: stream_delta
data: {"session_id":"ses_xyz789","run_id":"run_abc123","chunk_content":"I can help you with ","seq":1}
event: stream_ended
data: {"session_id":"ses_xyz789","run_id":"run_abc123","success":true,"stop_reason":"end_run","usage":{"cost":"0.0032"}}
บันทึกค่า session_id จาก stream_started เพื่อใช้ในคำขอต่อไป สำหรับการตอบกลับแบบ JSON แบบซิงโครนัส ดู ส่งข้อความ
แนวคิดหลัก
เอเจนต์
เอเจนต์ AI ที่คุณโต้ตอบด้วยผ่าน API เอเจนต์แต่ละตัวมี slug ที่ไม่ซ้ำกัน (เช่น my-support-agent) ซึ่งใช้เป็นค่า agent ในการเรียก API
- สร้างไว้ล่วงหน้า: เลือกจากเอเจนต์ที่มีอยู่แล้วบนแพลตฟอร์ม
- กำหนดเอง: กำหนดค่าเอเจนต์ของคุณเองในแดชบอร์ด พร้อมคำสั่ง โมเดล ฐานความรู้ เครื่องมือ และเซิร์ฟเวอร์ MCP
เซสชัน
เธรดการสนทนาที่เป็นอิสระระหว่างผู้ใช้ปลายทางและเอเจนต์
- ตัวระบุ: ID ที่มีคำนำหน้า (เช่น
ses_abc123) - ขอบเขต: สามารถมีหลายเซสชันสำหรับเอเจนต์และผู้ใช้ปลายทางเดียวกันได้ โดยแต่ละเซสชันมีสถานะการสนทนาที่เป็นอิสระ
- วงจรชีวิต: เซสชันจะคงอยู่อย่างไม่มีกำหนดจนกว่าจะถูกลบผ่าน API สำหรับงานแบบครั้งเดียวที่ไม่ต้องจัดเก็บข้อมูล ให้ใช้
POST /messagesพร้อมephemeral: true - การแยกแพลตฟอร์ม: เซสชันของ API แยกออกจากการสนทนาในเว็บแอป Jenova ผู้ใช้ปลายทาง ประวัติเซสชัน และการเรียกเก็บเงินเป็นอิสระต่อกันระหว่าง API และเว็บแอป
ข้อความ
รายการเดียวในประวัติการสนทนาของเซสชัน ซึ่งส่งกลับโดยจุดเชื่อมต่อ Messages ข้อความแต่ละรายการมีอ็อบเจ็กต์ from ที่มีโครงสร้าง ประกอบด้วย type ("user" หรือ "agent") และ name รวมถึง type ของข้อความ:
external- ข้อความในการสนทนาที่ตั้งใจให้แสดงเป็นเนื้อหาแชทinternal- ข้อความไม่บังคับที่แสดงถึงขั้นตอนการทำงานของเอเจนต์ระหว่างการรัน เช่น การเรียกใช้เครื่องมือหรือการค้นคืนข้อมูล
การรัน
การทำงานของเอเจนต์เพียงครั้งเดียวที่ถูกสร้างขึ้นเมื่อคุณส่งข้อความ การรันหนึ่งครั้งจะมี run_id อาจสตรีมอีเวนต์ระหว่างที่กำลังทำงานอยู่ และสร้างข้อความที่เสร็จสมบูรณ์อย่างน้อยหนึ่งรายการ แต่ละเซสชันสามารถมีการรันที่กำลังทำงานอยู่ได้เพียงหนึ่งครั้งในเวลาเดียวกัน
ผู้ใช้ปลายทาง
ฟิลด์ user กำหนดขอบเขตของเซสชันให้กับผู้ใช้ปลายทางในแอปพลิเคชันของคุณ ใช้ ID ที่คงที่และไม่มีความหมายในตัวเอง (opaque) เช่น ID ผู้ใช้ภายในของคุณหรือ UUID หลีกเลี่ยงการใช้อีเมลหรือ PII อื่น ๆ เว้นแต่แอปพลิเคชันของคุณจำเป็นต้องใช้ เซสชันที่สร้างด้วยค่า user เดียวกันจะถูกจัดกลุ่มเข้าด้วยกัน ทำให้สามารถแสดงรายการเซสชันตามผู้ใช้แต่ละรายได้
หากไม่ระบุ user เซสชันจะถูกกำหนดขอบเขตให้กับบัญชีนักพัฒนาของคุณ และจะไม่สามารถกรองตามผู้ใช้ปลายทางได้ในภายหลัง ให้ส่ง user เสมอในสภาพแวดล้อมที่ใช้งานจริง
สำหรับคำขอเกี่ยวกับเซสชันที่มีอยู่แล้ว user เป็นตัวป้องกันความเป็นเจ้าของที่ไม่บังคับ หากคุณระบุค่านี้ ค่าดังกล่าวต้องตรงกับค่า user ที่ใช้ตอนสร้างเซสชัน มิฉะนั้น API จะส่งกลับ 404 session_not_owned ให้ส่งค่านี้เป็นพารามิเตอร์คิวรีในคำขอ GET และ DELETE และส่งในเนื้อหา JSON สำหรับคำขอ POST และ PATCH
การยืนยันตัวตน
ยืนยันตัวตนทุกคำขอด้วย Bearer token ในส่วนหัว Authorization:
Authorization: Bearer jnv_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
คีย์ API ถูกสร้างขึ้นจากแดชบอร์ดสำหรับนักพัฒนา
User-Agent เป็นทางเลือกไม่บังคับ SDK อาจตั้งค่านี้เพื่อการวินิจฉัย แต่ API ไม่จำเป็นต้องใช้
รูปแบบคีย์: คีย์เริ่มต้นด้วยพรีฟิกซ์ jnv_sk_ ตามด้วยสตริงสุ่มที่เข้ารหัสแบบ base62
ขีดจำกัด: บัญชีนักพัฒนาแต่ละบัญชีสามารถมี คีย์ API ที่ใช้งานอยู่ได้สูงสุด 10 คีย์
จุดเชื่อมต่อ API
API ข้อความ
การส่งข้อความคือเส้นทาง API หลัก ใช้ POST /messages สำหรับข้อความแรก ซึ่งจะสร้างเซสชันและเริ่มการรันในคำขอเดียว ใช้ POST /sessions/{session_id}/messages เมื่อดำเนินการต่อจาก session_id ที่บันทึกไว้
ส่งข้อความ
POST /messages
สร้างเซสชันแบบถาวรและส่งข้อความแรกในคำขอแบบอะตอมมิกเดียว กำหนด ephemeral: true สำหรับคำขอแบบครั้งเดียวที่สตรีมอย่างเดียวโดยไม่มีการจัดเก็บข้อมูล ซึ่งจะไม่จัดเก็บเซสชันหรือประวัติข้อความ ไม่ส่งกลับ session ID และไม่สามารถดำเนินการต่อได้
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|---|
agent | string | ใช่ | - | slug ที่ระบุตัวตนของเอเจนต์ |
content | string | ตามเงื่อนไข | - | ข้อความ จำเป็นต้องระบุ เว้นแต่มีการระบุ file_urls |
file_urls | string[] | ตามเงื่อนไข | - | URL ของไฟล์ที่จะแนบ จำเป็นต้องระบุ เว้นแต่มีการระบุ content |
user | string | ไม่ | - | ตัวระบุผู้ใช้ปลายทางภายนอกของคุณ (สูงสุด 255 ตัวอักษร) หากไม่ระบุ จะใช้ค่าเริ่มต้นเป็นบัญชีนักพัฒนาของคุณ |
session_name | string | ไม่ | - | ชื่อที่แสดงสำหรับเซสชันใหม่ (สูงสุด 200 ตัวอักษร) |
ephemeral | boolean | ไม่ | false | คำขอแบบครั้งเดียวที่สตรีมอย่างเดียวโดยไม่มีการจัดเก็บข้อมูล ไม่จัดเก็บเซสชันหรือประวัติข้อความ ไม่ส่งกลับ session ID และไม่สามารถดำเนินการต่อได้ |
stream | boolean | ไม่ | true | true สำหรับการสตรีมแบบ SSE, false สำหรับ JSON การอนุญาตสิทธิ์ของ MCP ต้องใช้การสตรีม |
model | string | ไม่ | - | การกำหนดโมเดลแทนที่แบบครั้งเดียวสำหรับคำขอนี้เท่านั้น ใช้ ID โมเดลที่มั่นคง เช่น claude-sonnet-5 ไม่เปลี่ยนแปลงโมเดลเริ่มต้นของเซสชัน |
ตัวอย่าง - การสตรีม (ค่าเริ่มต้น)
curl -N -X POST https://api.jenova.ai/v1/messages \
-H "Authorization: Bearer jnv_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"agent": "my-support-agent",
"user": "user_12345",
"content": "Hello, I need help with my account"
}'
การตอบกลับเป็นสตรีม SSE (ดู การสตรีม (SSE) สำหรับรูปแบบอีเวนต์) คำขอแบบถาวรจะรวม session_id ใหม่ ส่วนคำขอ ephemeral: true จะไม่มี session_id และต้องใช้การสตรีม
ตัวอย่าง - JSON (ไม่สตรีม)
curl -X POST https://api.jenova.ai/v1/messages \
-H "Authorization: Bearer jnv_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"agent": "my-support-agent",
"user": "user_12345",
"content": "Hello, I need help with my account",
"stream": false
}'
การตอบกลับ
การตอบกลับแบบสตรีมจะส่งอีเวนต์ SSE ตามที่ระบุไว้ใน การสตรีม (SSE) การตอบกลับแบบไม่สตรีมจะส่งกลับรูปแบบ JSON ของข้อความตามที่แสดงไว้ใน ดำเนินเซสชันต่อ รวมถึง stop_reason และ usage สำหรับคำขอที่เสร็จสมบูรณ์
หากการรันแบบไม่สตรีมยังอยู่ในระหว่างประมวลผลหลังจาก 90 วินาที API จะส่งกลับ 202 Accepted พร้อมด้วย status: "processing", session_id, run_id และ message การรันจะดำเนินต่อไปหลังจากการตอบกลับหรือการตัดการเชื่อมต่อของไคลเอนต์ ตรวจสอบข้อความของเซสชัน หรือใช้การสตรีมสำหรับกระบวนการทำงานที่ยาวขึ้น
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | missing_required_field | ต้องระบุ agent |
| 400 | invalid_payload | JSON มีรูปแบบไม่ถูกต้อง หรือฟิลด์มีประเภทข้อมูลไม่ถูกต้อง |
| 400 | bad_request | โหมด ephemeral ไม่ถูกต้อง หรือ user/session_name เกินความยาวสูงสุด |
| 400 | content_or_uploaded_files_required | ไม่มีการระบุทั้ง content และ file_urls |
| 400 | content_too_long | เนื้อหาข้อความเกินความยาว token สูงสุด |
| 400 | exceed_max_upload_files | มี URL ไฟล์มากกว่า 10 รายการในคำขอเดียว |
| 400 | unsupported_file_format | URL ไฟล์มีนามสกุลไฟล์ที่ไม่รองรับ |
| 400 | invalid_file_url | URL ไฟล์มีรูปแบบไม่ถูกต้อง หรือไม่ใช่ HTTPS |
| 400 | invalid_model_selection | โมเดลที่กำหนดแทนที่ไม่ใช่โมเดลที่ใช้งานจริงที่ถูกต้อง |
| 402 | insufficient_credits | เครดิตไม่พอสำหรับการสร้างเซสชันหรือส่งข้อความ |
| 404 | agent_not_found | เอเจนต์ไม่มีอยู่ หรือบัญชีของคุณไม่สามารถเข้าถึงได้ |
ดำเนินเซสชันต่อ
POST /sessions/{session_id}/messages
ส่งข้อความไปยังเซสชันแบบต่อเนื่อง (persistent session) ที่มีอยู่แล้ว และรับการตอบกลับจากเอเจนต์ โดยค่าเริ่มต้นการตอบกลับจะสตรีมผ่าน SSE ตั้งค่า stream: false เพื่อรับผลลัพธ์เป็น JSON
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|---|
content | string | มีเงื่อนไข | - | ข้อความ จำเป็นต้องระบุ เว้นแต่มีการระบุ file_urls |
file_urls | string[] | มีเงื่อนไข | - | URL ของไฟล์ที่จะแนบ จำเป็นต้องระบุ เว้นแต่มีการระบุ content |
stream | boolean | ไม่บังคับ | true | true สำหรับการสตรีมผ่าน SSE, false สำหรับ JSON การให้สิทธิ์ MCP จำเป็นต้องใช้การสตรีม |
model | string | ไม่บังคับ | - | การกำหนดโมเดลเฉพาะครั้งสำหรับคำขอนี้เท่านั้น ใช้ ID โมเดลที่เสถียร เช่น claude-sonnet-5 การตั้งค่านี้ไม่เปลี่ยนโมเดลเริ่มต้นของเซสชัน |
ตัวอย่าง - การสตรีม (ค่าเริ่มต้น)
curl -N -X POST https://api.jenova.ai/v1/sessions/ses_abc123/messages \
-H "Authorization: Bearer jnv_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"content": "How do I reset my password?"
}'
ตัวอย่าง - JSON (ไม่สตรีม)
curl -X POST https://api.jenova.ai/v1/sessions/ses_abc123/messages \
-H "Authorization: Bearer jnv_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"content": "How do I reset my password?",
"stream": false
}'
การตอบกลับ 200 OK
{
"id": "msg_xyz789",
"session_id": "ses_abc123",
"sequence": 4,
"from": {
"type": "agent",
"name": "my-support-agent"
},
"type": "external",
"time": "2026-05-19T10:31:05Z",
"content": "To reset your password, go to Settings > Security > Change Password...",
"model": "claude-sonnet-5",
"files": [],
"stop_reason": "end_run",
"usage": {
"cost": "0.0015"
}
}
หากเซสชันมีการรันที่กำลังทำงานอยู่หรือมีข้อความอยู่ในคิวแล้ว API จะส่งกลับ JSON 202 Accepted พร้อม status: "queued", session_id, run_id, และ message_id ข้อความของผู้ใช้จะถูกประมวลผลโดยการรันที่กำลังทำงานอยู่
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | invalid_payload | JSON มีรูปแบบไม่ถูกต้อง หรือฟิลด์มีประเภทข้อมูลไม่ถูกต้อง |
| 400 | content_or_uploaded_files_required | ไม่มีการระบุทั้ง content และ file_urls |
| 400 | content_too_long | เนื้อหาข้อความเกินความยาว token สูงสุดที่กำหนด |
| 400 | exceed_max_upload_files | มี URL ไฟล์มากกว่า 10 รายการในคำขอเดียว |
| 400 | unsupported_file_format | URL ไฟล์มีนามสกุลไฟล์ที่ไม่รองรับ |
| 400 | invalid_file_url | URL ไฟล์มีรูปแบบไม่ถูกต้องหรือไม่ใช่ HTTPS |
| 400 | invalid_model_selection | การกำหนดโมเดลไม่ใช่โมเดลที่ใช้งานจริง (production model) ที่ถูกต้อง |
| 402 | insufficient_credits | มีเครดิตไม่เพียงพอสำหรับการส่งข้อความ |
| 404 | session_not_found | ไม่พบเซสชันที่ระบุ |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
Idempotency
POST /messages และ POST /sessions/{session_id}/messages รองรับส่วนหัว Idempotency-Key แบบไม่บังคับ ใช้คีย์ที่ไม่ซ้ำกันสำหรับการส่งของผู้ใช้ในแต่ละครั้งตามหลักตรรกะ เพื่อไม่ให้การลองใหม่ของเครือข่ายหรือการส่งซ้ำสองครั้งสร้างการรันที่ซ้ำกัน
curl -N -X POST https://api.jenova.ai/v1/messages \
-H "Authorization: Bearer jnv_sk_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: send-user_12345-2026-05-19T10:30:00Z" \
-d '{
"agent": "my-support-agent",
"user": "user_12345",
"content": "Hello"
}'
ไม่ใช้การสตรีม: การลองใหม่จะส่งคืนการตอบกลับ 200 หรือ 202 ที่บันทึกไว้พร้อมส่วนหัว Idempotent-Replayed: true
การสตรีม: สตรีมจะไม่ถูกเล่นซ้ำ การลองใหม่ในระหว่างที่กำลังรันอยู่หรือหลังจากเสร็จสมบูรณ์แล้วจะส่งคืนข้อผิดพลาดเกี่ยวกับ idempotency พร้อม run_id เดิม และสำหรับคำขอแบบถาวรจะมี session_id ด้วย ใช้ GET /sessions/{session_id}/runs/{run_id} เพื่อตรวจสอบการรันที่กำลังทำงานอยู่ หรือ GET /sessions/{session_id}/messages เพื่อดึงผลลัพธ์ที่ถูกบันทึกไว้แล้ว
ตัวอย่างการลองใหม่ของการสตรีมที่เสร็จสมบูรณ์แล้ว:
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"error": {
"code": "idempotency_key_reused",
"message": "This Idempotency-Key has already completed. Streaming responses cannot be replayed; use the returned session_id and run_id to retrieve the result."
},
"idempotency": {
"status": "completed",
"session_id": "ses_abc123",
"run_id": "run_abc123"
}
}
ข้อผิดพลาดเกี่ยวกับ idempotency
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 409 | idempotency_key_reused | มีการใช้คีย์เดียวกันกับคำขอที่แตกต่างกัน |
| 409 | idempotency_key_in_use | คำขอเดิมยังคงทำงานอยู่ |
| 409 | idempotency_key_reused | คำขอสตรีมเดิมเสร็จสมบูรณ์ไปแล้วและไม่สามารถเล่นซ้ำได้ |
รายการข้อความ
GET /sessions/{session_id}/messages
ส่งกลับรายการข้อความสนทนาที่มองเห็นได้แบบแบ่งหน้า หน้าแรกจะมีข้อความล่าสุด และในแต่ละหน้า ข้อความจะเรียงตามลำดับเวลา (จากเก่าไปใหม่) sequence เป็นเลขลำดับที่มั่นคงภายในเซสชัน
พารามิเตอร์คิวรี
| พารามิเตอร์ | ประเภท | ค่าเริ่มต้น | สูงสุด | คำอธิบาย |
|---|---|---|---|---|
limit | integer | 20 | 100 | จำนวนข้อความต่อหน้า |
cursor | string | - | - | เคอร์เซอร์สำหรับการแบ่งหน้า |
ตัวอย่าง
curl "https://api.jenova.ai/v1/sessions/ses_abc123/messages?limit=50" \
-H "Authorization: Bearer jnv_sk_xxx"
การตอบกลับ 200 OK
{
"items": [
{
"id": "msg_002",
"session_id": "ses_abc123",
"sequence": 4,
"from": {
"type": "agent",
"name": "my-support-agent"
},
"type": "external",
"time": "2026-05-19T10:31:05Z",
"content": "To reset your password, go to Settings > Security...",
"model": "claude-sonnet-5",
"files": []
}
],
"next_cursor": "",
"has_more": false
}
อ็อบเจ็กต์ข้อความ
| ฟิลด์ | ประเภท | คำอธิบาย |
|---|---|---|
id | string | ID ของข้อความ (มีคำนำหน้า msg_) |
session_id | string | ID ของเซสชันหลัก |
sequence | integer | เลขลำดับที่มั่นคงภายในเซสชัน |
from | object | อ็อบเจ็กต์ผู้ส่งซึ่งมี type ("user" หรือ "agent") และ name |
type | string | ประเภทของข้อความ ปกติจะเป็น external สำหรับข้อความสนทนาที่มองเห็นได้ |
time | string | timestamp แบบ ISO 8601 |
content | string | เนื้อหาข้อความ มีอยู่ในข้อความประเภท external |
model | string | ID ของโมเดลที่ใช้สร้างการตอบกลับแบบคงที่ มีอยู่เฉพาะในข้อความของเอเจนต์เท่านั้น |
files | array | ไฟล์ที่แนบมาหรือถูกสร้างขึ้นซึ่งรวมอยู่กับข้อความ แต่ละรายการมี file_id, name, url, format และ size เมื่อทราบข้อมูล |
stop_reason | string | มีอยู่ในข้อความของเอเจนต์ที่เสร็จสมบูรณ์ ค่าปัจจุบันคือ end_run |
agent | string | slug ของเอเจนต์ที่ทำการรัน เมื่อมีข้อมูล |
agent_name | string | ชื่อที่แสดงของเอเจนต์ที่ทำการรัน เมื่อมีข้อมูล |
อ็อบเจ็กต์ไฟล์
| ฟิลด์ | ประเภท | คำอธิบาย |
|---|---|---|
file_id | string | ID ไฟล์ของ Jenova เมื่อมีข้อมูล |
name | string | ชื่อไฟล์ |
url | string | URL ของไฟล์ เมื่อมีข้อมูล |
format | string | รูปแบบไฟล์เป็นตัวพิมพ์เล็ก เช่น pdf, png หรือ csv |
size | integer | ขนาดไฟล์เป็นไบต์ เมื่อทราบข้อมูล |
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | bad_request | พารามิเตอร์คิวรีไม่ถูกต้อง |
| 404 | session_not_found | ไม่มีเซสชันนี้อยู่ |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุมา |
รับข้อความ
GET /sessions/{session_id}/messages/{message_id}
ดึงข้อมูลข้อความที่มองเห็นได้รายการเดียวตาม ID
การตอบกลับ 200 OK
ส่งกลับอ็อบเจ็กต์ข้อความรายการเดียวที่มีโครงสร้างเหมือนกับการตอบกลับแบบรายการ
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 404 | session_not_found | ไม่มีเซสชันนี้อยู่ |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุมา |
| 404 | not_found | ไม่มีข้อความนี้อยู่ในเซสชันนี้ |
ไฟล์แนบ
ส่ง URL แบบ HTTPS ที่เข้าถึงได้แบบสาธารณะในฟิลด์ file_urls
| ขีดจำกัด | ค่า |
|---|---|
| จำนวนไฟล์สูงสุดต่อข้อความ | 10 |
| ขนาดไฟล์สูงสุด | 20 MB ต่อไฟล์ |
รูปแบบที่รองรับ
- รูปภาพ: JPG, JPEG, PNG, WebP
- เอกสาร: PDF, DOCX, XLSX, PPTX, TXT, CSV, RTF, MD, HTML, XML, JSON, LOG
- โค้ด: JS, TS, TSX, JSX, PY, Java, Go, C, CPP, H, HPP, CS, RB, PHP, RS, Swift, KT, Scala, SQL, CSS, YAML, YML
เมื่อแสดงรายการข้อความ ไฟล์ที่แนบมาจะปรากฏในอาร์เรย์ files ของข้อความ
API เซสชัน
เซสชันคือบทสนทนาที่คงอยู่ระหว่างผู้ใช้ปลายทางและเอเจนต์ การผสานรวมส่วนใหญ่สามารถสร้างเซสชันได้โดยปริยายผ่าน POST /messages
สร้างเซสชัน
POST /sessions
สร้างเซสชันที่ยังไม่มีข้อมูลใดๆ (empty persistent session) ซึ่งผูกกับเอเจนต์ที่ระบุ ใช้กรณีที่คุณต้องการรับ session ID ก่อนส่งข้อความแรก แต่โดยทั่วไปแล้วแนะนำให้ใช้ POST /messages แทน
หมายเหตุ:
ephemeralไม่สามารถใช้กับPOST /sessionsได้ หากต้องการส่งคำขอแบบครั้งเดียวโดยไม่จัดเก็บข้อมูล ให้ใช้POST /messagesพร้อมกับephemeral: true
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
agent | string | จำเป็น | slug identifier ของเอเจนต์ |
user | string | ไม่บังคับ | ตัวระบุผู้ใช้ปลายทางภายนอกของคุณ (สูงสุด 255 ตัวอักษร) หากไม่ระบุ จะใช้ค่าเริ่มต้นเป็นบัญชีนักพัฒนาของคุณ |
session_name | string | ไม่บังคับ | ชื่อที่แสดงของเซสชัน (สูงสุด 200 ตัวอักษร) |
ตัวอย่าง
curl -X POST https://api.jenova.ai/v1/sessions \
-H "Authorization: Bearer jnv_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"agent": "my-support-agent",
"user": "user_12345",
"session_name": "Billing inquiry"
}'
การตอบกลับ 201 Created
{
"id": "ses_abc123",
"session_name": "Billing inquiry",
"agent": "my-support-agent",
"user": "user_12345",
"model": "claude-sonnet-5",
"created_at": "2026-05-19T10:30:00Z",
"updated_at": "2026-05-19T10:30:00Z"
}
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | invalid_payload | JSON มีรูปแบบไม่ถูกต้อง หรือฟิลด์มีประเภทข้อมูลไม่ถูกต้อง |
| 400 | missing_required_field | agent เป็นฟิลด์ที่จำเป็น |
| 400 | bad_request | มีการระบุ ephemeral หรือ user/session_name มีความยาวเกินขีดจำกัดที่กำหนด |
| 402 | insufficient_credits | เครดิตไม่เพียงพอสำหรับการสร้างเซสชัน |
| 404 | agent_not_found | ไม่พบเอเจนต์ หรือบัญชีของคุณไม่มีสิทธิ์เข้าถึงเอเจนต์นี้ |
รายการเซสชัน
GET /sessions
ส่งกลับรายการเซสชันของคุณแบบแบ่งหน้า โดยเรียงตามลำดับการอัปเดตล่าสุดก่อน
พารามิเตอร์คิวรี
| พารามิเตอร์ | ประเภท | คำอธิบาย |
|---|---|---|
limit | integer | จำนวนรายการต่อหน้า (ค่าเริ่มต้น 20 สูงสุด 100) |
cursor | string | cursor สำหรับการแบ่งหน้า |
user | string | กรองตามตัวระบุผู้ใช้ปลายทาง (สูงสุด 255 ตัวอักษร) |
agent | string | กรองตาม slug ของเอเจนต์ |
ตัวอย่าง
curl "https://api.jenova.ai/v1/sessions?user=user_12345&limit=10" \
-H "Authorization: Bearer jnv_sk_xxx"
การตอบกลับ 200 OK
{
"items": [
{
"id": "ses_abc123",
"session_name": "Billing inquiry",
"agent": "my-support-agent",
"user": "user_12345",
"model": "claude-sonnet-5",
"created_at": "2026-05-19T10:30:00Z",
"updated_at": "2026-05-19T11:15:00Z"
}
],
"next_cursor": "eyJ2IjoxLCJrIjoiY3VyXzAxIn0",
"has_more": true
}
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | bad_request | พารามิเตอร์คิวรีไม่ถูกต้อง |
รับเซสชัน
GET /sessions/{session_id}
ดึงข้อมูลเซสชันเดียวตาม ID
การตอบกลับ 200 OK
ส่งกลับออบเจ็กต์เซสชันในรูปแบบเดียวกันกับการตอบกลับของการสร้างเซสชัน
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
เปลี่ยนชื่อเซสชัน
PATCH /sessions/{session_id}
อัปเดตชื่อที่แสดงของเซสชัน
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
session_name | string | ใช่ | ชื่อที่แสดงใหม่ (ไม่เกิน 200 ตัวอักษร) |
การตอบกลับ 200 OK
ส่งกลับอ็อบเจ็กต์เซสชันที่อัปเดตแล้ว
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | invalid_payload | JSON มีรูปแบบไม่ถูกต้อง หรือฟิลด์มีประเภทไม่ถูกต้อง |
| 400 | missing_required_field | ต้องระบุ session_name |
| 400 | bad_request | session_name มีความยาวเกินขีดจำกัดที่กำหนด |
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
ลบเซสชัน
DELETE /sessions/{session_id}
ลบเซสชันและข้อความทั้งหมดในเซสชันอย่างถาวร เซสชันต้องไม่มีการรันที่กำลังทำงานอยู่
การตอบกลับ 204 No Content
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
| 409 | busy | เซสชันมีการรันที่กำลังทำงานอยู่ - โปรดยกเลิกก่อน |
การดำเนินการ
จุดเชื่อมต่อเหล่านี้เป็นตัวควบคุมสำหรับการกู้คืนและการแก้ไขเซสชันแบบต่อเนื่อง การผสานรวมส่วนใหญ่ต้องการเพียงการยกเลิกเท่านั้น ให้ใช้การดำเนินการอื่น ๆ เมื่อคุณตั้งใจที่จะเปลี่ยนแปลงหรือกู้คืนสถานะของเซสชัน การดำเนินการทั้งหมดสนับสนุนตัวป้องกันความเป็นเจ้าของ user แบบไม่บังคับที่อธิบายไว้ใน ผู้ใช้ปลายทาง
ยกเลิกการรันที่กำลังทำงาน
POST /sessions/{session_id}/cancel
ยกเลิกการรันของเอเจนต์ที่กำลังดำเนินการอยู่ในปัจจุบัน การดำเนินการนี้จะไม่ลบข้อความที่เสร็จสมบูรณ์แล้วก่อนการยกเลิก
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
run_id | string | ไม่ | ตัวป้องกันการรันที่ล้าสมัยแบบไม่บังคับ หากระบุและไม่ตรงกับการรันที่กำลังทำงานอยู่ API จะส่งกลับ 409 stale_run |
การตอบกลับ 204 No Content
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | cancel_not_allowed | ไม่มีการรันที่กำลังทำงานให้ยกเลิก หรือไม่อนุญาตให้ยกเลิก |
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
| 409 | stale_run | run_id ที่ระบุไม่ตรงกับการรันที่กำลังทำงานอยู่ |
เลิกทำการรันที่กำลังทำงาน
POST /sessions/{session_id}/undo
ยกเลิกการรันที่กำลังทำงาน รอให้หยุดทำงาน แล้วลบข้อความใด ๆ ที่ถูกเพิ่มเข้ามาแล้ว จะไม่มีการบันทึกผลลัพธ์เพิ่มเติมหลังจากมีการเลิกทำ
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
run_id | string | ไม่ | ตัวป้องกันการรันที่ล้าสมัยแบบไม่บังคับ หากระบุและไม่ตรงกับการรันที่กำลังทำงานอยู่ API จะส่งกลับ 409 stale_run |
การตอบกลับ 200 OK
{
"session_id": "ses_abc123",
"run_id": "run_abc123",
"deleted": ["msg_002", "msg_001"]
}
หากการรันถูกยกเลิกก่อนที่ข้อความใด ๆ จะเสร็จสมบูรณ์ deleted จะเป็นอาร์เรย์ว่าง
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | cancel_not_allowed | ไม่มีการรันที่กำลังทำงานให้เลิกทำ หรือไม่อนุญาตให้ยกเลิก |
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันนี้เป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
| 409 | stale_run | run_id ที่ระบุไม่ตรงกับการรันที่กำลังทำงานอยู่ |
| 409 | busy | เซสชันไม่สามารถใช้งานได้ชั่วคราวเนื่องจากมีการอัปเดตอื่นกำลังดำเนินการอยู่ |
ลบข้อความล่าสุด
POST /sessions/{session_id}/messages/delete
ลบข้อความล่าสุด N ข้อความออกจากเซสชันที่อยู่ในสถานะไม่ทำงาน เซสชันต้องไม่มีการรันที่กำลังทำงานอยู่
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
count | integer | ใช่ | จำนวนข้อความล่าสุดที่จะลบจากท้ายสุด (ต้องมากกว่า 0) |
การตอบกลับ 200 OK
{
"deleted": ["msg_002", "msg_001"]
}
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | bad_request | ไม่มี count, เป็นศูนย์, หรือเป็นค่าลบ; หรือไม่มีข้อความให้ลบ |
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันเป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
| 409 | busy | เซสชันมีการรันที่กำลังทำงานอยู่ |
ฟอร์กเซสชัน
POST /sessions/{session_id}/fork
สร้างเซสชันใหม่โดยคัดลอกเซสชันต้นทางไปจนถึงข้อความที่ระบุ เซสชันต้นทางต้องไม่มีการรันที่กำลังทำงานอยู่
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
message_id | string | ไม่ | ID ของข้อความที่เป็นจุดฟอร์ก หากไม่ระบุ จะฟอร์กจากข้อความล่าสุด |
การตอบกลับ 201 Created
ส่งกลับอ็อบเจ็กต์เซสชันที่สร้างขึ้นใหม่ ซึ่งมีโครงสร้างเดียวกับการสร้างเซสชัน
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | bad_request | message_id ไม่ถูกต้อง |
| 402 | insufficient_credits | เครดิตไม่เพียงพอสำหรับการฟอร์กเซสชัน |
| 404 | not_found | ไม่พบ message_id ในเซสชันนี้ |
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันเป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
| 409 | busy | เซสชันต้นทางมีการรันที่กำลังทำงานอยู่ |
รับสถานะการรัน
GET /sessions/{session_id}/runs/{run_id}
ส่งกลับสถานะปัจจุบันของการรันที่กำลังทำงานอยู่ ใช้สิ่งนี้หลังจากการเชื่อมต่อ SSE หลุด หรือหลังได้รับการตอบกลับแบบ idempotency ที่ส่งกลับ run_id มา หลังจากการรันเสร็จสิ้น ให้ดึงผลลัพธ์ด้วย GET /sessions/{session_id}/messages
การตอบกลับ 200 OK
{
"session_id": "ses_abc123",
"run_id": "run_abc123",
"status": "streaming",
"started_at": "2026-05-19T10:30:00Z",
"updated_at": "2026-05-19T10:30:06Z",
"content": "Partial visible response text so far"
}
การตอบกลับอาจรวมคำแนะนำความคืบหน้าล่าสุดในขณะที่การรันยังทำงานอยู่ด้วย
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | bad_request | เซสชันเป็นแบบชั่วคราว |
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | เซสชันเป็นของนักพัฒนารายอื่น หรือไม่ตรงกับ user ที่ระบุ |
| 404 | not_found | การรันนี้ไม่ได้กำลังทำงานอยู่สำหรับเซสชันนี้ |
เครดิต
รับยอดคงเหลือ
GET /credits/balance
ส่งกลับยอดเครดิตคงเหลือปัจจุบันของคุณ
การตอบกลับ 200 OK
{
"balance": "123.45"
}
API เอเจนต์
สร้างและแก้ไขเอเจนต์แบบกำหนดเองได้ในแดชบอร์ด การสนับสนุน API สำหรับการสร้างและแก้ไขเอเจนต์จะเปิดให้ใช้งานเร็ว ๆ นี้
เวิร์กโฟลว์แบบตั้งเวลา/เบื้องหลังยังไม่ได้รับการสนับสนุนผ่าน API ในขณะนี้ การสนับสนุนจะเปิดให้ใช้งานเร็ว ๆ นี้
รายการเอเจนต์
GET /agents
ส่งกลับรายการเอเจนต์ที่พร้อมใช้งานสำหรับคีย์ API ของคุณ ใช้ค่า agent เมื่อสร้างเซสชันหรือส่งข้อความ
การตอบกลับ 200 OK
{
"agents": [
{
"agent": "jenova",
"display_name": "Jenova",
"description": "General-purpose Jenova agent"
},
{
"agent": "my-support-agent",
"display_name": "Support Agent",
"description": "Answers customer questions"
}
]
}
| ฟิลด์ | ประเภท | คำอธิบาย |
|---|---|---|
agent | string | slug ของเอเจนต์ที่คงที่ ใช้ส่งเป็นค่า agent |
display_name | string | ชื่อที่แสดงในรูปแบบที่มนุษย์อ่านได้ |
description | string | คำอธิบายเอเจนต์ |
โมเดล
รายการโมเดล
GET /models
ส่งกลับโมเดลทั้งหมดที่สามารถใช้ในฟิลด์ model เมื่อส่งข้อความ
การตอบกลับ 200 OK
{
"models": [
{
"id": "claude-opus-4-8",
"name": "Claude Opus 4.8",
"thinking_variant": "claude-opus-4-8-thinking"
},
{
"id": "claude-opus-4-8-thinking",
"name": "Claude Opus 4.8 (Thinking)"
},
{
"id": "kimi-k2.6",
"name": "Kimi K2.6",
"thinking_variant": "kimi-k2.6-thinking"
}
]
}
| ฟิลด์ | ประเภท | คำอธิบาย |
|---|---|---|
id | string | ตัวระบุโมเดลที่คงที่ ใช้ส่งเป็นค่า model ใน Send Message |
name | string | ชื่อที่แสดงในรูปแบบที่มนุษย์อ่านได้ |
thinking_variant | string | ID ของโมเดลรูปแบบ thinking/reasoning มีอยู่เฉพาะในโมเดลพื้นฐานที่รองรับการให้เหตุผลเท่านั้น |
โมเดลที่มี thinking_variant รองรับการให้เหตุผลแบบขยาย (extended reasoning) ใช้ ID ของรูปแบบนี้โดยตรงในฟิลด์ model เพื่อเปิดใช้งาน
หากไม่ได้ระบุ model เมื่อส่งข้อความ ระบบจะใช้โมเดลเริ่มต้นของเอเจนต์
เอกสาร
GET /docs?lang=en
GET /doc?lang=en
ส่งกลับเอกสารอ้างอิงนี้ในรูปแบบ Markdown ใช้ lang เพื่อเลือกภาษา
การสตรีม (SSE)
เมื่อไม่ได้ระบุ stream หรือระบุเป็น true (ค่าเริ่มต้น) การตอบกลับข้อความจะถูกส่งในรูปแบบ Server-Sent Events ใช้อีเวนต์ message_completed เพื่อระบุข้อความที่พร้อมสำหรับการดึงข้อมูลหรือแสดงผล
การหมดเวลา: การเชื่อมต่อ SSE จะเปิดอยู่ได้นานสูงสุด 60 นาที คำขอแบบไม่สตรีมจะรอนานสูงสุด 90 วินาที จากนั้นจะส่งกลับ 202 Accepted ในขณะที่การรันยังดำเนินต่อไป
ส่วนหัวการเชื่อมต่อ
การตอบกลับ SSE จะตั้งค่าส่วนหัวเหล่านี้:
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
X-Accel-Buffering: no
X-Run-Id: run_abc123
X-Run-Id จะพร้อมใช้งานก่อนอีเวนต์ SSE แรก
การเชื่อมต่อใหม่และการกู้คืน
สตรีม SSE จะไม่ถูกเล่นซ้ำ หากการเชื่อมต่อขาดหาย ให้ใช้ session_id และ run_id ที่บันทึกไว้เพื่อกู้คืนสถานะ:
curl "https://api.jenova.ai/v1/sessions/ses_abc123/runs/run_abc123" \
-H "Authorization: Bearer jnv_sk_xxx"
หากการรันยังทำงานอยู่ คำขอนี้จะส่งกลับสถานะปัจจุบัน ข้อความส่วนที่เสร็จบางส่วน และความคืบหน้าล่าสุด หากได้รับผลลัพธ์เป็น 404 not_found แสดงว่าการรันนั้นไม่ได้ทำงานอยู่แล้ว ให้ดึงข้อความของเซสชันเพื่อตรวจสอบผลลัพธ์ที่เสร็จสมบูรณ์:
curl "https://api.jenova.ai/v1/sessions/ses_abc123/messages?limit=20" \
-H "Authorization: Bearer jnv_sk_xxx"
รูปแบบเฟรม
เฟรม SSE แต่ละเฟรมเป็นไปตามรูปแบบมาตรฐาน:
event: <event_type>
data: <json_payload>
การขึ้นบรรทัดใหม่สองครั้งเป็นตัวสิ้นสุดของแต่ละเฟรม
ประเภทอีเวนต์
สตรีมประกอบด้วยเหตุการณ์วงจรชีวิต เดลตาข้อความ การคิด ความคืบหน้า คำเตือน การเสร็จสมบูรณ์ของข้อความ การเชื่อมต่อ MCP ข้อผิดพลาด เหตุการณ์สุดท้าย และ ping เหตุการณ์บางประเภทจะถูกส่งเมื่อเกี่ยวข้องเท่านั้น
สำหรับคำขอแบบชั่วคราว (ephemeral: true) อีเวนต์ SSE ทุกตัวจะไม่มี session_id ให้ใช้ run_id เท่านั้นในการเชื่อมโยงอีเวนต์ภายในสตรีมนั้นเพียงหนึ่งเดียว
สำหรับการตรวจสอบยืนยันครั้งสุดท้ายในคำขอแบบถาวร ให้รอ stream_ended แล้วจึงเรียก List Messages
ฟิลด์ทั่วไปในอีเวนต์ที่อยู่ในขอบเขตของการรัน:
| ฟิลด์ | คำอธิบาย |
|---|---|
session_id | ID ของเซสชัน ไม่มีในสตรีมแบบชั่วคราว ให้เก็บค่านี้จาก stream_started เพื่อใช้ในคำขอถัดไปเมื่อใช้ POST /messages แบบถาวร |
run_id | ID ของการรันปัจจุบัน เมื่อมี |
stream_started
ส่งครั้งเดียวเมื่อการรันเริ่มต้น
| ฟิลด์ | คำอธิบาย |
|---|---|
agent | slug ของเอเจนต์ในเซสชัน เมื่อมี |
stream_delta
ส่งซ้ำ ๆ ขณะที่เอเจนต์สร้างข้อความตอบกลับที่มองเห็นได้ ให้เชื่อมค่า chunk_content ตามลำดับ seq เพื่อสร้างข้อความตอบกลับแบบสตรีม
event: stream_delta
data: {"session_id":"ses_abc123","run_id":"run_abc123","chunk_content":"To reset your ","seq":1}
| ฟิลด์ | คำอธิบาย |
|---|---|
chunk_content | ส่วนย่อยของข้อความ |
seq | เลขลำดับส่วนย่อยที่เพิ่มขึ้นเรื่อย ๆ ภายในสตรีม |
stream_thinking
ส่งซ้ำ ๆ ขณะที่เอเจนต์ปล่อยผลลัพธ์การคิดออกมา ใช้สำหรับตัวแสดงสถานะการคิดแยกต่างหากหรือมุมมองการตรวจสอบ (trace view) เท่านั้น อย่านำมาเชื่อมต่อเข้ากับข้อความตอบกลับสุดท้าย
| ฟิลด์ | คำอธิบาย |
|---|---|
content | ส่วนย่อยของข้อความการคิด |
stream_progress
รายงานกิจกรรมที่ผู้ใช้มองเห็นได้ระหว่างการสร้าง เช่น การอ่านเอกสาร การค้นหาเว็บ หรือการรอการดำเนินการจากผู้ใช้ เหตุการณ์เหล่านี้มีไว้สำหรับแสดงผลชั่วคราวใน UI โปรดละเว้นฟิลด์ที่ไม่รู้จัก ใช้ข้อความที่เสร็จสมบูรณ์แล้วเป็นประวัติข้อความที่เชื่อถือได้
ขั้นสูง: คำขอข้อความรองรับ include_progress: false เพื่อละเว้นเฉพาะ stream_progress เท่านั้น อีเวนต์วงจรชีวิต ping message_completed ข้อผิดพลาด และอีเวนต์สุดท้ายยังคงถูกส่งเมื่อเกี่ยวข้อง
| ฟิลด์ | คำอธิบาย |
|---|---|
state | สถานะวงจรชีวิต: running, in-progress, success, failed, skipped, complete, cancelled และอื่น ๆ ให้จัดการค่าที่ไม่รู้จักอย่างเหมาะสม |
label | ป้ายกิจกรรมที่มนุษย์อ่านเข้าใจได้ |
อีเวนต์ความคืบหน้าบางตัวอาจมี url, file_name, หรือ server_name เป็นคำแนะนำเพิ่มเติมสำหรับการแสดงผล
message_completed
ส่งทุกครั้งที่ข้อความเสร็จสมบูรณ์และพร้อมสำหรับการดึงข้อมูลหรือแสดงผล
นี่คือตัวบอกขอบเขต (boundary marker) ไม่ใช่อ็อบเจ็กต์ข้อความแบบสมบูรณ์ ให้ดึงข้อความหากคุณต้องการเนื้อหาหรือข้อมูลเมทาดาทา
event: message_completed
data: {"session_id":"ses_abc123","run_id":"run_abc123","message_id":"msg_abc123","sequence":4,"from":{"type":"agent","name":"Jenova"},"type":"external"}
| ฟิลด์ | คำอธิบาย |
|---|---|
message_id | ID ของข้อความที่เสร็จสมบูรณ์แล้ว |
sequence | เลขลำดับที่คงที่ภายในเซสชัน |
from | อ็อบเจ็กต์ผู้ส่งซึ่งมี type (user หรือ agent) และ name |
type | ประเภทของข้อความ: external หรือ internal |
mcp_connection
ส่งเมื่อเอเจนต์ต้องการให้ผู้ใช้ปลายทางเชื่อมต่อหรืออนุญาตเซิร์ฟเวอร์ MCP อย่างน้อยหนึ่งรายการก่อนที่จะดำเนินการต่อได้ เหตุการณ์นี้ใช้ได้เฉพาะในโหมดสตรีมมิงเท่านั้น
| ฟิลด์ | คำอธิบาย |
|---|---|
connection_server_list | เซิร์ฟเวอร์ MCP ที่ต้องการการดำเนินการเชื่อมต่อ แต่ละเซิร์ฟเวอร์มี mcp_server_id, mcp_server_name และ auth_url ที่เป็นตัวเลือก |
user_action_deadline_unix | Unix timestamp เมื่อการดำเนินการเชื่อมต่อของผู้ใช้หมดอายุ |
mcp_connection_resolved
ส่งเมื่อการดำเนินการเชื่อมต่อ MCP ของผู้ใช้ได้รับการแก้ไขหรือหมดอายุแล้ว
ไม่มีฟิลด์เพิ่มเติมนอกเหนือจากฟิลด์ทั่วไปที่อยู่ในขอบเขตของการรัน
warning
ส่งสำหรับคำเตือนที่ไม่ถึงขั้นร้ายแรงระหว่างการรัน
| ฟิลด์ | คำอธิบาย |
|---|---|
message | คำเตือนที่ไม่ถึงขั้นร้ายแรงที่มนุษย์อ่านเข้าใจได้ |
code | รหัสคำเตือน (ไม่บังคับ) |
stream_error
ส่งเมื่อการรันล้มเหลว อาจมีอีเวนต์ stream_ended สุดท้ายตามมาพร้อมกับ success:false และ stop_reason:"error"
| ฟิลด์ | คำอธิบาย |
|---|---|
code | รหัสข้อผิดพลาด |
message | ข้อความแสดงข้อผิดพลาดที่มนุษย์อ่านเข้าใจได้ |
stream_ended
ส่งครั้งเดียวเมื่อการรันเสร็จสิ้น นี่คืออีเวนต์สุดท้ายของสตรีม
event: stream_ended
data: {"session_id":"ses_abc123","run_id":"run_abc123","success":true,"stop_reason":"end_run","usage":{"cost":"0.0032"}}
ตัวอย่างกรณีล้มเหลว:
event: stream_ended
data: {"session_id":"ses_abc123","run_id":"run_abc123","success":false,"stop_reason":"user_cancelled","usage":{"cost":"0.0012"}}
| ฟิลด์ | คำอธิบาย |
|---|---|
success | บอกว่าการรันเสร็จสมบูรณ์หรือไม่ |
stop_reason | เหตุผลสิ้นสุดของการรัน: end_run, user_cancelled, user_action_timeout หรือ error |
usage | ออบเจ็กต์การใช้งานสำหรับคำขอนี้ ปัจจุบันมี cost เมื่อสามารถคำนวณได้ |
ping
เฟรมสัญญาณคงชีพ (keepalive) ที่ส่งทุก 15 วินาที เพื่อป้องกันการหมดเวลาของพร็อกซี/CDN ให้ละเลยเฟรมเหล่านี้ในไคลเอนต์ของคุณ
การผสานรวมเซิร์ฟเวอร์ MCP
เชื่อมต่อเอเจนต์ของคุณกับเครื่องมือภายนอกผ่าน Model Context Protocol (MCP):
- เซิร์ฟเวอร์ MCP ที่ Jenova จัดการ: เซิร์ฟเวอร์ที่ Jenova โฮสต์ไว้สำหรับการค้นหา การดึงเนื้อหา การสร้างเอกสาร และความสามารถอื่น ๆ ที่มีอยู่ในระบบ
- เซิร์ฟเวอร์ MCP ระยะไกล: เซิร์ฟเวอร์ MCP ระยะไกลอื่น ๆ ที่กำหนดค่าไว้สำหรับเอเจนต์ของคุณ
เซิร์ฟเวอร์ MCP ต้องได้รับการกำหนดค่าในแดชบอร์ดเมื่อสร้างหรือแก้ไขเอเจนต์ของคุณ หากต้องการใช้เซิร์ฟเวอร์ MCP ของคุณเอง ให้เพิ่มเข้าไปในเอเจนต์แบบกำหนดเอง แล้วเรียกใช้เอเจนต์นั้นผ่าน API API จะดำเนินการเครื่องมือที่เปิดใช้งานไว้ในการกำหนดค่าของเอเจนต์ ไม่จำเป็นต้องตั้งค่าเพิ่มเติมในคำขอ API
เมื่อเอเจนต์ใช้เครื่องมือ MCP ระหว่างการตอบกลับ อีเวนต์ความคืบหน้าจะถูกส่งในสตรีมทันทีที่เกิดขึ้น:
event: stream_progress
data: {"session_id":"ses_...","run_id":"run_...","state":"running","label":"Searching Google"}
หากเอเจนต์ต้องการให้ผู้ใช้ปลายทางเชื่อมต่อหรืออนุญาตเซิร์ฟเวอร์ MCP ระหว่างการรัน การตอบกลับแบบสตรีมมิงอาจมีเหตุการณ์ mcp_connection และ mcp_connection_resolved แสดงรายการเซิร์ฟเวอร์ที่ต้องเชื่อมต่อให้ผู้ใช้ปลายทางเห็น และเปิด auth_url ที่ให้มาเมื่อมี ให้เปิดสตรีม SSE ค้างไว้ขณะที่ผู้ใช้เชื่อมต่อหรืออนุญาตเซิร์ฟเวอร์
หลังจากอนุมัติสิทธิ์แล้ว Jenova จะจัดเก็บ token หน้าต่างการอนุมัติสิทธิ์จะแสดงหน้าเสร็จสมบูรณ์ และการรันเดิมจะดำเนินการต่อโดยอัตโนมัติ ผู้ใช้ปลายทางไม่จำเป็นต้องส่งข้อความซ้ำ
หากผู้ใช้ปลายทางไม่เชื่อมต่อ ไม่อนุญาต ไม่ข้าม หรือไม่ปิดเสียงก่อน user_action_deadline_unix การรันจะสิ้นสุดด้วย stop_reason:"user_action_timeout" คุณยังสามารถยกเลิกการรันที่ใช้งานอยู่ด้วย POST /sessions/{session_id}/cancel
เก็บ auth_url ไว้ฝั่งไคลเอ็นต์ หากไคลเอ็นต์ตัดการเชื่อมต่อระหว่างการอนุญาต URL จะยังใช้ได้จนถึง user_action_deadline_unix สำหรับคำขอแบบถาวร ให้เชื่อมต่อใหม่ด้วย Get Run Status หรือดึงข้อความหลังจากการรันเสร็จสิ้น
คำขอที่ไม่ใช่สตรีมมิง (stream: false) ไม่รองรับการดำเนินการของผู้ใช้สำหรับการเชื่อมต่อ MCP ใช้สตรีมมิงสำหรับเอเจนต์ที่อาจต้องมีการโต้ตอบนี้
ข้ามการเชื่อมต่อ MCP
POST /sessions/{session_id}/mcp/connection/skip
ยกเลิกการดำเนินการของผู้ใช้สำหรับการเชื่อมต่อ MCP ที่รอดำเนินการ และให้การรันดำเนินต่อโดยไม่มีการเชื่อมต่อนั้น
หากต้องการปิดเสียงพรอมป์การเชื่อมต่อในอนาคตสำหรับเซิร์ฟเวอร์หนึ่งรายการสำหรับผู้ใช้ API เดียวกัน ให้ระบุ mcp_server_id และ mute ค่าที่รองรับคือ 24h และ forever
เนื้อหาคำขอ
| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|---|---|---|---|
run_id | string | ใช่ | ID การรันที่ใช้งานอยู่จากเหตุการณ์ mcp_connection |
mcp_server_id | string | ไม่ | จำเป็นเมื่อใช้ mute; ใช้ mcp_server_id จากเหตุการณ์ |
mute | string | ไม่ | 24h หรือ forever |
การตอบกลับ 204 No Content
สตรีมจะส่ง mcp_connection_resolved จากนั้นการรันจะดำเนินต่อด้วย run_id เดิม
ข้อผิดพลาด
| สถานะ | รหัส | เงื่อนไข |
|---|---|---|
| 400 | bad_request | ไม่มี run_id ไม่มีการรันที่ใช้งานอยู่ หรือไม่มีการเชื่อมต่อ MCP ให้ข้าม |
| 400 | bad_request | mute ไม่ถูกต้อง หรือไม่มี mcp_server_id เมื่อกำหนด mute |
| 404 | session_not_found | ไม่พบเซสชัน |
| 404 | session_not_owned | ไม่ตรงกับ user ที่ระบุ |
| 409 | stale_run | run_id ไม่ตรงกับการรันที่กำลังทำงานอยู่ |
การเรียกเก็บเงิน
ค่าใช้จ่ายทั้งหมดจะถูกหักออกจากยอดเครดิตสำหรับนักพัฒนาของคุณ ดูการใช้งานและเติมเครดิตได้ที่ www.jenova.ai/platform
ราคา
| การดำเนินการ | ค่าใช้จ่าย |
|---|---|
| สร้างเซสชัน | $0.01 แบบตายตัวสำหรับเซสชันที่มีการเก็บข้อมูลถาวรทุกครั้ง รวมถึงเซสชันที่สร้างโดยปริยายจาก POST /messages |
| แยกสาขาเซสชัน (Fork Session) | $0.05 แบบตายตัว |
| ส่งข้อความ | ผันแปร (ดูรายละเอียดด้านล่าง) |
ค่าใช้จ่ายของข้อความขึ้นอยู่กับ:
- โมเดล - โมเดลแต่ละตัวมีค่าใช้จ่ายต่อ token แตกต่างกัน
- ความยาวของบริบท - เซสชันที่ยาวขึ้นจะใช้ input token มากขึ้นต่อคำขอ
- ความซับซ้อนของเวิร์กโฟลว์ - เวิร์กโฟลว์ที่ยาวขึ้นและการใช้เครื่องมือที่มากขึ้น (การค้นหาเว็บ การสร้างไฟล์ การวิเคราะห์เอกสาร) จะเพิ่มการใช้ token โดยรวม
ค่าใช้จ่ายจริงจะถูกส่งกลับเป็น stream_ended.usage.cost สำหรับคำขอแบบสตรีม และ usage.cost สำหรับคำขอ JSON แบบไม่สตรีม
การกันเครดิต
การรันข้อความใหม่ทุกครั้งจะทำการ กันเครดิต $0.50 จากยอดเครดิตของคุณก่อนที่จะเริ่มดำเนินการ นี่คือการสำรองเงินทุนไว้สำหรับการรันนั้น ข้อความที่ต่อเนื่องซึ่งอยู่ในคิวของการรันที่กำลังทำงานอยู่จะไม่สร้างการกันเครดิตเพิ่มเติม; การใช้งานของการรันที่กำลังทำงานอยู่จะถูกตรวจสอบกับยอดเครดิตที่เหลือของคุณ
เมื่อการรันเสร็จสมบูรณ์ การกันเครดิตจะถูกชำระตามค่าใช้จ่ายจริง และส่วนต่างจะถูกปลดปล่อยคืน การรันที่ถูกยกเลิกหรือล้มเหลวจะถูกเรียกเก็บเงินเฉพาะการใช้งานที่เกิดขึ้นจริงเท่านั้น หากคำขอล้มเหลวก่อนที่จะไปถึงโมเดล การกันเครดิตทั้งหมดจะถูกปลดปล่อยคืน
ซึ่งหมายความว่ายอดเครดิตที่ใช้ได้ของคุณอาจดูต่ำลงชั่วคราวในช่วงที่คำขอกำลังดำเนินการอยู่ คุณต้องมียอดเครดิตที่ใช้ได้อย่างน้อย $0.50 เพื่อส่งข้อความไปยังเซสชันที่มีอยู่ หรือเพื่อส่งข้อความชั่วคราว (ephemeral) คำขอ POST /messages แบบถาวรครั้งแรกจะสร้างเซสชันและต้องมียอดเครดิตอย่างน้อย $0.51 เพื่อครอบคลุมการกันเครดิตของข้อความบวกกับค่าธรรมเนียมการสร้างเซสชัน
การจำกัดอัตราการใช้งาน
บัญชีนักพัฒนาทุกบัญชีอยู่ภายใต้มิติการจำกัดอัตราการใช้งานสามมิติ:
| มิติ | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
| RPM (คำขอต่อนาที) | 60 | หน้าต่างเวลาตายตัวต่อนาที |
| RPD (คำขอต่อวัน) | 1,000 | หน้าต่างเวลาตายตัวต่อวัน |
| การทำงานพร้อมกัน (Concurrent) | 5 | จำนวนคำขอที่กำลังดำเนินการพร้อมกันสูงสุด |
คำขอ GET และ HEAD ไม่ใช้สล็อตพร้อมกัน cancel, undo และ mcp/connection/skip ก็ไม่ใช้สล็อตพร้อมกันเช่นกัน ดังนั้นการดำเนินการเหล่านี้ยังคงใช้ได้เมื่อสล็อตทั้งหมดถูกใช้งาน คำขอเหล่านี้ยังคงนับรวมใน RPM และ RPD
ส่วนหัวการตอบกลับ
การตอบกลับ API ที่ผ่านการยืนยันตัวตนจะมีส่วนหัวการจำกัดอัตราการใช้งานรวมอยู่ด้วย:
| ส่วนหัว | คำอธิบาย |
|---|---|
X-RateLimit-Limit | ขีดจำกัด RPM ของคุณ |
X-RateLimit-Remaining | จำนวนคำขอที่เหลือในหน้าต่างนาทีปัจจุบัน |
X-RateLimit-Reset | Unix timestamp ที่หน้าต่างปัจจุบันจะรีเซ็ต |
Retry-After | จำนวนวินาทีที่ต้องรอก่อนลองใหม่ (เฉพาะเมื่อได้รับ 429) |
เมื่อเกินขีดจำกัด API จะส่งกลับ 429 Too Many Requests:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please retry after 12 seconds."
}
}
การจัดการข้อผิดพลาด
ข้อผิดพลาด HTTP ที่เกิดขึ้นทันทีและข้อผิดพลาดของการรันแบบไม่สตรีมจะใช้รูปแบบซองข้อมูลที่สอดคล้องกัน:
{
"error": {
"code": "error_code_string",
"message": "Human-readable description"
}
}
ข้อความแสดงข้อผิดพลาดจะถูกปรับให้เข้ากับท้องถิ่นตามพารามิเตอร์ lang (ดู การปรับให้เข้ากับท้องถิ่น)
ข้อผิดพลาดของการรันแบบสตรีมจะถูกส่งในรูปแบบอีเวนต์ stream_error การรันที่ล้มเหลวอาจยังส่งอีเวนต์ stream_ended ครั้งสุดท้ายพร้อมกับ success:false และมีการกำหนด stop_reason ข้อผิดพลาดของการรันแบบไม่สตรีมอาจมีออบเจกต์ usage ระดับบนสุดรวมอยู่ด้วยเมื่อมีข้อมูลค่าใช้จ่าย
ข้อผิดพลาดเฉพาะของแต่ละจุดเชื่อมต่อจะถูกอธิบายไว้ในเนื้อหาของแต่ละจุดเชื่อมต่อนั้น
ข้อผิดพลาดของการรันหลังจากเริ่มต้น
ข้อผิดพลาดของการรันจะปรากฏขึ้นหลังจากการรันข้อความได้เริ่มต้นไปแล้ว ในโมดการสตรีม ข้อผิดพลาดเหล่านี้จะปรากฏเป็นอีเวนต์ stream_error และอาจตามด้วย stream_ended ที่มี success:false ในโมดไม่สตรีม ข้อผิดพลาดจะถูกส่งกลับเป็นการตอบกลับ JSON แสดงข้อผิดพลาดพร้อมกับรหัสสถานะ HTTP ตามด้านล่าง
| รหัสสถานะ HTTP แบบไม่สตรีม | รหัส | คำอธิบาย |
|---|---|---|
| 400 | content_policy_violation | ผู้ให้บริการโมเดลปฏิเสธคำขอเนื่องจากเหตุผลด้านนโยบายเนื้อหา |
| 404 | session_not_found | เซสชันถูกลบไปก่อนที่การรันจะสามารถดำเนินการได้ |
| 409 | busy | เซสชันไม่ว่างหรือใช้งานไม่ได้ชั่วคราวก่อนที่การรันจะสามารถเริ่มต้นได้ |
| 413 | total_image_size_exceeded | ขนาดรวมของรูปภาพเกินขีดจำกัดขนาดต่อคำขอของโมเดล |
| 500 | internal_error | การรันล้มเหลวโดยไม่คาดคิด |
| 502 | llm_api_error | ข้อผิดพลาดจากผู้ให้บริการโมเดลหรือ API โมเดลต้นทาง |
การแบ่งหน้า
จุดเชื่อมต่อประเภทรายการใช้ การแบ่งหน้าแบบ cursor:
{
"items": [],
"next_cursor": "eyJ2IjoxLCJrIjoiY3VyXzAyIn0",
"has_more": true
}
| พารามิเตอร์ | ประเภท | ค่าเริ่มต้น | ค่าสูงสุด | คำอธิบาย |
|---|---|---|---|---|
limit | integer | 20 | 100 | จำนวนรายการต่อหน้า |
cursor | string | - | - | cursor ที่ได้จาก next_cursor ในคำขอก่อนหน้า |
ส่ง next_cursor เป็นพารามิเตอร์คิวรี cursor เพื่อดึงหน้าถัดไป เมื่อ has_more เป็น false แสดงว่าไม่มีผลลัพธ์เพิ่มเติมแล้ว
การปรับให้เข้ากับท้องถิ่น
จุดเชื่อมต่อทั้งหมดรองรับพารามิเตอร์คิวรี lang แบบไม่บังคับ เพื่อควบคุมภาษาของข้อความแสดงข้อผิดพลาดและเนื้อหาที่ปรับให้เข้ากับท้องถิ่นอื่น ๆ
| แหล่งที่มา | ลำดับความสำคัญ | ตัวอย่าง |
|---|---|---|
พารามิเตอร์คิวรี lang | สูงสุด | ?lang=zh |
ส่วนหัว Accept-Language | สำรอง | Accept-Language: ja |
| ค่าเริ่มต้น | ต่ำสุด | English (en) |
คุณสามารถเพิ่ม ?lang=xx ต่อท้าย URL ของคำขอใดก็ได้:
POST /sessions?lang=zh
GET /sessions/ses_abc123/messages?lang=ja
ภาษาที่รองรับ: en, zh, ja, ko, es, fr, de, it, pt, ru, id, th, vi
ความเป็นส่วนตัวและข้อมูล
Jenova ไม่ใช้พรอมต์ API, ผลลัพธ์, ประวัติการสนทนา, ไฟล์ที่อัปโหลด, คำสั่งของเอเจนต์ หรือฐานความรู้ ในการฝึกโมเดลของ Jenova
สำหรับผู้ให้บริการโมเดลบุคคลที่สาม Jenova ใช้ช่องทาง API เชิงพาณิชย์ การตั้งค่าบัญชี ข้อผูกพันตามสัญญา หรือการเลือกไม่เข้าร่วม เพื่อป้องกันไม่ให้เนื้อหาของลูกค้าถูกนำไปใช้ในการฝึกโมเดลของผู้ให้บริการ
Jenova จัดเก็บและประมวลผลข้อมูล API โดยใช้โครงสร้างพื้นฐานในสหรัฐอเมริกา ผู้ให้บริการบุคคลที่สามอาจประมวลผลข้อมูลในเขตอำนาจศาลอื่น ๆ ตามที่ระบุไว้ในนโยบายความเป็นส่วนตัวและข้อกำหนดการใช้งาน
สำหรับรายละเอียดทั้งหมด ดู ข้อกำหนดการใช้งาน, นโยบายความเป็นส่วนตัว และ นโยบายการใช้งาน
การสนับสนุน
- แดชบอร์ด: www.jenova.ai/platform
- อีเมล: [email protected]