Jenova - Nền tảng tác nhân AINền tảng API

Tài liệu tham khảo Jenova Agent API

URL cơ sở: https://api.jenova.ai/v1

Xác thực: Bearer token trong tiêu đề Authorization


Mục lục


Tổng quan

Vận hành các tác nhân tùy chỉnh ngay trong sản phẩm hoặc workflow của bạn chỉ sau vài phút. Thiết lập tác nhân của bạn cho bất kỳ tác vụ nào, chọn bất kỳ mô hình và công cụ nào, và để Jenova đảm nhận agent harness, cơ sở dữ liệu và mở rộng quy mô.

Bộ công nghệ Tác nhân đầy đủ:

  • Agent Harness được quản lý: Một lệnh gọi vào, công việc hoàn chỉnh trả về. Tác nhân của bạn nghiên cứu, suy luận, gọi công cụ và tạo ra các tệp — đúng như bạn hướng dẫn.
  • Ngữ cảnh và Bộ nhớ không giới hạn: Quản lý ngữ cảnh dựa trên RAG và cơ chế độc quyền theo dõi trạng thái phiên cho phép bộ nhớ không giới hạn trong suốt một cuộc hội thoại.
  • Thư viện công cụ và MCP: Kết nối với thư viện của chúng tôi gồm 30+ công cụ và server MCP, như tìm kiếm, tạo hình ảnh, email và hơn thế nữa — hoặc tích hợp server MCP của riêng bạn.
  • Chuyển đổi mượt mà sang bất kỳ mô hình nào: Triển khai các mô hình từ OpenAI, Anthropic, Google, xAI hoặc các nhà cung cấp mã nguồn mở hàng đầu, và chuyển đổi giữa các mô hình này chỉ với một tham số.
  • Tri thức và RAG được quản lý: Jenova đảm nhận pipeline RAG từ đầu đến cuối — chunking, lập chỉ mục, lưu trữ và truy xuất.
  • Đã kiểm chứng ở quy mô lớn: Triển khai trên hạ tầng dày dạn thực chiến, đang vận hành hàng trăm tác nhân thực tế trong production. Không phải khởi tạo, mở rộng hay bảo trì bất kỳ cluster nào.

Bắt đầu nhanh

1. Lấy Khóa API của bạn

Tạo một khóa API từ bảng điều khiển dành cho nhà phát triển tại www.jenova.ai/platform. Các khóa sử dụng định dạng jnv_sk_* và được truyền dưới dạng Bearer token.

2. Chọn hoặc Tạo một Tác nhân

Chọn một tác nhân dựng sẵn từ nền tảng, hoặc tạo một tác nhân tùy chỉnh trong bảng điều khiển với các chỉ dẫn, cấu hình mô hình, tệp cơ sở kiến thức, công cụ và máy chủ MCP.

3. Gửi Tin nhắn đầu tiên của bạn

Tạo một phiên và gửi một tin nhắn trong một lần gọi:

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

Phản hồi được truyền trở lại dưới dạng 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"}}

Ghi lại session_id từ stream_started để dùng cho các yêu cầu tiếp theo. Đối với các phản hồi JSON đồng bộ, xem Gửi Tin nhắn.


Khái niệm cốt lõi

Tác nhân

Một tác nhân AI mà bạn tương tác qua API. Mỗi tác nhân có một slug duy nhất (ví dụ: my-support-agent) được dùng làm giá trị agent trong các lệnh gọi API.

  • Dựng sẵn: Chọn từ các tác nhân hiện có trên nền tảng.
  • Tùy chỉnh: Cấu hình tác nhân riêng của bạn trong bảng điều khiển với các chỉ dẫn, mô hình, cơ sở kiến thức, công cụ và máy chủ MCP.

Phiên

Một luồng hội thoại độc lập giữa một người dùng cuối và một tác nhân.

  • Định danh: ID có tiền tố (ví dụ: ses_abc123).
  • Phạm vi: Có thể tồn tại nhiều phiên cho cùng một tác nhân và người dùng cuối, mỗi phiên có trạng thái hội thoại độc lập.
  • Vòng đời: Các phiên tồn tại vô thời hạn cho đến khi bị xóa qua API. Đối với các nhiệm vụ một lần không cần phiên, hãy sử dụng POST /messages với ephemeral: true.
  • Cách ly nền tảng: Các phiên API tách biệt hoàn toàn với các hội thoại trong ứng dụng web Jenova. Người dùng cuối, lịch sử phiên và thanh toán là độc lập giữa API và ứng dụng web.

Tin nhắn

Một mục đơn lẻ trong lịch sử hội thoại của một phiên, được trả về bởi các điểm cuối Tin nhắn. Mỗi tin nhắn bao gồm một đối tượng from có cấu trúc với type (user hoặc agent) và name, cùng với type của tin nhắn:

  • external - một tin nhắn hội thoại được dự định hiển thị dưới dạng nội dung chat.
  • internal - một tin nhắn tùy chọn đại diện cho các bước làm việc của tác nhân trong một lượt chạy, chẳng hạn như lệnh gọi công cụ hoặc truy xuất.

Lượt chạy

Một lần thực thi tác nhân đơn lẻ được tạo ra khi bạn gửi một tin nhắn. Một lượt chạy có một run_id, có thể truyền phát các sự kiện trong khi đang hoạt động, và có thể tạo ra một hoặc nhiều tin nhắn hoàn chỉnh. Mỗi phiên chỉ có thể có một lượt chạy đang hoạt động tại một thời điểm.

Người dùng cuối

Trường user giới hạn phạm vi các phiên cho một người dùng cuối trong ứng dụng của bạn. Hãy sử dụng một ID ổn định và không mang thông tin định danh, chẳng hạn như ID người dùng nội bộ hoặc UUID của bạn. Tránh sử dụng email hoặc các thông tin cá nhân khác trừ khi ứng dụng của bạn yêu cầu. Các phiên được tạo với cùng giá trị user được nhóm lại với nhau, cho phép liệt kê phiên theo từng người dùng.

Nếu user bị bỏ qua, phiên sẽ được giới hạn phạm vi theo tài khoản nhà phát triển của bạn và không thể lọc theo người dùng cuối sau này. Hãy truyền user trong môi trường sản xuất.

Đối với các yêu cầu trên phiên đã tồn tại (bất kỳ điểm cuối nào có {session_id} trong đường dẫn), user là một cơ chế bảo vệ quyền sở hữu tùy chọn. Nếu bạn cung cấp trường này, nó phải khớp với giá trị user đã dùng khi phiên được tạo; nếu không, API sẽ trả về 404 session_not_owned. Hãy gửi trường này như một tham số truy vấn trong các yêu cầu GET và DELETE, và trong phần nội dung JSON của các yêu cầu POST và PATCH. Tham số truy vấn user trên yêu cầu POST hoặc PATCH sẽ trả về 400 bad_request.


Xác thực

Xác thực mọi yêu cầu bằng Bearer token trong tiêu đề Authorization:

Authorization: Bearer jnv_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Khóa API được tạo từ bảng điều khiển dành cho nhà phát triển.

User-Agent là tùy chọn. Các SDK có thể thiết lập giá trị này để phục vụ chẩn đoán, nhưng API không yêu cầu điều đó.

Định dạng khóa: Khóa bắt đầu bằng tiền tố jnv_sk_ theo sau là một chuỗi ngẫu nhiên được mã hóa base62.

Giới hạn: Mỗi tài khoản nhà phát triển có thể có tối đa 10 khóa API đang hoạt động.


Điểm cuối API

API Tin nhắn

Gửi Tin nhắn là đường dẫn API chính. Sử dụng POST /messages cho tin nhắn đầu tiên; nó sẽ tạo phiên và bắt đầu lượt chạy trong một yêu cầu duy nhất. Sử dụng POST /sessions/{session_id}/messages khi tiếp tục một session_id đã được ghi lại.

Gửi Tin nhắn

POST /messages

