Jenova 智能体 API 参考
基础 URL: https://api.jenova.ai/v1
身份验证: 在 Authorization 标头中携带 Bearer token
目录
概述
无需自行搭建底层技术栈,即可构建并运行可用于生产环境的 AI 智能体。Jenova 智能体 API 将各项核心能力整合到单一的托管服务中:
完整的智能体技术栈
- 智能体编排: 统一的编排层可在复杂工作流中协调模型、工具、记忆和检索。
- 记忆与上下文: 每个会话内置无限的对话记忆与上下文,无需额外的外部状态管理。
- 工具与 MCP: 提供无限的工具集成能力,涵盖平台原生工具以及任意远程 MCP 服务器,开箱即用。
- 可使用任意模型: 通过单一集成,即可使用来自 OpenAI、Anthropic、Google、xAI、Qwen 等提供商的模型驱动您的智能体。
- 全托管存储: 内置 RAG 的托管关系型数据库和向量数据库,无需自行搭建或扩展基础设施。
- 生产级可靠性: 已为数十万用户提供服务。基础设施全托管,API 稳定,专为生产环境流量而设计。
快速入门
1. 获取您的 API 密钥
请在开发者控制面板 www.jenova.ai/platform 中生成 API 密钥。密钥格式为 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"}}
请从 stream_started 事件中获取 session_id,以便用于后续请求。若需了解同步 JSON 响应方式,请参阅发送消息。
核心概念
智能体
您通过 API 交互的 AI 智能体。每个智能体都有一个唯一的 slug(例如 my-support-agent),在 API 调用中作为 agent 值使用。
- 预构建: 从平台上已有的智能体中进行选择。
- 自定义: 在控制面板中配置您自己的智能体,包括指令、模型、知识库、工具和 MCP 服务器。
会话
终端用户与智能体之间的一段独立对话线程。
- 标识符: 带前缀的 ID(例如
ses_abc123) - 范围: 同一个智能体与同一终端用户之间可以存在多个会话,每个会话都拥有独立的对话状态
- 生命周期: 会话会一直保留,直到通过 API 删除为止。对于无需存储的一次性任务,请使用
POST /messages并设置ephemeral: true - 平台隔离: API 会话与 Jenova 网页应用中的对话是相互独立的。终端用户、会话历史记录以及账单在 API 与网页应用之间彼此独立。
消息
会话对话历史中的单条记录,由消息相关端点返回。每条消息都包含一个结构化的 from 对象,其中含有 type("user" 或 "agent")和 name,此外还有消息本身的 type:
external—— 用作聊天内容展示的对话消息。internal—— 一种可选消息,用于表示运行期间智能体的工作步骤,例如工具调用或检索。
运行
发送消息时创建的一次智能体执行。每次运行都有一个 run_id,在活动期间可能会流式传输事件,并会生成一条或多条已完成的消息。每个会话在任意时刻只能有一个活动运行。
终端用户
user 字段用于将会话限定到您应用中的某个终端用户。请使用稳定的不透明 ID,例如您内部的用户 ID 或 UUID。除非您的应用确有需要,请避免使用电子邮件或其他个人身份信息(PII)。使用相同 user 值创建的会话会被归为一组,从而支持按终端用户列出会话。
如果省略 user,则该会话将归属于您的开发者账户,此后无法按终端用户进行筛选。在生产环境中请务必传入 user。
对于针对已有会话的请求,user 是一个可选的所有权校验字段。如果您提供了该字段,其值必须与创建会话时所使用的 user 值一致;否则 API 将返回 404 session_not_owned。请在 GET 和 DELETE 请求中以查询参数形式传递该字段,在 POST 和 PATCH 请求中则以 JSON 正文形式传递。
身份验证
对每个请求都必须使用 Authorization 标头中的 Bearer token 进行身份验证:
Authorization: Bearer jnv_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
API 密钥从开发者控制面板生成。
User-Agent 是可选的。SDK 可以为诊断目的设置该标头,但 API 并不要求提供它。
密钥格式: 密钥以前缀 jnv_sk_ 开头,后跟一个 base62 编码的随机字符串。
限制: 每个开发者账户最多可以拥有 10 个有效 API 密钥。
API 端点
消息 API
发送消息是主要的 API 路径。首次发送消息时使用 POST /messages;该请求会在一次调用中创建会话并启动运行。当需要继续使用已获取的 session_id 时,则使用 POST /sessions/{session_id}/messages。
发送消息
POST /messages
在一次原子请求中创建持久化会话并发送首条消息。将 ephemeral 设为 true 可发起一次不存储数据的流式单次请求,该请求不会存储任何会话或消息历史,不返回会话 ID,且无法继续。
请求正文
| 字段 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
agent | string | 是 | - | 智能体的 slug 标识符 |
content | string | 视情况而定 | - | 消息文本。除非提供了 file_urls,否则为必需 |
file_urls | string[] | 视情况而定 | - | 要附加的文件的 URL。除非提供了 content,否则为必需 |
user | string | 否 | - | 您的外部终端用户标识符(最多 255 个字符)。若省略,则默认为您的开发者账户 |
session_name | string | 否 | - | 新会话的显示名称(最多 200 个字符) |
ephemeral | boolean | 否 | false | 不存储数据、仅流式传输的单次请求。不存储任何会话或消息历史,不返回会话 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 | 无效的临时模式,或 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
向现有的持久化会话发送消息,并接收智能体的响应。默认情况下,响应通过 SSE 流式传输;如需 JSON,请设置 stream: false。
请求正文
| 字段 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
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 | 单次请求中包含超过 10 个文件 URL |
| 400 | unsupported_file_format | 某个文件 URL 的文件扩展名不受支持 |
| 400 | invalid_file_url | 某个文件 URL 格式有误或不是 HTTPS |
| 400 | invalid_model_selection | 模型覆盖值不是有效的生产模型 |
| 402 | insufficient_credits | 额度不足,无法发送消息 |
| 404 | session_not_found | 会话不存在 |
| 404 | session_not_owned | 该会话属于其他开发者,或与提供的 user 不匹配 |
幂等性
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 标头。
流式传输: 该流不会被重放。在运行期间或完成之后重试,都会返回一个幂等性错误,其中包含原始的 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"
}
}
幂等性错误
| 状态码 | 代码 | 条件 |
|---|---|---|
| 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
}
Message 对象
| 字段 | 类型 | 描述 |
|---|---|---|
id | string | 消息 ID(前缀为 msg_) |
session_id | string | 所属会话 ID |
sequence | integer | 会话内的稳定排序编号 |
from | object | 发送者对象,包含 type("user" 或 "agent")和 name |
type | string | 消息类型,对于可见对话消息通常为 external |
time | string | ISO 8601 时间戳 |
content | string | 文本内容。存在于外部消息中 |
model | string | 生成该响应的稳定模型 ID。仅存在于智能体消息中 |
files | array | 该消息附带或生成的文件。每个条目在已知时包含 file_id、name、url、format 和 size |
stop_reason | string | 存在于已完成的智能体消息中。当前值为 end_run |
agent | string | 执行该消息的智能体 slug(如可用) |
agent_name | string | 执行该消息的智能体显示名称(如可用) |
File 对象
| 字段 | 类型 | 描述 |
|---|---|---|
file_id | string | Jenova 文件 ID(如可用) |
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 | 该会话中不存在此消息 |
文件附件
在 file_urls 字段中传入可公开访问的 HTTPS URL。
| 限制 | 值 |
|---|---|
| 每条消息最大文件数 | 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
创建绑定到特定智能体的空持久会话。当您需要在发送第一条消息之前获取会话 ID 时使用此端点;否则请优先使用 POST /messages。
说明:
POST /sessions不接受ephemeral参数;如需不存储数据的一次性请求,请对POST /messages使用ephemeral: true。
请求正文
| 字段 | 类型 | 必需 | 描述 |
|---|---|---|---|
agent | string | 是 | 智能体的 slug 标识符 |
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 | 分页游标 |
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、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 连接中断或幂等性响应返回了 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 | 用作 agent 值的稳定智能体标识(slug) |
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 值传入 |
name | string | 便于阅读的显示名称 |
thinking_variant | string | 思维/推理变体的模型 ID。仅在支持推理的基础模型上存在 |
带有 thinking_variant 的模型支持扩展推理。要启用它,请直接在 model 字段中使用该变体 ID。
如果发送消息时未指定 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。临时流中会省略此字段。当使用持久性 POST /messages 时,请从 stream_started 中获取该值,用于后续请求 |
run_id | 当前运行 ID(如可用) |
stream_started
运行开始时发送一次。
| 字段 | 描述 |
|---|---|
agent | 会话智能体 slug(如可用) |
stream_delta
在智能体生成可见响应文本时反复发送。按 seq 顺序拼接 chunk_content 值即可构建流式传输的响应。
event: stream_delta
data: {"session_id":"ses_abc123","run_id":"run_abc123","chunk_content":"To reset your ","seq":1}
| 字段 | 描述 |
|---|---|
chunk_content | 文本块 |
seq | 流内单调递增的分块序号 |
stream_thinking
在智能体输出思考内容时反复发送。请将其用于单独的思考指示器或跟踪视图;不要将其拼接进最终响应文本中。
| 字段 | 描述 |
|---|---|
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
每当消息完成并可供获取或渲染时发送。
这是一个边界标记,并非完整的消息对象。如需内容或元数据,请获取该消息。
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 时间戳 |
mcp_connection_resolved
当 MCP 连接用户操作已解决或已过期时发送。
除通用运行范围字段外,无其他附加字段。
warning
在运行过程中出现非致命警告时发送。
| 字段 | 描述 |
|---|---|
message | 人类可读的非致命警告信息 |
code | 可选的警告代码 |
stream_error
运行失败时发送。随后可能会跟随一个 success:false、stop_reason:"error" 的最终 stream_ended 事件。
| 字段 | 描述 |
|---|---|
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
每 15 秒 发送一次的保活帧,用于防止代理/CDN 超时。您的客户端应忽略这些帧。
MCP 服务器集成
通过 Model Context Protocol (MCP) 将您的智能体连接到外部工具:
- Jenova 托管的 MCP 服务器: 由 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 之前仍然有效。对于持久化请求,可通过获取运行状态重新连接,或在运行结束后获取消息。
非流式请求(stream: false)不支持 MCP 连接用户操作;对于可能需要此类交互的智能体,请使用流式传输。
跳过 MCP 连接
POST /sessions/{session_id}/mcp/connection/skip
驳回一个待处理的 MCP 连接用户操作,使运行无需该连接即可继续。
若要为同一 API 用户静音某个服务器未来的连接提示,请包含 mcp_server_id 和 mute。支持的值为 24h 和 forever。
请求正文
| 字段 | 类型 | 必需 | 描述 |
|---|---|---|---|
run_id | string | 是 | 来自 mcp_connection 事件的当前活动运行 ID |
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 无效,或设置 mute 时缺少 mcp_server_id |
| 404 | session_not_found | 会话不存在 |
| 404 | session_not_owned | 与提供的 user 不匹配 |
| 409 | stale_run | run_id 与当前活动运行不匹配 |
账单
所有费用均从您的开发者额度余额中扣除。可在 www.jenova.ai/platform 查看用量并充值额度。
定价
| 操作 | 费用 |
|---|---|
| 创建会话 | 每个持久会话统一收取 $0.01,包括由 POST /messages 隐式创建的会话 |
| 派生会话 | 统一收取 $0.05 |
| 发送消息 | 可变(见下文) |
消息费用取决于以下因素:
- 模型 - 不同模型的每 token 费用不同
- 上下文长度 - 会话越长,每次请求消耗的输入 token 越多
- 工作流复杂度 - 更长的工作流以及更繁重的工具使用(网络搜索、文件生成、文档分析)会增加总 token 消耗
对于流式请求,实际费用以 stream_ended.usage.cost 返回;对于非流式 JSON 请求,则以 usage.cost 返回。
额度冻结
每次新的消息运行在开始执行前,都会在您的额度余额上产生 $0.50 的冻结。这是为该运行预留资金。在活动运行中排队的后续消息不会产生额外的冻结;该活动运行的用量会与您的剩余余额进行核对。
运行完成后,冻结金额会结算为实际费用,差额将被释放。已取消和失败的运行仅按已产生的用量计费。如果请求在到达模型之前失败,全部冻结金额都会被释放。
这意味着在请求进行期间,您的可用余额可能会暂时显示较低。要向现有会话发送消息或发送临时消息,您的可用余额至少需要 $0.50。首次通过持久性的 POST /messages 请求会创建一个会话,因此至少需要 $0.51,以覆盖消息冻结额外加上创建会话的费用。
速率限制
每个开发者账户均受以下三个速率限制维度的约束:
| 维度 | 默认值 | 描述 |
|---|---|---|
| RPM(每分钟请求数) | 60 | 按分钟计算的固定窗口 |
| RPD(每日请求数) | 1,000 | 按天计算的固定窗口 |
| 并发数 | 5 | 同时进行中的请求的最大数量 |
GET 和 HEAD 请求不占用并发名额。cancel、undo 以及 mcp/connection/skip 也不占用并发名额,因此即使所有名额都已被占用,这些操作仍然可用。这些请求仍会计入 RPM 和 RPD。
响应标头
经过身份验证的 API 响应中包含速率限制标头:
| 标头 | 描述 |
|---|---|
X-RateLimit-Limit | 您的 RPM 限制 |
X-RateLimit-Remaining | 当前一分钟窗口内剩余的请求数 |
X-RateLimit-Reset | 当前窗口重置的 Unix 时间戳 |
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 事件,随后可能跟随 success:false 的 stream_ended 事件。在非流式传输模式下,它们以 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 错误 |
分页
列表端点使用基于游标的分页:
{
"items": [],
"next_cursor": "eyJ2IjoxLCJrIjoiY3VyXzAyIn0",
"has_more": true
}
| 参数 | 类型 | 默认值 | 最大值 | 描述 |
|---|---|---|---|---|
limit | integer | 20 | 100 | 每页的项目数量 |
cursor | string | - | - | 来自上一次响应中 next_cursor 的不透明游标 |
将 next_cursor 作为 cursor 查询参数传入以获取下一页。当 has_more 为 false 时,表示没有更多结果。
本地化
所有端点都接受可选的 lang 查询参数,用于控制错误消息及任何本地化内容所使用的语言。
| 来源 | 优先级 | 示例 |
|---|---|---|
lang 查询参数 | 最高 | ?lang=zh |
Accept-Language 标头 | 备用 | Accept-Language: ja |
| 默认值 | 最低 | 英语(en) |
您可以在任意请求 URL 后附加 ?lang=xx:
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]