Tạo một phiên lâu dài và gửi tin nhắn đầu tiên trong một yêu cầu duy nhất. Đặt ephemeral: true để tạo yêu cầu truyền phát trực tuyến một lần không trả về ID phiên và không thể tiếp tục. Dữ liệu của yêu cầu sẽ bị xóa ngay sau khi yêu cầu hoàn tất.

Nội dung yêu cầu

TrườngLoạiBắt buộcMặc địnhMô tả
agentstringCó-Định danh slug của tác nhân
contentstringCó điều kiện-Nội dung văn bản tin nhắn. Bắt buộc trừ khi đã cung cấp file_urls
file_urlsstring[]Có điều kiện-URL của các tệp cần đính kèm. Bắt buộc trừ khi đã cung cấp content
userstringKhông-Định danh người dùng cuối bên ngoài của bạn (tối đa 255 ký tự). Nếu bỏ trống, giá trị mặc định sẽ là tài khoản nhà phát triển của bạn
session_namestringKhông-Tên hiển thị cho phiên mới (tối đa 200 ký tự)
ephemeralbooleanKhôngfalseYêu cầu một lần chỉ truyền phát trực tuyến. Không trả về ID phiên, không thể tiếp tục, và dữ liệu sẽ bị xóa ngay sau khi yêu cầu hoàn tất
streambooleanKhôngtruetrue để truyền phát trực tuyến qua SSE, false để dùng JSON. Việc cấp quyền MCP yêu cầu phải truyền phát trực tuyến
include_progressbooleanKhôngtrueĐặt thành false để bỏ qua các sự kiện stream_progress. Chỉ áp dụng khi truyền phát trực tuyến
modelstringKhông-Ghi đè mô hình một lần chỉ cho yêu cầu này. Sử dụng một ID mô hình ổn định như claude-sonnet-5. Không thay đổi mô hình mặc định của phiên
additional_contextobject[]Không-Ngữ cảnh có tên chỉ dành cho yêu cầu này. Xem Ngữ cảnh bổ sung

Ví dụ - Truyền phát trực tuyến (mặc định)

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

Phản hồi là một luồng SSE (xem Truyền phát trực tuyến (SSE) để biết định dạng sự kiện). Các yêu cầu lâu dài bao gồm session_id mới; các yêu cầu ephemeral: true không có session_id và phải sử dụng truyền phát trực tuyến.

Ví dụ - JSON (không truyền phát trực tuyến)

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

Phản hồi

Các phản hồi truyền phát trực tuyến phát ra các sự kiện SSE được mô tả trong Truyền phát trực tuyến (SSE). Các phản hồi không truyền phát trực tuyến trả về đối tượng tin nhắn kèm stop_reason và usage cho yêu cầu, như được trình bày trong Tiếp tục Phiên. stop_reason là end_run, hoặc user_cancelled nếu lượt chạy bị hủy sau khi tác nhân đã tạo ra tin nhắn.

Nếu lượt chạy bị hủy trước khi tác nhân tạo ra tin nhắn, API trả về 200 OK với status: "cancelled", session_id, run_id, stop_reason: "user_cancelled", và usage.

Nếu một lượt chạy không truyền phát trực tuyến vẫn đang được xử lý sau 90 giây, API sẽ trả về 202 Accepted với status: "processing", session_id, run_id, và một message dạng văn bản dễ đọc. Lượt chạy tiếp tục sau khi phản hồi được gửi hoặc khi client ngắt kết nối; hãy kiểm tra các tin nhắn của phiên, hoặc sử dụng truyền phát trực tuyến cho các luồng công việc dài hơn.

Lỗi

Trạng tháiMãĐiều kiện
400missing_required_fieldTrường agent là bắt buộc
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400bad_requestChế độ ephemeral không hợp lệ, additional_context không hợp lệ, hoặc user/session_name vượt quá độ dài tối đa
400content_or_uploaded_files_requiredKhông cung cấp content cũng không cung cấp file_urls
400content_too_longNội dung tin nhắn vượt quá 32.000 token
400exceed_max_upload_filesCó nhiều hơn 10 URL tệp khác nhau trong một yêu cầu duy nhất
400unsupported_file_formatMột URL tệp có phần mở rộng tệp không được hỗ trợ
400invalid_file_urlMột URL tệp có định dạng không hợp lệ hoặc không phải HTTPS
400invalid_model_selectionmodel không phải là ID mô hình hợp lệ, hoặc mô hình mặc định của tác nhân không khả dụng
402insufficient_creditsKhông đủ tín dụng để tạo phiên hoặc gửi tin nhắn
404agent_not_foundTác nhân không tồn tại hoặc không thể truy cập được đối với tài khoản của bạn

Tiếp tục Phiên

POST /sessions/{session_id}/messages

Gửi một tin nhắn đến một phiên liên tục hiện có và nhận phản hồi từ tác nhân. Theo mặc định, phản hồi được truyền phát trực tuyến qua SSE; đặt stream: false để nhận JSON.

Nội dung yêu cầu

TrườngLoạiBắt buộcMặc địnhMô tả
contentstringCó điều kiện-Nội dung tin nhắn. Bắt buộc trừ khi file_urls được cung cấp
file_urlsstring[]Có điều kiện-URL của các tệp cần đính kèm. Bắt buộc trừ khi content được cung cấp
streambooleanKhôngtruetrue để truyền phát trực tuyến qua SSE, false để nhận JSON. Xác thực MCP yêu cầu truyền phát trực tuyến
include_progressbooleanKhôngtrueĐặt thành false để bỏ qua các sự kiện stream_progress. Chỉ áp dụng khi truyền phát trực tuyến
modelstringKhông-Ghi đè mô hình một lần chỉ áp dụng cho yêu cầu này. Sử dụng một ID mô hình ổn định như claude-sonnet-5. Không làm thay đổi mô hình mặc định của phiên
additional_contextobject[]Không-Ngữ cảnh có tên chỉ dành cho yêu cầu này. Xem Ngữ cảnh bổ sung

Ví dụ - Truyền phát trực tuyến (mặc định)

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

Ví dụ - JSON (không truyền phát trực tuyến)

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

Phản hồi 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"
  }
}

Nếu phiên đã có một lượt chạy đang hoạt động hoặc tin nhắn đang chờ xử lý, API trả về JSON 202 Accepted với status: "queued", session_id, run_id, và message_id. Tin nhắn của người dùng sẽ được xử lý bởi lượt chạy đang hoạt động. Thay vào đó, yêu cầu có additional_context sẽ trả về 409 busy.

Các phản hồi không truyền phát trực tuyến tuân theo cùng quy tắc như Gửi Tin nhắn, bao gồm phản hồi status: "cancelled" khi lượt chạy bị hủy trước khi tác nhân tạo ra tin nhắn.

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại không hợp lệ
400bad_requestadditional_context không hợp lệ
400content_or_uploaded_files_requiredKhông có content hoặc file_urls được cung cấp
400content_too_longNội dung tin nhắn vượt quá 32.000 token
400exceed_max_upload_filesCó hơn 10 URL tệp khác nhau trong một yêu cầu
400unsupported_file_formatMột URL tệp có phần mở rộng tệp không được hỗ trợ
400invalid_file_urlMột URL tệp không hợp lệ hoặc không phải HTTPS
400invalid_model_selectionmodel không phải là ID mô hình hợp lệ, hoặc mô hình của phiên không còn khả dụng
402insufficient_creditsKhông đủ tín dụng để gửi tin nhắn
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
409busyPhiên tạm thời không khả dụng vì có một bản cập nhật khác đang được thực hiện, hoặc additional_context được gửi khi phiên đang có lượt chạy hoạt động hoặc tin nhắn đang chờ xử lý
429too_many_pendingPhiên đã có 200 tin nhắn đang chờ xử lý
503service_unavailableDịch vụ tạm thời không khả dụng

Tính bất biến (Idempotency)

POST /messages, POST /sessions/{session_id}/messages và POST /invoke chấp nhận tiêu đề Idempotency-Key tùy chọn (tối đa 255 ký tự). Hãy sử dụng một khóa duy nhất cho mỗi lần gửi hợp lệ của người dùng để việc thử lại mạng hoặc gửi trùng lặp không tạo ra các lượt chạy trùng lặp. Các khóa được lưu giữ trong 24 giờ.

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

Không truyền phát trực tuyến: Việc thử lại sẽ trả về phản hồi đã được lưu kèm theo tiêu đề Idempotent-Replayed: true, bao gồm cả các lỗi được trả về sau khi yêu cầu đã bắt đầu được xử lý. Phản hồi 202 Accepted đã lưu sẽ được phát lại nguyên trạng; hãy sử dụng Lấy Trạng thái Lượt chạy hoặc Danh sách Tin nhắn để kiểm tra kết quả. Các yêu cầu bị từ chối trước khi bắt đầu xử lý, chẳng hạn như lỗi kiểm tra hợp lệ hoặc lỗi tín dụng, sẽ không được lưu, vì vậy lần thử lại sẽ được đánh giá lại.

Truyền phát trực tuyến: Luồng dữ liệu không được phát lại. Đối với POST /messages và POST /sessions/{session_id}/messages, việc thử lại trong khi đang chạy hoặc sau khi hoàn tất sẽ trả về một lỗi bất biến cùng với run_id gốc và, đối với các yêu cầu lưu trữ lâu dài, session_id. Đối với các yêu cầu lưu trữ lâu dài, hãy sử dụng Lấy Trạng thái Lượt chạy để kiểm tra một lượt chạy đang hoạt động, hoặc Danh sách Tin nhắn để lấy các kết quả đã được lưu trữ. Kết quả POST /invoke dạng truyền phát trực tuyến không thể truy xuất sau khi luồng đóng. Các lần thử lại POST /invoke trả về id ban đầu thay vì run_id và session_id.

Ví dụ về việc thử lại truyền phát trực tuyến đã hoàn tất:

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

Lỗi bất biến

Trạng tháiMãĐiều kiện
400bad_requestIdempotency-Key vượt quá độ dài tối đa
409idempotency_key_reusedCùng một khóa đã được sử dụng với một yêu cầu khác
409idempotency_key_in_useYêu cầu gốc vẫn đang chạy
409idempotency_key_reusedYêu cầu truyền phát trực tuyến gốc đã hoàn tất và không thể phát lại

Danh sách Tin nhắn

GET /sessions/{session_id}/messages

Trả về danh sách phân trang các tin nhắn của phiên. Theo mặc định, chỉ các tin nhắn hội thoại external được trả về. Trang đầu tiên chứa các tin nhắn mới nhất; trong mỗi trang, các tin nhắn được sắp xếp theo thứ tự thời gian (cũ nhất trước). sequence là số thứ tự của tin nhắn trong phạm vi phiên.

Tham số truy vấn

Tham sốLoạiMặc địnhTối đaMô tả
limitinteger20100Số tin nhắn mỗi trang
cursorstring--Con trỏ phân trang
includestringexternal-Các loại tin nhắn cần trả về: external, internal, hoặc all

Ví dụ

curl "https://api.jenova.ai/v1/sessions/ses_abc123/messages?limit=50" \
  -H "Authorization: Bearer jnv_sk_xxx"

Phản hồi 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",
      "stop_reason": "end_run"
    }
  ],
  "next_cursor": "",
  "has_more": false
}

Đối tượng tin nhắn

TrườngLoạiMô tả
idstringID tin nhắn (tiền tố msg_)
session_idstringID phiên cha
sequenceintegerSố thứ tự trong phạm vi phiên. Các số có thể được dùng lại sau khi tin nhắn bị xóa
fromobjectĐối tượng người gửi với type (user hoặc agent) và name
typestringexternal đối với tin nhắn hội thoại, hoặc internal đối với các bước làm việc của tác nhân
timestringMốc thời gian ISO 8601
contentstringNội dung văn bản. Có mặt trên các tin nhắn external
modelstringID mô hình ổn định đã tạo ra phản hồi. Chỉ có mặt trên tin nhắn của tác nhân
filesarrayCác tệp được đính kèm hoặc tạo ra kèm theo tin nhắn. Xem Đối tượng tệp bên dưới. Bị lược bỏ khỏi Danh sách Tin nhắn và Lấy Tin nhắn khi tin nhắn không có tệp
stop_reasonstringCó mặt trên các tin nhắn external của tác nhân có nội dung. Giá trị là end_run
agentstringSlug của tác nhân thực thi, khi có
agent_namestringTên hiển thị của tác nhân thực thi, khi có
progress_eventsarrayHoạt động được ghi lại cho một tin nhắn internal, khi có. Mỗi mục có cùng các trường như một sự kiện stream_progress

Đối tượng tệp

TrườngLoạiMô tả
file_idstringID tệp Jenova. Để trống khi không xác định
namestringTên tệp
urlstringURL tệp. Để trống khi không xác định
formatstringĐịnh dạng tệp viết thường, chẳng hạn pdf, png, hoặc csv
sizeintegerKích thước tệp tính bằng byte. 0 khi không xác định

Lỗi

Trạng tháiMãĐiều kiện
400bad_requestTham số truy vấn không hợp lệ
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về nhà phát triển khác hoặc không khớp với user được cung cấp

Lấy Tin nhắn

GET /sessions/{session_id}/messages/{message_id}

Truy xuất một tin nhắn đơn lẻ theo ID.

Tham số truy vấn

Tham sốLoạiMặc địnhMô tả
includestringexternalCác loại tin nhắn có thể được trả về: external, internal, hoặc all

Phản hồi 200 OK

Trả về một đối tượng tin nhắn đơn lẻ có cấu trúc giống với phản hồi danh sách.

Lỗi

Trạng tháiMãĐiều kiện
400bad_requestTham số truy vấn không hợp lệ
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về nhà phát triển khác hoặc không khớp với user được cung cấp
404not_foundTin nhắn không tồn tại trong phiên này

Tệp đính kèm

Truyền các URL HTTPS có thể truy cập công khai trong trường file_urls.

Giới hạnGiá trị
Số tệp tối đa mỗi tin nhắn10
Kích thước tệp tối đa20 MB mỗi tệp

Định dạng được hỗ trợ

  • Hình ảnh: JPG, JPEG, PNG, WebP
  • Tài liệu: PDF, DOCX, XLSX, PPTX, TXT, CSV, RTF, MD, HTML, XML, JSON, LOG
  • Mã nguồn: JS, TS, TSX, JSX, PY, Java, Go, C, CPP, H, HPP, CS, RB, PHP, RS, Swift, KT, Scala, SQL, CSS, YAML, YML

URL tệp được tải về khi tác nhân đọc chúng trong lượt chạy, không phải khi yêu cầu được chấp nhận. URL không thể tải về, hoặc tệp lớn hơn 20 MB, sẽ không được đọc; bản thân yêu cầu không bị từ chối.

Khi liệt kê tin nhắn, các tệp đính kèm sẽ xuất hiện trong mảng files của tin nhắn.


Ngữ cảnh bổ sung

Truyền ngữ cảnh có tên cho một tin nhắn trong additional_context, chẳng hạn thông tin tài khoản của người dùng cuối. Ngữ cảnh này không được lưu vào lịch sử tin nhắn.

TrườngLoạiBắt buộcMô tả
namestringCóChữ thường, chữ số và dấu gạch dưới, bắt đầu bằng một chữ cái (tối đa 64 ký tự). Duy nhất trong yêu cầu, không tính dấu gạch dưới và dạng số nhiều
contentstringCóNội dung ngữ cảnh. Không được để trống (tối đa 12.000 token)
Giới hạnGiá trị
Số mục tối đa mỗi tin nhắn4
Số token tối đa mỗi mục12.000

Hãy sử dụng một tên mang tính mô tả như customer_profile hoặc order_details.

Một mục thiếu name hoặc content, hoặc có giá trị không phải chuỗi, sẽ trả về 400 invalid_payload. Các mục không hợp lệ khác trả về 400 bad_request.

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?",
    "additional_context": [
      {
        "name": "customer_profile",
        "content": "Plan: Pro. Last login: 2026-05-18."
      }
    ]
  }'

API Phiên

Phiên là các cuộc hội thoại lâu dài giữa một người dùng cuối và một tác nhân. Hầu hết các tích hợp có thể tạo phiên một cách ngầm định bằng POST /messages.

Tạo Phiên

POST /sessions

Tạo một phiên bền vững trống được liên kết với một tác nhân cụ thể. Sử dụng thao tác này khi bạn cần một ID phiên trước tin nhắn đầu tiên; nếu không, hãy ưu tiên sử dụng POST /messages.

Lưu ý: ephemeral không được chấp nhận trên POST /sessions; hãy sử dụng POST /messages với ephemeral: true cho các yêu cầu một lần.

Nội dung yêu cầu

TrườngLoạiBắt buộcMô tả
agentstringCóĐịnh danh slug của tác nhân
userstringKhôngĐịnh danh người dùng cuối bên ngoài của bạn (tối đa 255 ký tự). Nếu bỏ qua, giá trị mặc định sẽ là tài khoản nhà phát triển của bạn
session_namestringKhôngTên hiển thị cho phiên (tối đa 200 ký tự)

Ví dụ

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

Phản hồi 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"
}

Đối tượng phiên

TrườngLoạiMô tả
idstringID phiên (tiền tố ses_)
session_namestringTên hiển thị
agentstringSlug của tác nhân
agent_detailsobjectThông tin chi tiết về tác nhân với display_name. Chỉ có mặt khi được yêu cầu bằng include=agent
userstringĐịnh danh người dùng cuối. null nếu phiên được tạo mà không có user
modelstringMô hình được sử dụng khi tin nhắn không chỉ định mô hình. Được đặt thành mô hình mặc định của tác nhân khi phiên được tạo. Để trống khi tác nhân để Jenova tự chọn mô hình
created_atstringMốc thời gian ISO 8601
updated_atstringMốc thời gian ISO 8601

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400missing_required_fieldagent là trường bắt buộc
400bad_requestephemeral đã được cung cấp, hoặc user/session_name vượt quá độ dài tối đa
402insufficient_creditsKhông đủ tín dụng để tạo phiên
404agent_not_foundTác nhân không tồn tại hoặc tài khoản của bạn không có quyền truy cập

Danh sách Phiên

GET /sessions

Trả về danh sách các phiên của bạn theo dạng phân trang, được sắp xếp theo thời điểm cập nhật gần nhất.

Tham số truy vấn

Tham sốLoạiMặc địnhTối đaMô tả
limitinteger20100Số mục trên mỗi trang
cursorstring--Con trỏ phân trang
userstring--Lọc theo định danh người dùng cuối (tối đa 255 ký tự)
agentstring--Lọc theo slug của tác nhân
includestring--Đặt thành agent để thêm agent_details vào mỗi phiên

Ví dụ

curl "https://api.jenova.ai/v1/sessions?user=user_12345&limit=10" \
  -H "Authorization: Bearer jnv_sk_xxx"

Phản hồi 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": "2026-05-19T11:15:00Z|ses_abc123",
  "has_more": true
}

Lỗi

Trạng tháiMãĐiều kiện
400bad_requestTham số truy vấn không hợp lệ

Lấy Phiên

GET /sessions/{session_id}

Truy xuất một phiên đơn lẻ theo ID.

Tham số truy vấn

Tham sốLoạiMô tả
includestringĐặt thành agent để thêm agent_details vào phiên

Phản hồi 200 OK

Trả về một đối tượng phiên.

Lỗi

Trạng tháiMãĐiều kiện
400bad_requestTham số truy vấn không hợp lệ
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp

Đổi tên Phiên

PATCH /sessions/{session_id}

Cập nhật tên hiển thị của một phiên.

Nội dung yêu cầu

TrườngLoạiBắt buộcMô tả
session_namestringCóTên hiển thị mới (tối đa 200 ký tự)

Phản hồi 200 OK

Trả về đối tượng phiên đã được cập nhật.

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400missing_required_fieldsession_name là bắt buộc
400bad_requestsession_name vượt quá độ dài tối đa
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
409busyPhiên tạm thời không khả dụng vì có một bản cập nhật khác đang được thực hiện

Xóa Phiên

DELETE /sessions/{session_id}

Xóa vĩnh viễn một phiên và toàn bộ tin nhắn của phiên đó. Phiên này không được có lượt chạy đang hoạt động.

Phản hồi 204 No Content

Lỗi

Trạng tháiMãĐiều kiện
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
409busyPhiên có lượt chạy đang hoạt động - hãy hủy lượt chạy đó trước

Thao tác

Các điểm cuối này là các công cụ khôi phục và chỉnh sửa cho các phiên bền vững (persistent sessions). Hầu hết các tích hợp chỉ cần dùng Hủy Lượt chạy đang hoạt động; hãy sử dụng các thao tác khác khi bạn cố ý muốn thay đổi hoặc khôi phục trạng thái phiên. Tất cả các thao tác đều hỗ trợ cơ chế bảo vệ quyền sở hữu tùy chọn user được mô tả trong Người dùng cuối.

Hủy Lượt chạy đang hoạt động

POST /sessions/{session_id}/cancel

Hủy lượt chạy tác nhân đang hoạt động. Thao tác này không xóa các tin nhắn đã hoàn tất trước khi hủy.

Nội dung yêu cầu

TrườngLoạiBắt buộcMô tả
run_idstringKhôngCơ chế bảo vệ lượt chạy lỗi thời (stale-run) tùy chọn. Nếu được cung cấp và không khớp với lượt chạy đang hoạt động, API sẽ trả về 409 stale_run

Phản hồi 204 No Content

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400cancel_not_allowedKhông có lượt chạy đang hoạt động để hủy, hoặc không được phép hủy
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
409stale_runrun_id được cung cấp không khớp với lượt chạy đang hoạt động

Hoàn tác Lượt chạy đang hoạt động

POST /sessions/{session_id}/undo

Hủy lượt chạy đang hoạt động, đợi cho lượt chạy đó dừng lại, sau đó xóa mọi tin nhắn mà nó đã thêm vào. Không có đầu ra bổ sung nào được lưu lại sau khi lệnh hoàn tác được thực hiện.

Nội dung yêu cầu

TrườngLoạiBắt buộcMô tả
run_idstringKhôngCơ chế bảo vệ lượt chạy lỗi thời (stale-run) tùy chọn. Nếu được cung cấp và không khớp với lượt chạy đang hoạt động, API sẽ trả về 409 stale_run

Phản hồi 200 OK

{
  "session_id": "ses_abc123",
  "run_id": "run_abc123",
  "deleted": ["msg_002", "msg_001"]
}

Nếu lượt chạy bị hủy trước khi bất kỳ tin nhắn nào được hoàn tất, deleted sẽ là một mảng trống.

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400cancel_not_allowedKhông có lượt chạy đang hoạt động để hoàn tác, hoặc không được phép hủy
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
409stale_runrun_id được cung cấp không khớp với lượt chạy đang hoạt động
409busyPhiên tạm thời không khả dụng vì có một bản cập nhật khác đang được thực hiện

Xóa Tin nhắn gần đây

POST /sessions/{session_id}/messages/delete

Xóa count tin nhắn gần đây nhất từ một phiên đang ở trạng thái nghỉ, bao gồm cả các tin nhắn internal. Sử dụng include=all trên Danh sách Tin nhắn để xem chúng. Phiên không được có lượt chạy đang hoạt động.

Nội dung yêu cầu

TrườngLoạiBắt buộcMô tả
countintegerCóSố tin nhắn gần đây cần xóa tính từ cuối (phải lớn hơn 0). Giá trị lớn hơn 100 được xử lý như 100

Phản hồi 200 OK

{
  "deleted": ["msg_002", "msg_001"]
}

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400bad_requestcount bị thiếu, bằng 0, hoặc âm; hoặc không có tin nhắn nào để xóa
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
409busyPhiên có lượt chạy đang hoạt động

Phân nhánh Phiên

POST /sessions/{session_id}/fork

Tạo một phiên mới bằng cách sao chép phiên nguồn cho đến một tin nhắn cụ thể. Phiên nguồn không được có lượt chạy đang hoạt động.

Nội dung yêu cầu (tùy chọn)

TrườngLoạiBắt buộcMô tả
message_idstringKhôngID tin nhắn tại điểm phân nhánh. Nếu bỏ qua, sẽ phân nhánh từ tin nhắn cuối cùng

Phản hồi 201 Created

Trả về đối tượng phiên vừa được tạo với cấu trúc giống như khi tạo phiên.

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400bad_requestmessage_id không hợp lệ
402insufficient_creditsKhông đủ tín dụng để phân nhánh một phiên
404not_foundmessage_id không tồn tại trong phiên này
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
409busyPhiên nguồn có lượt chạy đang hoạt động

Lấy Trạng thái Lượt chạy

GET /sessions/{session_id}/runs/{run_id}

Trả về trạng thái hiện tại của một lượt chạy đang hoạt động. Sử dụng lệnh này sau khi kết nối SSE bị gián đoạn hoặc sau khi nhận được phản hồi idempotency có chứa run_id. Sau khi lượt chạy hoàn tất, hãy lấy kết quả bằng GET /sessions/{session_id}/messages.

Phản hồi 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"
}

status là running khi tác nhân đang làm việc, streaming khi văn bản phản hồi bắt đầu được tạo ra, hoặc ended trong thời gian ngắn sau khi lượt chạy kết thúc. Phản hồi cũng có thể bao gồm progress_events với hoạt động gần đây, theo cùng định dạng như stream_progress. Khi status là ended hoặc yêu cầu trả về 404 not_found, hãy lấy các tin nhắn của phiên.

Lỗi

Trạng tháiMãĐiều kiện
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user được cung cấp
404not_foundLượt chạy này không đang hoạt động đối với phiên này

Tín dụng

Lấy Số dư

GET /credits/balance

Trả về số dư tín dụng hiện tại của bạn.

Phản hồi 200 OK

{
  "balance": "123.45"
}

API Tác nhân

Tạo và chỉnh sửa các tác nhân tùy chỉnh trong bảng điều khiển. Hỗ trợ API cho việc tạo và chỉnh sửa tác nhân sẽ sớm ra mắt.

Các luồng công việc theo lịch/nền hiện chưa được hỗ trợ qua API. Hỗ trợ sẽ sớm ra mắt.

Danh sách Tác nhân

GET /agents

Trả về các tác nhân khả dụng cho tài khoản của bạn. Sử dụng giá trị agent khi tạo phiên hoặc gửi tin nhắn.

Phản hồi 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"
    }
  ]
}
TrườngLoạiMô tả
agentstringSlug ổn định của tác nhân để truyền vào giá trị agent
display_namestringTên hiển thị thân thiện với con người
descriptionstringMô tả tác nhân

Mô hình

Danh sách Mô hình

GET /models

Trả về tất cả các mô hình khả dụng để sử dụng trong trường model khi gửi tin nhắn hoặc gọi POST /invoke.

Phản hồi 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": "claude-sonnet-5",
      "name": "Claude Sonnet 5",
      "thinking_variant": "claude-sonnet-5-thinking"
    }
  ]
}
TrườngLoạiMô tả
idstringĐịnh danh mô hình ổn định. Truyền giá trị này vào trường model trong Gửi Tin nhắn hoặc Gọi Mô hình
namestringTên hiển thị thân thiện với con người
thinking_variantstringID mô hình của biến thể suy luận/tư duy. Chỉ xuất hiện trên các mô hình cơ sở hỗ trợ suy luận

Các mô hình có thinking_variant hỗ trợ suy luận mở rộng. Sử dụng trực tiếp ID biến thể trong trường model để bật tính năng này.

Nếu không có model nào được chỉ định khi gửi tin nhắn, model của phiên sẽ được sử dụng. Giá trị này được đặt thành mô hình mặc định của tác nhân khi phiên được tạo.


Gọi Mô hình

POST /invoke

Gửi lời nhắc trực tiếp đến mô hình, không qua tác nhân, phiên hay công cụ. Theo mặc định, phản hồi được truyền phát trực tuyến qua SSE; đặt stream: false để nhận JSON.

Nội dung yêu cầu

TrườngLoạiBắt buộcMặc địnhMô tả
modelstringCó-ID mô hình từ Danh sách Mô hình
contentstringCó-Lời nhắc, bao gồm mọi chỉ dẫn
streambooleanKhôngtruetrue để truyền phát trực tuyến qua SSE, false để dùng JSON
userstringKhông-Định danh người dùng cuối bên ngoài của bạn (tối đa 255 ký tự). Nếu bỏ trống, giá trị mặc định sẽ là tài khoản nhà phát triển của bạn

Ví dụ

curl -X POST https://api.jenova.ai/v1/invoke \
  -H "Authorization: Bearer jnv_sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "content": "Describe a forest in one sentence.",
    "stream": false
  }'

Phản hồi 200 OK

{
  "id": "inv_abc123",
  "model": "claude-sonnet-5",
  "content": "Sunlight filters through tall pines onto a quiet, mossy floor.",
  "usage": {
    "cost": "0.0004"
  }
}

Phản hồi truyền phát trực tuyến gửi stream_started, sau đó gửi các sự kiện stream_delta khi mô hình tạo văn bản, và kết thúc bằng stream_ended, trong đó có usage. Nối các giá trị chunk_content theo thứ tự seq để tạo thành phản hồi được truyền phát trực tuyến. Nếu yêu cầu thất bại, stream_error được gửi trước stream_ended. Các sự kiện mang id thay cho session_id và run_id.

usage.cost là null khi không có thông tin chi phí. Nếu một yêu cầu không truyền phát trực tuyến thất bại sau khi lệnh gọi mô hình đã bắt đầu, phản hồi lỗi sẽ bao gồm các trường id và usage ở cấp cao nhất.

Các yêu cầu truyền phát trực tuyến bị giới hạn ở 120 phút. Các yêu cầu không truyền phát trực tuyến chờ kết quả tối đa 30 phút thay vì trả về 202 Accepted, và trả về lỗi nếu đến lúc đó kết quả vẫn chưa sẵn sàng.

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400missing_required_fieldcontent là bắt buộc
400content_too_longNội dung vượt quá 32.000 token
400bad_requestuser vượt quá độ dài tối đa
400invalid_model_selectionThiếu model hoặc không phải ID mô hình hợp lệ
400content_policy_violationNhà cung cấp mô hình từ chối yêu cầu vì lý do chính sách nội dung
400llm_context_limit_reachedĐầu vào vượt quá cửa sổ ngữ cảnh của mô hình
402insufficient_creditsKhông đủ tín dụng để gọi mô hình
500internal_errorLỗi máy chủ không mong đợi
502llm_api_errorLỗi từ nhà cung cấp mô hình hoặc API mô hình phía trên
502llm_empty_responseMô hình trả về phản hồi trống
502llm_reasoning_limit_reachedMô hình đạt giới hạn suy luận mà chưa tạo phản hồi
502llm_generation_limit_reachedMô hình đạt giới hạn tạo nội dung mà chưa tạo phản hồi
503service_unavailableDịch vụ tạm thời không khả dụng

Tài liệu

GET /docs?lang=en
GET /doc?lang=en

Trả về tài liệu tham khảo này dưới dạng Markdown. Sử dụng lang để chọn ngôn ngữ.


Truyền phát trực tuyến (SSE)

Khi stream bị bỏ qua hoặc là true (giá trị mặc định), các phản hồi tin nhắn được gửi dưới dạng Server-Sent Events. Sử dụng các sự kiện message_completed để xác định các tin nhắn đã sẵn sàng để lấy hoặc hiển thị.

Thời gian chờ: Các kết nối SSE duy trì mở cho đến khi lượt chạy kết thúc. Mỗi lượt chạy bị giới hạn ở 120 phút. Các yêu cầu tin nhắn không truyền phát trực tuyến chờ tối đa 90 giây, sau đó trả về 202 Accepted trong khi lượt chạy vẫn tiếp tục. Đối với POST /invoke không truyền phát trực tuyến, xem Gọi Mô hình.

Tiêu đề Kết nối

Các luồng tin nhắn đặt các tiêu đề sau:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
X-Accel-Buffering: no
X-Run-Id: run_abc123

X-Run-Id có sẵn trước khi sự kiện SSE đầu tiên xuất hiện. Các luồng POST /invoke không đặt X-Run-Id; hãy sử dụng id trong stream_started.

Kết nối lại và Khôi phục

Các luồng SSE không được phát lại. Nếu kết nối bị ngắt trên một yêu cầu bền vững, hãy sử dụng session_id và run_id đã ghi lại để khôi phục trạng thái:

curl "https://api.jenova.ai/v1/sessions/ses_abc123/runs/run_abc123" \
  -H "Authorization: Bearer jnv_sk_xxx"

Nếu lượt chạy vẫn đang hoạt động, lệnh này trả về trạng thái hiện tại, văn bản một phần và tiến trình gần đây. Nếu trả về status: "ended" hoặc 404 not_found, nghĩa là lượt chạy không còn hoạt động; hãy lấy các tin nhắn của phiên để đối chiếu đầu ra đã hoàn tất:

curl "https://api.jenova.ai/v1/sessions/ses_abc123/messages?limit=20" \
  -H "Authorization: Bearer jnv_sk_xxx"

Định dạng Khung

Mỗi khung SSE tuân theo định dạng chuẩn sau:

event: <event_type>
data: <json_payload>

Hai dấu xuống dòng kết thúc mỗi khung.

Các loại Sự kiện

Luồng bao gồm các sự kiện vòng đời, delta văn bản, suy nghĩ, tiến trình, cảnh báo, hoàn tất tin nhắn, kết nối MCP, lỗi, cuối cùng và ping. Một số loại sự kiện chỉ được gửi khi có liên quan.

Đối với các yêu cầu tạm thời (ephemeral: true), mọi Sự kiện SSE đều bỏ qua session_id. Chỉ sử dụng run_id để liên kết các Sự kiện trong luồng đó.

Để đối chiếu cuối cùng đối với các yêu cầu bền vững, hãy chờ stream_ended, sau đó gọi Danh sách Tin nhắn.

Các trường phổ biến trên các Sự kiện phạm vi lượt chạy:

TrườngMô tả
session_idID Phiên. Bị bỏ qua đối với các luồng tạm thời. Ghi lại giá trị này từ stream_started để dùng cho các yêu cầu tiếp theo khi sử dụng POST /messages bền vững
run_idID Lượt chạy hiện tại, khi có sẵn
idID yêu cầu invoke (có tiền tố inv_). Chỉ có mặt trong các luồng POST /invoke, vốn không có session_id hay run_id

stream_started

Được gửi một lần khi Lượt chạy bắt đầu.

TrườngMô tả
agentSlug Tác nhân của Phiên, khi có sẵn

stream_delta

Được gửi liên tục khi Tác nhân tạo ra văn bản phản hồi hiển thị. Nối các giá trị chunk_content theo thứ tự seq để tạo thành phản hồi được truyền phát trực tuyến.

event: stream_delta
data: {"session_id":"ses_abc123","run_id":"run_abc123","chunk_content":"To reset your ","seq":1}
TrườngMô tả
chunk_contentĐoạn văn bản
seqSố thứ tự đoạn tăng dần trong luồng

stream_thinking

Được gửi liên tục khi Tác nhân phát ra đầu ra suy nghĩ. Sử dụng trường này cho một chỉ báo suy nghĩ riêng biệt hoặc chế độ xem theo dõi; không nối trường này vào văn bản phản hồi cuối cùng.

TrườngMô tả
contentĐoạn văn bản suy nghĩ

stream_progress

Báo cáo hoạt động hiển thị cho người dùng trong quá trình tạo, chẳng hạn như đọc tài liệu, tìm kiếm trên web hoặc chờ hành động của người dùng. Những sự kiện này dùng để hiển thị tạm thời trong UI; hãy bỏ qua các trường không xác định. Sử dụng các tin nhắn đã hoàn tất làm lịch sử tin nhắn có thẩm quyền.

Đặt include_progress: false trên một yêu cầu tin nhắn để chỉ bỏ qua stream_progress. Các Sự kiện vòng đời, ping, message_completed, lỗi, và các Sự kiện kết thúc vẫn được gửi khi phù hợp.

TrườngMô tả
stateTrạng thái hoạt động: running, success, failed, hoặc skipped. Xử lý các giá trị không xác định một cách hợp lý
labelNhãn hoạt động dễ đọc

Một số Sự kiện tiến trình có thể bao gồm url, file_name, hoặc server_name như các gợi ý hiển thị tùy chọn.

message_completed

Được gửi mỗi khi một Tin nhắn hoàn tất và sẵn sàng để lấy hoặc hiển thị.

Đây là một điểm mốc ranh giới, không phải toàn bộ đối tượng Tin nhắn. Hãy lấy Tin nhắn nếu bạn cần nội dung hoặc metadata.

event: message_completed
data: {"session_id":"ses_abc123","run_id":"run_abc123","message_id":"msg_abc123","sequence":4,"from":{"type":"agent","name":"my-support-agent"},"type":"external"}
TrườngMô tả
message_idID Tin nhắn đã hoàn tất
sequenceSố thứ tự trong Phiên
fromĐối tượng người gửi với type (user hoặc agent) và name
typeLoại Tin nhắn: external hoặc internal

mcp_connection

Được gửi khi tác nhân cần người dùng cuối kết nối hoặc cấp quyền cho một hoặc nhiều máy chủ MCP trước khi có thể tiếp tục. Sự kiện này chỉ khả dụng ở chế độ streaming.

TrườngMô tả
connection_server_listCác máy chủ MCP cần hành động kết nối. Mỗi máy chủ bao gồm mcp_server_id, mcp_server_name, và auth_url tùy chọn
user_action_deadline_unixMốc thời gian Unix khi hành động kết nối của người dùng hết hạn

mcp_connection_resolved

Được gửi khi hành động kết nối MCP của người dùng đã được giải quyết hoặc đã hết hạn.

Không có trường bổ sung nào ngoài các trường phổ biến phạm vi lượt chạy.

warning

Được gửi cho các cảnh báo không nghiêm trọng trong một Lượt chạy.

TrườngMô tả
messageCảnh báo không nghiêm trọng dễ đọc
codeMã cảnh báo tùy chọn

stream_error

Được gửi khi một Lượt chạy thất bại. Một Sự kiện stream_ended cuối cùng có thể theo sau với success: false và stop_reason: "error".

TrườngMô tả
codeMã lỗi
messageThông báo lỗi dễ đọc

stream_ended

Được gửi một lần khi lượt chạy kết thúc. Đây là sự kiện cuối cùng của luồng.

event: stream_ended
data: {"session_id":"ses_abc123","run_id":"run_abc123","success":true,"stop_reason":"end_run","usage":{"cost":"0.0032"}}

Ví dụ lượt chạy bị hủy:

event: stream_ended
data: {"session_id":"ses_abc123","run_id":"run_abc123","success":false,"stop_reason":"user_cancelled","usage":{"cost":"0.0012"}}
TrườngMô tả
successCho biết lượt chạy có hoàn thành thành công hay không
stop_reasonLý do kết thúc lượt chạy: end_run, user_cancelled, user_action_timeout, hoặc error
usageĐối tượng mức sử dụng cho yêu cầu này. cost luôn có mặt và là null khi không có thông tin chi phí

ping

Các khung giữ kết nối được gửi mỗi 15 giây để tránh việc proxy/CDN hết thời gian chờ. Hãy bỏ qua các sự kiện này trong client của bạn.


Tích hợp Máy chủ MCP

Kết nối các Tác nhân của bạn với các công cụ bên ngoài qua Model Context Protocol (MCP):

  • Máy chủ MCP do Jenova quản lý: các máy chủ do Jenova lưu trữ cho tìm kiếm, truy xuất nội dung, tạo tài liệu và các khả năng tích hợp sẵn khác
  • Máy chủ MCP từ xa: các máy chủ MCP từ xa khác được cấu hình cho Tác nhân của bạn

Các máy chủ MCP phải được cấu hình trong bảng điều khiển khi tạo hoặc chỉnh sửa Tác nhân của bạn. Để sử dụng máy chủ MCP riêng của bạn, hãy thêm nó vào một Tác nhân tùy chỉnh, sau đó gọi Tác nhân đó qua API. API sẽ thực thi các Công cụ được bật trong cấu hình của Tác nhân; không cần thiết lập thêm trong các yêu cầu API.

Khi một Tác nhân sử dụng các Công cụ MCP trong khi phản hồi, các Sự kiện tiến trình sẽ được gửi trong luồng ngay khi chúng xảy ra:

event: stream_progress
data: {"session_id":"ses_...","run_id":"run_...","state":"running","label":"Searching Google"}

Nếu tác nhân cần người dùng cuối kết nối hoặc cấp quyền cho một máy chủ MCP trong quá trình chạy, các phản hồi streaming có thể bao gồm các sự kiện mcp_connection và mcp_connection_resolved. Hãy hiển thị danh sách máy chủ kết nối cho người dùng cuối của bạn và mở auth_url được cung cấp khi có. Giữ luồng SSE mở trong khi người dùng cuối kết nối hoặc cấp quyền cho máy chủ.

Sau khi cấp quyền, Jenova lưu trữ token, cửa sổ cấp quyền hiển thị trang hoàn tất, và cùng Lượt chạy đó tiếp tục tự động. Người dùng cuối không cần gửi lại Tin nhắn.

Nếu người dùng cuối không kết nối, cấp quyền, hoặc bỏ qua hay tắt lời nhắc trước user_action_deadline_unix, lượt chạy kết thúc với stop_reason: "user_action_timeout". Bạn cũng có thể hủy lượt chạy đang hoạt động bằng POST /sessions/{session_id}/cancel.

Lưu trữ auth_url ở phía client. Nếu client bị mất kết nối trong quá trình cấp quyền, URL vẫn còn hiệu lực cho đến user_action_deadline_unix. Đối với các yêu cầu bền vững, hãy kiểm tra lượt chạy bằng Lấy Trạng thái Lượt chạy, hoặc lấy các tin nhắn sau khi lượt chạy kết thúc.

Các yêu cầu không streaming (stream: false) không hỗ trợ hành động người dùng kết nối MCP; hãy dùng streaming cho các tác nhân có thể cần tương tác này.

Bỏ qua kết nối MCP

POST /sessions/{session_id}/mcp/connection/skip

Hủy một hành động người dùng kết nối MCP đang chờ xử lý và cho phép lượt chạy tiếp tục mà không có kết nối đó.

Để tắt các lời nhắc kết nối trong tương lai cho một máy chủ đối với cùng một người dùng cuối và tác nhân, hãy bao gồm mcp_server_id và mute. mute chấp nhận một khoảng thời gian như 30m, 24h, hoặc 7d, hoặc forever.

Nội dung yêu cầu

TrườngLoạiBắt buộcMô tả
run_idstringCóID lượt chạy đang hoạt động từ sự kiện mcp_connection
mcp_server_idstringKhôngBắt buộc khi dùng mute; sử dụng mcp_server_id từ sự kiện
mutestringKhôngMột khoảng thời gian như 30m, 24h, hoặc 7d, hoặc forever

Phản hồi 204 No Content

Luồng phát ra sự kiện mcp_connection_resolved, sau đó lượt chạy tiếp tục với cùng run_id.

Lỗi

Trạng tháiMãĐiều kiện
400invalid_payloadJSON không hợp lệ hoặc một trường có loại dữ liệu không hợp lệ
400bad_requestThiếu run_id, không có lượt chạy đang hoạt động, hoặc không có kết nối MCP để bỏ qua
400bad_requestmute không hợp lệ, thiếu mcp_server_id khi đã đặt mute, hoặc mcp_server_id không hợp lệ cho phiên này
404session_not_foundPhiên không tồn tại
404session_not_ownedPhiên thuộc về một nhà phát triển khác hoặc không khớp với user đã cung cấp
409stale_runrun_id không khớp với Lượt chạy đang hoạt động

Thanh toán

Mọi chi phí đều được trừ từ số dư Tín dụng dành cho nhà phát triển của bạn. Xem mức sử dụng và nạp thêm Tín dụng tại www.jenova.ai/platform.

Giá cả

Thao tácChi phí
Tạo Phiên$0.01 cố định cho mỗi Phiên bền vững được tạo bởi POST /sessions hoặc POST /messages
Nhân bản Phiên$0.05 cố định, không tính thêm phí tạo Phiên riêng
Gửi Tin nhắnThay đổi (xem bên dưới)
Gọi Mô hìnhThay đổi, tùy theo mô hình và token

Chi phí Tin nhắn phụ thuộc vào:

  • Mô hình - các Mô hình khác nhau có chi phí trên mỗi token khác nhau
  • Độ dài ngữ cảnh - Phiên dài hơn tiêu thụ nhiều token đầu vào hơn cho mỗi yêu cầu
  • Độ phức tạp của quy trình làm việc - quy trình làm việc dài hơn và việc sử dụng Công cụ nhiều hơn (tìm kiếm web, tạo tệp, phân tích tài liệu) làm tăng tổng mức tiêu thụ token

Chi phí thực tế được trả về dưới dạng stream_ended.usage.cost đối với các yêu cầu Truyền phát trực tuyến và usage.cost đối với các yêu cầu JSON không truyền phát trực tuyến.

Tạm giữ Tín dụng

Mỗi yêu cầu POST /messages, POST /sessions/{session_id}/messages và POST /invoke sẽ đặt một khoản tạm giữ $0.50 trên số dư Tín dụng của bạn trước khi việc thực thi bắt đầu. Điều này nhằm dự trữ tiền cho yêu cầu. Một Tin nhắn được đưa vào hàng đợi của một Lượt chạy đang hoạt động (202 Accepted với status: "queued") không tạo ra khoản tạm giữ bổ sung; mức sử dụng của Lượt chạy đang hoạt động được kiểm tra dựa trên số dư còn lại của bạn.

Khi yêu cầu hoàn tất, khoản tạm giữ được quyết toán theo chi phí thực tế và phần chênh lệch được giải phóng. Nếu chi phí thực tế vượt quá khoản tạm giữ, phần chênh lệch cũng sẽ bị tính phí, vì vậy số dư của bạn có thể xuống dưới 0. Các yêu cầu bị hủy và thất bại chỉ bị tính phí cho mức sử dụng đã phát sinh. Nếu một yêu cầu thất bại trước khi đến được Mô hình, toàn bộ khoản tạm giữ sẽ được giải phóng.

Do có các khoản tạm giữ, số dư khả dụng của bạn có thể tạm thời hiển thị thấp hơn trong khi các yêu cầu đang xử lý. Bạn cần có ít nhất $0.50 trong số dư khả dụng cho một yêu cầu POST /sessions/{session_id}/messages, POST /messages tạm thời, hoặc POST /invoke. Một yêu cầu POST /messages bền vững cũng tạo ra một Phiên và cần ít nhất $0.51 để trang trải khoản tạm giữ cùng với phí tạo Phiên.


Giới hạn tốc độ

Mọi tài khoản nhà phát triển đều chịu ba chiều Giới hạn tốc độ:

ChiềuMặc địnhMô tả
RPM (Yêu cầu mỗi phút)200Cửa sổ cố định 60 giây
RPD (Yêu cầu mỗi ngày)10.000Cửa sổ cố định 24 giờ
Đồng thời10Số lượng yêu cầu đang xử lý và lượt chạy đang hoạt động đồng thời tối đa

Một lượt chạy giữ slot đồng thời cho đến khi kết thúc, kể cả sau phản hồi 202 Accepted hoặc khi client ngắt kết nối. Một yêu cầu POST /invoke giữ slot cho đến khi hoàn tất, kể cả khi client ngắt kết nối.

Các yêu cầu GET và HEAD không tiêu thụ slot đồng thời. cancel, undo và mcp/connection/skip cũng không tiêu thụ slot đồng thời, vì vậy các thao tác này vẫn khả dụng khi tất cả slot đang được sử dụng. Các yêu cầu này vẫn được tính vào RPM và RPD.

Một giới hạn riêng theo từng IP là 1.200 yêu cầu mỗi 60 giây cũng áp dụng cho mọi yêu cầu và trả về cùng lỗi 429 rate_limit_exceeded.

Tiêu đề Phản hồi

Các phản hồi API đã xác thực bao gồm các tiêu đề giới hạn tốc độ:

Tiêu đềMô tả
X-RateLimit-LimitGiới hạn RPM của bạn
X-RateLimit-RemainingSố yêu cầu còn lại trong khung thời gian một phút hiện tại
X-RateLimit-ResetMốc thời gian Unix khi khung thời gian hiện tại được đặt lại
Retry-AfterSố giây cần chờ trước khi thử lại. Được gửi trên các phản hồi 429 rate_limit_exceeded và 503 write_freeze_active

Khi vượt quá giới hạn hàng ngày, X-RateLimit-Limit, X-RateLimit-Remaining và X-RateLimit-Reset sẽ mô tả cửa sổ theo ngày thay vì cửa sổ theo phút.

Khi vượt quá giới hạn, API trả về 429 Too Many Requests:

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please try again later."
  }
}

Xử lý lỗi

Các lỗi HTTP tức thời và lỗi lượt chạy không truyền phát trực tuyến tuân theo một cấu trúc thống nhất:

{
  "error": {
    "code": "error_code_string",
    "message": "Human-readable description"
  }
}

Thông báo lỗi được bản địa hóa dựa trên lang hoặc Accept-Language (xem Bản địa hóa).

Các lỗi Lượt chạy truyền phát trực tuyến được gửi dưới dạng các sự kiện stream_error. Một lượt chạy thất bại vẫn có thể gửi một sự kiện stream_ended cuối cùng với success: false và stop_reason được thiết lập. Các lỗi Lượt chạy không truyền phát trực tuyến bao gồm một đối tượng usage ở cấp cao nhất; cost là null khi không có thông tin chi phí.

Các lỗi sau có thể xảy ra trên bất kỳ điểm cuối nào:

Trạng tháiMãĐiều kiện
401invalid_api_keyKhóa API bị thiếu, không hợp lệ hoặc đã bị thu hồi
402developer_not_activatedTài khoản nhà phát triển của bạn chưa được kích hoạt. Hãy mua tín dụng trong bảng điều khiển để kích hoạt
403developer_disabledTài khoản nhà phát triển của bạn đã bị vô hiệu hóa
403forbiddenCác yêu cầu từ mạng này bị chặn
413payload_too_largeNội dung yêu cầu vượt quá 1 MiB
429rate_limit_exceededĐã vượt quá giới hạn tốc độ. Xem Giới hạn tốc độ
503write_freeze_activeCác yêu cầu ghi tạm thời bị vô hiệu hóa để bảo trì

Các lỗi riêng của từng điểm cuối được ghi chú trực tiếp trong phần mô tả của mỗi điểm cuối.

Lỗi Lượt chạy sau khi Bắt đầu

Lỗi Lượt chạy xuất hiện sau khi một yêu cầu tin nhắn đã được chấp nhận. Ở chế độ truyền phát trực tuyến, chúng xuất hiện dưới dạng các sự kiện stream_error và có thể được theo sau bởi stream_ended với success: false. Ở chế độ không truyền phát trực tuyến, chúng được trả về dưới dạng phản hồi lỗi JSON kèm mã trạng thái HTTP dưới đây.

Mã trạng thái HTTP không truyền phát trực tuyếnMãĐiều kiện
400content_policy_violationNhà cung cấp mô hình từ chối yêu cầu vì lý do chính sách nội dung
400llm_context_limit_reachedĐầu vào vượt quá cửa sổ ngữ cảnh của mô hình
404session_not_foundPhiên đã bị xóa trước khi lượt chạy có thể thực thi
409busyPhiên trở nên bận hoặc tạm thời không khả dụng trước khi lượt chạy có thể bắt đầu
413total_image_size_exceededTổng dung lượng hình ảnh vượt quá giới hạn kích thước cho mỗi yêu cầu của mô hình
500internal_errorLỗi lượt chạy không mong đợi
500response_interruptedLượt chạy bị gián đoạn. Hãy gửi lại tin nhắn
500response_interrupted_message_savedLượt chạy bị gián đoạn sau khi tin nhắn của bạn đã được lưu. Hãy lấy các tin nhắn của phiên trước khi gửi lại
502llm_api_errorLỗi từ nhà cung cấp mô hình hoặc API mô hình phía trên
502llm_empty_responseMô hình trả về phản hồi trống
502llm_reasoning_limit_reachedMô hình đạt giới hạn suy luận mà chưa tạo phản hồi
502llm_generation_limit_reachedMô hình đạt giới hạn tạo nội dung mà chưa tạo phản hồi

Phân trang

Danh sách Phiên và Danh sách Tin nhắn sử dụng phân trang dựa trên con trỏ (cursor-based pagination):

{
  "items": [],
  "next_cursor": "2026-05-19T11:15:00Z|ses_abc123",
  "has_more": true
}
Tham sốLoạiMặc địnhTối đaMô tả
limitinteger20100Số lượng mục trên mỗi trang
cursorstring--Con trỏ ẩn từ next_cursor của lần trước

Truyền next_cursor làm tham số truy vấn cursor để lấy trang tiếp theo, mã hóa URL cho giá trị này. Khi has_more là false, không còn kết quả nào nữa. limit nằm ngoài khoảng 1-100 hoặc con trỏ không hợp lệ sẽ trả về 400 bad_request.


Bản địa hóa

Tất cả các điểm cuối đều nhận tham số truy vấn tùy chọn lang để kiểm soát ngôn ngữ của thông báo lỗi và bất kỳ nội dung được bản địa hóa nào.

NguồnMức ưu tiênVí dụ
Tham số truy vấn langCao nhất?lang=zh
Tiêu đề Accept-LanguageDự phòngAccept-Language: ja
Mặc địnhThấp nhấtTiếng Anh (en)

Bạn có thể thêm ?lang=xx vào bất kỳ URL yêu cầu nào:

POST /sessions?lang=zh
GET /sessions/ses_abc123/messages?lang=ja

Ngôn ngữ được hỗ trợ: en, zh, ja, ko, es, fr, de, it, pt, ru, id, th, vi


Quyền riêng tư và Dữ liệu

Jenova không sử dụng các prompt API, đầu ra, lịch sử hội thoại, tệp đã tải lên, hướng dẫn tác nhân hoặc cơ sở kiến thức để huấn luyện các mô hình của Jenova.

Đối với các nhà cung cấp mô hình bên thứ ba, Jenova sử dụng các kênh API thương mại, cài đặt tài khoản, các cam kết hợp đồng hoặc các tùy chọn từ chối (opt-out) nhằm ngăn nội dung của khách hàng bị sử dụng để huấn luyện các mô hình của nhà cung cấp.

Jenova lưu trữ và xử lý dữ liệu API bằng cơ sở hạ tầng tại Hoa Kỳ. Các nhà cung cấp bên thứ ba có thể xử lý dữ liệu tại các khu vực pháp lý khác như được mô tả trong Chính sách Quyền riêng tư và Điều khoản Sử dụng.

Để biết đầy đủ chi tiết, hãy xem Điều khoản Sử dụng, Chính sách Quyền riêng tư, và Chính sách Sử dụng.


Hỗ trợ