服务 API
kimi web 启动的本地服务暴露两组程序化接口:REST API(/api/v1,另有 /api/v2/sessions 和 /api/v2/mcp)和 WebSocket 事件流(/api/v1/ws)。本页是这两组接口的协议参考。如何启动服务及其命令行选项见 kimi 命令 参考;端到端的上手流程见下文「用 API 驱动一个会话」。
本页是一份经过整理、面向人阅读的参考:下文逐一记录每个端点的参数、请求体与响应结构。每个端点精确的机器可读 schema 以服务的在线规范文档为准:GET /openapi.json(OpenAPI)与 GET /asyncapi.json(AsyncAPI),两者都由服务运行时实际执行的校验 schema 生成。两者都需要鉴权;当本页与在线规范不一致时,以在线规范为准。
注意
本页描述的 REST 与 WebSocket API 为实验性特性:不保证接口稳定性,端点、字段与事件类型可能随任何版本更改。集成时请以你所用版本服务的 /openapi.json 与 /asyncapi.json 文档为准。
基础约定
地址
默认地址为 http://127.0.0.1:58627。端口被占用时,服务会用下一个端口重试(至多 100 次);可用 --port / --host 修改绑定。同一 home 目录下可并存多个实例,运行中的实例登记在 ~/.kimi-code/server/instances/。
鉴权
除以下例外,所有 /api/* 路径(含 /openapi.json 与 /asyncapi.json)都要求 bearer token:
OPTIONS预检请求GET /api/v1/healthz(探活)- 静态 web 资源(非
/api/路径)
携带方式:REST 用 Authorization: Bearer <token> 请求头;WebSocket 升级请求接受同一请求头,或子协议 kimi-code.bearer.<token>。token 的生成与轮换见 在网页中使用:开始使用。
鉴权失败返回 HTTP 401,信封 code 为 40101。在非 loopback 绑定上,同一来源 60 秒内鉴权失败 10 次会被封禁 60 秒,期间每个请求都返回 HTTP 429(code 为 42901)。
响应信封
所有 JSON 响应统一包在信封里:
{
"code": 0,
"msg": "success",
"data": {},
"request_id": "01JZX4A6E7M8V0R3Q0N2K2M5Q9"
}code:业务结果,0表示成功;错误码分段见下文。data:成功时的业务数据。注意部分「错误」信封也携带非空data——例如无法执行的撤销返回40911,data为{ reason, requestedCount, undoableCount }——客户端应先判code再看data。request_id:本次请求的 ULID;客户端可用X-Request-Id请求头指定,非法值会被服务端重新生成。
HTTP 状态码几乎总是 200,业务结果以 code 为准。例外情况:
| 场景 | HTTP 状态 |
|---|---|
| 鉴权失败 / 触发限流 | 401 / 429 |
| 创建供应商、导入供应商目录成功 | 201 |
| 删除供应商成功 | 204 |
| 二进制与流式端点 | 支持时返回 206(Range 分段)/ 304(ETag 未变),各端点能力不同,详见「二进制与流式端点」 |
GET /api/v1/files/{file_id}、/api/v1/fs:content 与会话 :download 错误 | 真实 4xx / 500(响应体仍为信封) |
其中 201 的响应体仍是标准信封(code 为 0),只是状态行遵循 REST 的资源创建惯例;204 按定义没有响应体,删除成功以状态码本身为准。
错误码
错误码按段位分组:
| 段位 | 含义 | 示例 |
|---|---|---|
0 | 成功 | |
400xx | 请求参数错误 | 40001 校验失败(details 逐字段说明)、40003 供应商由 OAuth 托管、40006 工作区源文件夹重复 |
401xx | 鉴权与就绪状态 | 40101 未授权、40110 未配置供应商、40113 模型未解析 |
404xx | 资源不存在 | 40401 会话、40408 MCP 服务、40409 文件路径 |
409xx | 状态冲突 | 40901 会话忙、40902 交互已结束、40922 分页条件与 page_token 不符、40931 会话正被其他客户端使用、40932 会话已被其他客户端更新、40935 无法进入 Tower 模式 |
413xx | 体积或边界超限 | 41302 读取文件超 10 MB、41304 路径越出会话目录 |
429xx | 限流 | 42901 鉴权失败封禁、42902 文件监听数超限 |
500xx | 服务端内部错误 | 50001 未捕获异常、50003 持久化失败 |
6xxxx / 7xxxx / 8xxxx | 工具运行时 / LLM 供应商 / MCP 透传错误,msg 保留上游原文 |
40931 和 40932 只在同一会话被多个客户端打开时出现。40931 表示另一个 Kimi Code 进程正在写入该会话,等它空闲后重试即可。如果确认该进程已退出、只是留下了锁,可以调用 POST /api/v1/sessions/{session_id}:takeover 后再重试。会话已被其他客户端更新时,提交 prompt、激活 skill 和压缩会在服务端重新载入会话、向订阅者推送最新的 turns 帧,然后重新执行请求,调用方不会从这些接口收到 40932。只有撤销会返回 40932:服务端已重新载入会话,本次没有撤销任何内容;请让用户先查看刷新后的历史,再决定是否撤销。
分页
列表端点有两种分页风格:
- 游标式:
before_id/after_id(互斥)加page_size(1–100),响应为{ items, has_more }。用于会话列表、消息列表等。Agent 的轮次改按轮次ordinal分页(before_ordinal/page_size)。 page_token:不透明令牌(绑定了查询条件的指纹),用于POST /api/v1/search与GET /api/v2/sessions。翻页途中改变任何查询条件会使令牌失效:v2 返回40922,search 返回40001。GET /api/v2/sessions另提供无状态的page页码模式作为替代。
用 API 驱动一个会话
下面用 curl 走一遍最小流程:确认服务状态 → 创建会话 → 订阅事件 → 提交提示词 → 回读历史。示例假设服务跑在默认地址,token 已存入 shell 变量 TOKEN。
- 确认服务状态:
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:58627/api/v1/meta所有 JSON 响应都包在统一信封里——{ "code": 0, "msg": "success", "data": ..., "request_id": "..." },业务结果以 code 为准(0 表示成功),HTTP 状态码只表达传输层结果。
- 创建会话,
metadata.cwd指定工作目录:
curl -s -X POST http://127.0.0.1:58627/api/v1/sessions \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"metadata": {"cwd": "/path/to/project"}}'返回的 data.id(形如 session_...)就是后续所有请求要用的会话 id。
- 连接 WebSocket 并订阅会话事件。任何 WebSocket 客户端都可以;下面是一个零依赖的 Node.js 脚本(Node.js 22+ 内置
WebSocket客户端):
// subscribe.mjs —— 用法:TOKEN=... node subscribe.mjs session_...
const ws = new WebSocket('ws://127.0.0.1:58627/api/v1/ws', [
`kimi-code.bearer.${process.env.TOKEN}`,
]);
ws.onmessage = (e) => console.log(e.data);
ws.onopen = () =>
ws.send(
JSON.stringify({
type: 'subscribe',
request_id: '1',
session_id: process.argv[2],
}),
);- 提交提示词:
curl -s -X POST http://127.0.0.1:58627/api/v1/sessions/<session_id>/prompts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": [{"type": "text", "text": "用一句话介绍这个仓库"}]}'订阅端先收到一条带 main agent 最近轮次的 turns 帧,之后依次看到 turn.started(轮次开始)→ 提示词的 item.ended → 思考、回复与工具调用流式产生时的 item.started、item.delta、item.ended → 一步结束时的 turn.updated → turn.ended(轮次结束)。见 对话协议。
- 随时可以用 REST 回读历史消息:
curl -s -H "Authorization: Bearer $TOKEN" \
"http://127.0.0.1:58627/api/v1/sessions/<session_id>/messages?page_size=20"REST 端点
下文按资源分组列出端点。路径里的 :{action} 后缀是动作约定——对单个资源 POST 到 路径:动作 执行非 CRUD 操作(如会话的 :fork、:archive)。
服务与元信息
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/healthz | 探活,免鉴权 |
GET /api/v1/meta | 服务版本、能力集、server_id、实验开关 |
POST /api/v1/shutdown | 优雅退出(先回 200 再关闭);仅 loopback 绑定时挂载 |
GET /api/v1/healthz
供脚本与进程管理器使用的探活端点。它是唯一豁免 bearer token 的 /api 端点(见 鉴权),应答时不触碰配置与引擎。
成功时 data 为 { "ok": true }。
GET /api/v1/meta
返回本实例的身份信息与能力集。大多数字段在启动时即固定;experimental_flags 与 features 按请求实时解析,因此开关翻转或某个 feature 失败会体现在下一次响应中。
成功时 data 携带:
| 字段 | 类型 | 说明 |
|---|---|---|
server_version | string | 服务版本 |
capabilities | object | 能力集——websocket、file_upload、fs_query、mcp、tasks,均恒为 true |
server_id | string | 本服务实例的唯一 id |
started_at | string | 启动时间,ISO 8601 格式 |
open_in_apps | array | 可作为 open-in 目标的宿主应用(finder / cursor / vscode / iterm / terminal);目前恒为空 |
dangerous_bypass_auth | boolean | 服务是否以 --dangerous-bypass-auth 启动(客户端可跳过 token 提示) |
backend | string | 引擎后端,v1 或 v2;本服务恒为 v2 |
web_title | string | 来自 --web-title 的自定义浏览器标签页标题;未设置时省略 |
experimental_flags | object | 实验开关 id → 是否启用,按请求时解析 |
features | array | 引擎 feature,形如 { name, state, meta };state 为 Pending / Activating / Active / Unloading / Failed |
POST /api/v1/shutdown
请求服务优雅退出。响应先发出,随后立即执行关闭,因此调用方可以信任收到的响应。该路由仅在 loopback 绑定时挂载——非 loopback 绑定时它根本不会被注册(请求得到 404),除非服务以 --allow-remote-shutdown 启动。
成功时 data 为 { "ok": true }。
登录与用量
这组端点驱动托管 Kimi OAuth 登录的生命周期,并暴露账号级信息。托管供应商名为 managed:kimi-code;下面每个端点上可选的 provider 参数都默认取它。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/auth | 鉴权状态快照 |
POST /api/v1/oauth/login | 发起 OAuth device-code 登录流程 |
GET /api/v1/oauth/login | 轮询登录流程状态 |
DELETE /api/v1/oauth/login | 取消进行中的登录流程 |
POST /api/v1/oauth/logout | 登出托管供应商 |
GET /api/v1/oauth/usage | 套餐额度与加油包 |
GET /api/v1/oauth/userinfo | 账号资料 |
GET /api/v1/oauth/region | 解析客户端所属区域(mainland-cn / global) |
GET /api/v1/auth
鉴权状态快照:默认模型能否解析到可用的供应商配置,以及托管供应商的登录状态。当全局 default_model 别名存在于模型表中且能解析到已配置的供应商时,models_ready 为 true——包括自带 base_url 的平铺(providerless)模型,以及通过 KIMI_MODEL_* 环境变量注入的模型。它不做凭据校验,因此此后的对话请求仍可能以 40111 / 40112 失败。
成功时 data 携带 models_ready(布尔值)、providers_count(已配置供应商数量)与 managed_provider(null,或 { name, status },其中 status 为 authenticated / expired / revoked / unauthenticated 之一)。全局默认模型别名本身改从 GET /api/v1/config 的 default_model 读取,本端点不再携带。
POST /api/v1/oauth/login
为托管供应商发起 OAuth device-code 登录流程;发起新流程会中止同一供应商进行中的流程。账号已登录时无需用户交互,响应会立即报告 authenticated。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider | body | string | 托管供应商名称。默认 managed:kimi-code |
region | body | string | mainland-cn 或 global;覆盖 GET /api/v1/oauth/region 一节描述的区域解析结果,仅对本次流程生效 |
成功时 data 有两种形态。进行中的流程——{ flow_id, provider, status: "pending", verification_uri, verification_uri_complete, user_code, expires_in, interval, expires_at }:打开 verification_uri_complete(或打开 verification_uri 并输入 user_code),然后每隔 interval 秒轮询 GET /api/v1/oauth/login,直到流程完结或超过 expires_at(expires_in 是以秒表示的同一时限)。已登录的快速路径——{ flow_id, provider, status: "authenticated" }。
GET /api/v1/oauth/login
轮询某供应商的登录流程状态。尚未发起过流程时返回 null。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider | query | string | 托管供应商名称。默认 managed:kimi-code |
成功时 data 为 null 或流程快照:{ flow_id, provider, status, verification_uri, verification_uri_complete, user_code, expires_in, expires_at, interval },其中 status 为 pending / authenticated / denied / expired / cancelled。流程离开 pending 后,resolved_at 记录其到达终态的时间,error_message 描述失败的流程。
DELETE /api/v1/oauth/login
取消某供应商进行中的登录流程。没有进行中的流程时,该调用为空操作,返回最近一次已知状态。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider | query | string | 托管供应商名称。默认 managed:kimi-code |
成功时 data 为 { cancelled, status }:只有确实中止了一个 pending 流程时 cancelled 才为 true,status 为调用后的流程状态。
POST /api/v1/oauth/logout
登出托管供应商:丢弃已存储的 OAuth 凭据、中止进行中的登录流程,并把托管供应商从配置中移除。OAuth 托管的供应商拒绝手动编辑与删除(见下文 PUT / DELETE /api/v1/providers/{provider_id}),因此要移除它需先登出。
对默认 Kimi 供应商(managed:kimi-code),登出还会拆除本机的远程控制并清除缓存的远程控制云端会话。当没有隧道运行或隧道由本机其他进程持有时,登出会先把本机设备下线并持有本机锁,确保凭据被丢弃之前本机任何进程都无法再次开启远程控制;清理失败会中止登出。当隧道由本服务持有时,先丢弃凭据,隧道在响应发出后随即拆除,因此通过远程控制链接发起的登出仍能收到响应。登出其他供应商不影响远程控制。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider | body | string | 托管供应商名称。默认 managed:kimi-code |
成功时 data 为 { logged_out: true, provider }。
GET /api/v1/oauth/usage
托管账号的套餐额度与加油包,实时取自账号服务。上游失败不会让信封失败——它以 kind: "error" 的形式带内返回。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider | query | string | 托管供应商名称。默认 managed:kimi-code |
成功时 data 为 { kind: "ok", quota } 或 { kind: "error", message, status? },其中 status 为上游 HTTP 状态码(如存在)。在 ok 形态中,quota 为 { usages, extraUsage }:usages 按窗口携带 { usedRatio, resetAt? } 条目——limit5h、limit7d、monthTotal、monthCode——其中 usedRatio 为 0–1 浮点数,resetAt 为 RFC3339 重置时间,客户端按实际下发的条目渲染;extraUsage(可空)是按量付费钱包:{ balanceCents, totalCents, monthlyChargeLimitEnabled, monthlyChargeLimitCents, monthlyUsedCents, currency }。
GET /api/v1/oauth/userinfo
托管账号的资料,带内 kind: "error" 约定与 GET /api/v1/oauth/usage 相同。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider | query | string | 托管供应商名称。默认 managed:kimi-code |
成功时 data 为 { kind: "ok", userInfo } 或 { kind: "error", message, status? }。userInfo 始终携带 userId、nickname、status、region、userLevel、userLevelName、domain、domainName,并可能附加 globalId、bio、avatar、username、email、phone({ countryCode, number })、createdTime 与 lastLoginTime。
GET /api/v1/oauth/region
解析该客户端所属的 Kimi 区域,结果在本地推导,不经网络探测。优先取环境变量或配置固定的 OAuth host,其次是已配置的 OAuth key,再次是 <home>/region 中的安装渠道标记。
客户端未登录且上述输入都无法决定区域时,会根据设备时区和语言环境进行推断。成功结果缓存到 <home>/region.json,登录状态变化时失效;原始时区和语言环境值不会上传。信号缺失或冲突时,本次进程回退到 mainland-cn,但不持久化该结果,下次启动会重新判断。设置 KIMI_CODE_REGION_MARKER=off 可同时禁用安装渠道标记和本地推断。
成功时 data 为 { region },region 为 mainland-cn / global 之一。
远程控制
这组端点管理机器级的远程控制隧道(见 远程控制指南)和账号的设备注册表。隧道状态按机器区分;设备注册表按账号区分、保存在云端,因此设备端点需要 Kimi 登录,并由服务端持会话代理到 relay——OAuth 凭据不会暴露给调用方。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/remote-control | 读取隧道状态 |
POST /api/v1/remote-control | 开启或关闭隧道 |
GET /api/v1/remote-control/devices | 列出账号下的设备 |
PATCH /api/v1/remote-control/devices/{id} | 重命名设备 |
POST /api/v1/remote-control/devices/{id}/deactivate | 让设备下线 |
DELETE /api/v1/remote-control/devices/{id} | 从注册表中删除设备 |
GET /api/v1/remote-control
返回当前隧道状态。当隧道处于关闭状态、但本机另一个存活进程持有单实例锁时,data.conflict 携带该持有者信息;每次读取都会重新检查锁,持有者进程退出后 conflict 与已存的 error 会一并清除。
成功时 data 为 { enabled, state, url?, device_id?, device_name?, error?, conflict? },其中 state 为 off / starting / on / stopping 之一,conflict 为 { pid, local_origin, device_id, url, started_at }。
POST /api/v1/remote-control
开启或关闭隧道。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
enabled | body | boolean | true 开启隧道,false 关闭隧道 |
成功时 data 与 GET /api/v1/remote-control 的状态对象相同。当本机另一个存活进程持有单实例锁时,开启会失败并返回 REMOTE_CONTROL_ALREADY_RUNNING(40928),details 中携带与 conflict 相同结构的锁持有者信息。
GET /api/v1/remote-control/devices
从云端注册表列出账号的远程控制设备。
成功时 data 为 { devices, max_devices? }。每个设备为 { device_id, alias, status, platform, client_version, local_base_url, created_at, updated_at, last_remote_access_at },其中 status 为 online / offline 之一。
PATCH /api/v1/remote-control/devices/{id}
重命名设备。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | string | 设备标识 |
alias | body | string | 新的显示名称,去除首尾空白;1–50 个字符 |
名称为空或超长时,在到达云端之前即返回 VALIDATION_FAILED。成功时 data 为 { ok: true }。
POST /api/v1/remote-control/devices/{id}/deactivate
在云端注册表把设备置为离线。离线设备保留在列表中,且不占用套餐的设备额度;该设备下次开启远程控制时恢复在线。当目标设备是本机时,先停止本地隧道(启动中的开启会被取消);随后请求持有本机锁完成下线,确保并发的开启无法在成功响应背后重新注册设备。持有者未在限定时间内停止时,请求以 INTERNAL_ERROR 失败,而不是报告成功。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | string | 设备标识 |
成功时 data 为 { ok: true }。
DELETE /api/v1/remote-control/devices/{id}
把设备从云端注册表移除:设备从列表中消失,仍在连接的隧道会被断开。下线只是把设备置为离线并保留在列表中;删除则把它整个移除。当目标设备是本机时,先停止本地隧道并持有本机锁完成删除,确保设备无法在成功响应背后重新注册。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | string | 设备标识 |
成功时 data 为 { ok: true }。
配置
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/config | 读取全局配置(密钥字段脱敏) |
POST /api/v1/config | 合并式更新配置,并广播 event.config.changed |
POST /api/v1/client_configs | 读取由 Kimi Code 服务远程控制的指定客户端配置 |
GET /api/v1/config
返回解析后的全局配置——config.toml 叠加覆盖层后的生效结果。密钥已脱敏:每个供应商只报告 has_api_key,绝不返回存储的密钥。
成功时 data 为配置对象;其字段与 顶层字段 记录的顶层域一一对应:
| 字段 | 类型 | 说明 |
|---|---|---|
providers | object | 供应商 id → { type, base_url?, default_model?, has_api_key } 的映射 |
default_provider | string | 全局默认供应商 id |
default_model | string | 全局默认模型别名 |
models | object | 模型别名 → 模型记录的映射 |
thinking | object | Thinking 模式的默认参数 |
plan_mode | boolean | Plan 模式开关 |
yolo | boolean | 派生值:default_permission_mode 为 yolo 时为 true |
default_permission_mode | string | 新会话的默认权限模式 |
default_plan_mode | boolean | 新会话是否以 Plan 模式启动 |
permission | object | 初始权限规则 |
hooks | array | 生命周期钩子 |
services | object | 内置外部服务配置 |
merge_all_available_skills | boolean | 是否合并所有可用目录中的 Agent Skills |
extra_skill_dirs | array | 额外的 Skill 搜索目录 |
loop_control | object | Agent 循环控制参数 |
background | object | 后台任务运行参数 |
subagent | object | subagent 配置 |
secondary_model | object | subagent 的次级模型池 |
experimental | object | 实验开关 id → 是否启用 |
telemetry | boolean | 是否启用匿名遥测 |
auto_session_title | boolean | 是否允许客户端自动生成会话标题 |
disable_feedback_survey | boolean | 是否关闭会话评分提示 |
raw | object | 原始解析的 config.toml 内容,包含未建模字段 |
POST /api/v1/config
合并式更新全局配置:请求体中的每个顶层域被深合并进对应域,未出现在请求体中的域保持不动。把 yolo 设为 true 是 default_permission_mode: "yolo" 的简写;被拒绝的补丁(值非法或持久化失败)返回 40001 与底层错误信息。
每一次配置变更——经本端点成功更新、在进程外编辑 config.toml,或服务端内部写入(如 OAuth 登录刷新)——都会广播全局 event.config.changed 事件。短时间窗内的多次变更会合并为一个事件,其 changedFields 携带受影响的域名(camelCase 配置域,例如 defaultModel),config 携带当前完整的配置投影(与 GET /api/v1/config 响应同形状)。
请求体是部分配置对象——上述响应域中除 raw 外的任意子集,均为可选:
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
providers | body | object | 供应商 id → 供应商表的映射 |
default_provider | body | string | 全局默认供应商 id |
default_model | body | string | 全局默认模型别名 |
models | body | object | 模型别名 → 模型记录的映射 |
thinking | body | object | Thinking 模式的默认参数 |
plan_mode | body | boolean | Plan 模式开关 |
yolo | body | boolean | true 映射为 default_permission_mode: "yolo";false 被忽略 |
default_permission_mode | body | string | manual / yolo / auto |
default_plan_mode | body | boolean | 新会话是否以 Plan 模式启动 |
permission | body | object | 初始权限规则 |
hooks | body | array | 生命周期钩子 |
services | body | object | 内置外部服务配置 |
merge_all_available_skills | body | boolean | 是否合并所有可用目录中的 Agent Skills |
extra_skill_dirs | body | array | 额外的 Skill 搜索目录 |
loop_control | body | object | Agent 循环控制参数 |
background | body | object | 后台任务运行参数 |
subagent | body | object | subagent 配置 |
secondary_model | body | object | subagent 的次级模型池 |
experimental | body | object | 实验开关 id → 是否启用 |
telemetry | body | boolean | 是否启用匿名遥测 |
auto_session_title | body | boolean | 是否允许客户端自动生成会话标题 |
disable_feedback_survey | body | boolean | 是否关闭会话评分提示 |
成功时 data 为完整的更新后配置,形态与 GET /api/v1/config 相同。
POST /api/v1/client_configs
读取由 Kimi Code 服务远程控制的指定客户端配置——哪些模型或思考强度的切换需要用户确认,以及客户端的升级策略。服务端从账号所在区域的 Kimi Code 服务读取(设置了 KIMI_CODE_BASE_URL 时改用该地址),并规范化成该名称预期的结构。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
name | body | string | 必填。 model_switch_confirm、effort_switch_confirm 或 client_upgrade_policy |
成功时,data 为 { name, config }。名称不在上述范围内或读取失败时,config 为 null,客户端回退到内置行为。读到的值不会变成 null:缺失或格式不对的字段取关闭状态的默认值,例如格式不对的 model_switch_confirm 会返回 { enable: false, rules: [] }。
模型与供应商
这组端点管理模型配置的两半——config.toml 的 供应商 表与模型别名表——外加一个由服务端代理的 models.dev 目录,用于一次性导入。模型别名 id 就是配置中的别名键:通过供应商管理端点创建的别名形如 provider_id/model(例如 my-provider/kimi-for-coding),而模型别名表中的裸键(如 turbo)原样使用;API 中任何接收 model_id 的地方(包括全局 default_model)指的都是这个别名 id。:{action} 路由上不支持的动作返回 40001。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/models | 列出已配置的模型别名 |
POST /api/v1/models/{model_id}:set_default | 设置全局默认模型 |
GET /api/v1/providers | 列出供应商 |
POST /api/v1/providers | 创建供应商(201) |
GET /api/v1/providers/{provider_id} | 读取供应商(含已存密钥) |
PUT /api/v1/providers/{provider_id} | 整体替换供应商配置 |
DELETE /api/v1/providers/{provider_id} | 删除供应商(204) |
POST /api/v1/providers/{provider_id}:refresh | 刷新该供应商的模型元数据 |
POST /api/v1/providers:{action} | 集合级动作:refresh / refresh_oauth / import_catalog / import_registry |
GET /api/v1/catalog/providers | 浏览 models.dev 目录(服务端代理) |
GET /api/v1/catalog/providers/{catalog_id} | 读取目录中单个条目 |
GET /api/v1/models
列出所有供应商下已配置的模型别名。
成功时 data.items 为 { provider, model, display_name?, max_context_size, capabilities?, support_efforts?, default_effort?, upgrade? } 数组:model 是别名 id(供应商管理的别名为 provider_id/model,否则为裸键),provider 是所属供应商 id,max_context_size 是以 token 计的上下文窗口,capabilities / support_efforts / default_effort 描述能力标志与 Thinking 模式的 effort 支持。对于自定义 registry 模型,upgrade 可以包含 { model, migration_markdown, retirement_at? },用于引导用户切换到替代模型;migration_markdown 中的占位符已替换为模型 ID。
POST /api/v1/models/{model_id}:set_default
把全局 default_model 设为一个已存在的别名。model_id 是配置中的别名键原样——裸键如 POST /api/v1/models/turbo:set_default;当 id 含 / 时需做 URL 编码,如 POST /api/v1/models/my-provider%2Fkimi-for-coding:set_default。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
model_id | path | string | 必填。 配置中的模型别名键原样;含 / 时需 URL 编码 |
成功时 data 为 { default_model, model }——当前生效的别名及其目录项(形态与 GET /api/v1/models 的单项相同)。
40001:路径中的动作后缀非法或不支持40413:不存在该 id 的模型别名
GET /api/v1/providers
列出每个已配置供应商及其凭据与模型发现状态,不泄露任何密钥。这也是其他供应商端点引用的供应商条目形态。
成功时 data.items 为如下结构的数组:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 供应商 id |
type | string | 通信协议:kimi / openai / openai_responses / anthropic / google-genai / vertexai |
base_url | string | API 基础 URL,如已设置 |
default_model | string | 该供应商的默认模型别名,如已设置 |
has_api_key | boolean | 是否已存储凭据 |
status | string | 存在 API 密钥或缓存的 OAuth token 时为 connected,否则为 unconfigured(error 在 schema 中保留) |
models | array | 该供应商的模型别名 id |
POST /api/v1/providers
一次保存创建供应商及其模型别名;响应为 HTTP 201 加标准信封。当全局 default_model 完全未配置时(全新安装),会以新供应商的 default_model(或第一个模型)播种;已有默认值绝不被修改。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | body | string | 必填。 供应商 id——字母、数字、-、_ 与空格;必须以字母或数字开头 |
type | body | string | 必填。 通信协议:kimi / openai / openai_responses / anthropic / google-genai / vertexai |
api_key | body | string | API 密钥,存储于 config.toml |
base_url | body | string | API 基础 URL;不得包含环境变量占位符(${...}) |
default_model | body | string | 该供应商的默认模型;必须是 models[].model 之一 |
models | body | array | 必填。 至少一条,不允许重复的 model 值;条目结构见下文 |
每个 models[] 条目声明一个别名,其 id 为 id/model:
| 字段 | 类型 | 说明 |
|---|---|---|
model | string | 必填。 上游模型名 |
max_context_size | integer | 必填。 以 token 计的上下文窗口,≥ 1 |
display_name | string | 显示名 |
capabilities | array | 能力标志,如 thinking 或 image_in |
max_output_size | integer | 最大输出 token 数,≥ 1 |
support_efforts | array | 支持的 Thinking 模式 effort 档位 |
adaptive_thinking | boolean | 自适应 thinking 开关 |
成功时 data 为创建好的供应商条目(形态与 GET /api/v1/providers 的单项相同)。
40921:已存在该id的供应商
GET /api/v1/providers/{provider_id}
读取单个供应商。与列表路由不同,设置了密钥时响应会暴露存储的 api_key,以便本地编辑表单预填——暴露端口时请牢记这一点。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider_id | path | string | 必填。 供应商 id |
成功时 data 为供应商条目,存有密钥时附带 api_key。
40412:供应商不存在
PUT /api/v1/providers/{provider_id}
一次保存整体替换供应商:type、base_url 与模型列表被重写,该供应商的别名按 models 重建——不再列出的别名从 config.toml 中消失,其他供应商的别名不受影响。api_key 是三态的:省略表示保留已存密钥,"" 表示清除,其他值表示替换。除 new_id 重命名迁移外,全局默认指针绝不被修改。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider_id | path | string | 必填。 当前供应商 id |
new_id | body | string | 重命名供应商;providers 键、模型别名、default_provider、指向旧别名的 default_model 以及 subagent 次级模型池都会随之迁移。id 规则与 POST /api/v1/providers 相同 |
type | body | string | 必填。 通信协议:kimi / openai / openai_responses / anthropic / google-genai / vertexai |
api_key | body | string | 三态,见上文 |
base_url | body | string | API 基础 URL;不得包含环境变量占位符(${...}) |
default_model | body | string | 该供应商的默认模型;必须是 models[].model 之一 |
models | body | array | 必填。 至少一条,不允许重复的 model 值;条目结构与 POST /api/v1/providers 相同 |
成功时 data 为 { provider },即保存后的供应商条目。
40001:重命名后的别名 id 会与其他供应商的别名冲突40003:供应商由 OAuth 托管——请改用POST /api/v1/oauth/logout登出40412:供应商不存在40921:new_id已被占用
DELETE /api/v1/providers/{provider_id}
删除供应商及其全部模型别名;subagent 次级模型池会级联清理。全局 default_provider / default_model 指针保持不动,即使它们指向被删的供应商——那是用户的设置,不由本端点代为回收。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider_id | path | string | 必填。 供应商 id |
成功时服务应答 204 且无响应体——状态行本身即表示删除成功(见 响应信封)。
40003:供应商由 OAuth 托管——请改用POST /api/v1/oauth/logout登出40412:供应商不存在
POST /api/v1/providers/{provider_id}:refresh
从上游来源重新发现单个供应商的模型元数据,并重写该供应商的别名。模型来源为静态的供应商不经任何网络调用直接报告 unchanged。至少一个供应商的别名或托管模型元数据发生变化时,服务会广播全局 event.model_catalog.changed 事件。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
provider_id | path | string | 必填。 供应商 id |
成功时 data 为刷新报告:changed 是 { provider_id, provider_name, added, removed }(新增 / 移除的别名数)的数组,unchanged 是无差异的供应商 id 数组,failed 是 { provider, reason } 的数组。当刷新发现 registry 移除了当前默认模型、且该模型此前声明过 upgrade 替代模型时,data 还带可选的 retired_default:{ from, to, from_display_name }——默认模型已被重定向为 to,仍绑定 from 的已打开会话也已切换到 to,from_display_name 是被移除模型的显示名,供提示使用。同一字段也会出现在 event.model_catalog.changed 事件中。
40001:路径中的动作后缀非法或不支持40412:供应商不存在
POST /api/v1/providers:refresh
刷新每个供应商的模型元数据。请求体可选且被忽略。
成功时 data 为与 POST /api/v1/providers/{provider_id}:refresh 相同的刷新报告(changed / unchanged / failed)。
POST /api/v1/providers:refresh_oauth
与 POST /api/v1/providers:refresh 相同的刷新,仅限 OAuth 凭据的供应商。请求体可选且被忽略。
成功时 data 为刷新报告(changed / unchanged / failed)。
POST /api/v1/providers:import_catalog
把一个 models.dev 目录条目导入为已配置供应商;响应为 HTTP 201 加标准信封。通信协议与端点来自目录解析,目录中的每个模型都写为一个别名。导入已存在的 id 等同于刷新——供应商条目及其别名按目录重写,省略 api_key 表示保留已存密钥。全局默认指针绝不被修改,仅在完全未配置默认模型时,以第一个导入的模型播种 default_model。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
catalog_id | body | string | 必填。 来自 GET /api/v1/catalog/providers 的目录条目 id |
id | body | string | 覆盖目录 id 作为本地供应商 id。id 规则与 POST /api/v1/providers 相同 |
api_key | body | string | 导入供应商的 API 密钥 |
base_url | body | string | 覆盖目录解析出的端点;条目的 needs_base_url 为 true 时必填 |
成功时 data 为 { provider, models_imported }——供应商条目与写入的别名数量。
40001:缺少catalog_id或其他请求体校验失败40003:目标供应商已存在且由 OAuth 托管40004:条目无法导入(被拒绝、要求base_url、没有可导入的模型,或其 id 不能用作供应商 id)40417:不存在该catalog_id的目录条目50004:models.dev 目录不可用
POST /api/v1/providers:import_registry
把一个 models.dev 形态的私有注册表——一个 api.json URL 加可选的 Bearer key——导入为已配置供应商;响应为 HTTP 201 加标准信封。每个列出的供应商都带 source 记录写入,以便定时刷新重新发现。重复导入同一 URL 会移除上游已消失的供应商——URL 是注册表的稳定身份,因此轮换 key 是安全的。全局默认指针遵循与 :import_catalog 相同的规则。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
url | body | string | 必填。 注册表 api.json 的 URL |
api_key | body | string | 注册表的 Bearer key;省略时复用上一次导入同一 URL 所用的 key |
成功时 data 为 { providers, models_imported }——供应商条目数组与写入的别名总数。
40001:缺少url或其他请求体校验失败40003:某个列出的供应商已存在且由 OAuth 托管40005:注册表无法获取或解析,或未列出可导入的供应商
GET /api/v1/catalog/providers
浏览 models.dev 目录,由服务端代理,带 10 分钟内存缓存与内置快照兜底。条目保持上游目录顺序。服务无法导入的条目携带 rejected: true 与机器可读的 reject_reason;needs_base_url: true 的条目在导入时要求提供 base URL。
成功时 data.items 为 { id, name, wire_type, base_url, guessed, needs_base_url, rejected, reject_reason, env_key, models } 数组:wire_type 是解析出的协议(可空,枚举与供应商 type 相同),base_url 是解析出的端点(可空;needs_base_url 或被拒绝的条目为 null),guessed 标记启发式解析,env_key 是上游约定的 API 密钥环境变量(可空),models 是 { id, name?, max_context_size, capabilities?, reasoning } 的数组。
50004:目录不可用(在线拉取与内置快照均失败)
GET /api/v1/catalog/providers/{catalog_id}
按 catalog id 读取单个 models.dev 目录条目——条目形态与 GET /api/v1/catalog/providers 相同。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
catalog_id | path | string | 必填。 目录条目 id |
成功时 data 为该目录条目(形态与 GET /api/v1/catalog/providers 的单项相同)。
40417:不存在该catalog_id的目录条目50004:目录不可用
会话
这些端点用于创建、列出和查看会话,执行会话级动作(fork、compact、undo 等),并读取会话级汇总。其中大多数返回的会话采用 session 对象 中统一说明的线上格式;非 CRUD 操作使用上文介绍的 :{action} 约定。
| 方法与路径 | 说明 |
|---|---|
POST /api/v1/sessions | 创建会话(需 workspace_id 或 metadata.cwd) |
GET /api/v1/sessions | 列出会话,游标分页,支持 busy / archived_only 等过滤 |
GET /api/v1/sessions/{session_id} | 读取单个会话 |
GET /api/v1/sessions/{session_id}/profile | 读取会话档案 |
POST /api/v1/sessions/{session_id}/profile | 更新标题、元数据、Agent 配置 |
POST /api/v1/sessions/{session_id}/title/generate | 通过托管的 chat_title 工具生成标题 |
POST /api/v1/sessions/{session_id}:{action} | 会话动作:fork / compact / undo / abort / btw / archive / restore |
GET /api/v1/sessions/{session_id}/children | 列出子会话 |
POST /api/v1/sessions/{session_id}/children | 创建子会话(fork 并打标) |
GET /api/v1/sessions/{session_id}/goal | 当前目标快照(无则 null) |
PATCH /api/v1/sessions/{session_id}/goal | 就地修改当前目标的 objective |
GET /api/v1/sessions/{session_id}/warnings | 会话级告警 |
GET /api/v1/sessions/{session_id}/environment | 读取 main agent 的环境绑定 |
GET /api/v1/sessions/{session_id}/environments | 列出会话工作区已注册的环境 |
POST /api/v1/sessions/{session_id}/export | 导出会话与诊断信息(zip 流,不走信封) |
GET /api/v1/sessions/{session_id}/media/{file_id} | 按文件 id 下载提示词媒体(二进制) |
GET /api/v1/sessions/{session_id}/file-history/changes | 列出一轮改动过的文件 |
GET /api/v1/sessions/{session_id}/file-history/content | 读取文件在一轮开始或结束时的内容 |
POST /api/v1/sessions/{session_id}/rating | 询问是否显示满意度问卷,并上报问卷的显示和回答 |
session 对象
每个返回会话的端点都使用这种线上格式。实时状态字段(busy、main_turn_active、pending_interaction、last_turn_reason)由会话的活动聚合解析得出:未加载到本服务进程中的会话(冷会话)始终上报为不忙碌且无待处理交互。少数字段在当前投影中是占位值——已逐字段注明。
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 会话 id(session_...) |
workspace_id | string | 所属工作区 id |
title | string | 会话标题;无标题时为 "" |
created_at / updated_at | string | 创建时间与最后更新时间,ISO 8601 |
archived | boolean | 会话是否已归档(归档后从默认会话列表中隐藏) |
archived_at | string | 归档时间,ISO 8601;仅在已归档时存在 |
busy | boolean | 是否有任一 Agent 存在进行中的轮次或后台任务 |
main_turn_active | boolean | main agent 是否有进行中的轮次 |
pending_interaction | string | none / approval / question——有未答复的交互在等待 |
last_turn_reason | string | main agent 最近一次轮次的结果:completed / cancelled / failed |
last_prompt | string | 最近一条用户提示词文本(如有) |
metadata | object | 自定义元数据;始终携带 cwd(会话的工作目录) |
agent_config | object | 投影为 { model };会话已加载到当前服务端进程、且 main agent 有模型时,model 为 main agent 当前的模型(例如创建请求设置了模型时的创建响应),否则为 "" |
usage | object | token 汇总 { input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, context_tokens, context_limit?, total_cost_usd?, turn_count? };当前始终为零。实时的上下文大小随每个 Agent 的 usage 帧通过 WebSocket 下发(见 事件) |
permission_rules | array | 会话权限规则;当前始终为 [] |
message_count | integer | 消息数;当前始终为 0 |
POST /api/v1/sessions
创建会话并返回。目标目录来自 workspace_id(已注册的工作区)或 metadata.cwd(首次使用时注册该工作区);两者同时提供时必须一致。创建时会广播全局 event.session.created 事件。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | body | string | 未提供 metadata.cwd 时必填。已注册的工作区 id;会话创建于该工作区的根目录 |
metadata | body | object | 自定义元数据。metadata.cwd 为工作目录,未提供 workspace_id 时必填;两者同时提供时必须等于工作区根目录。其他键保存为会话的自定义元数据;保留键 goal、parent_session_id、child_session_kind 会被丢弃 |
title | body | string | 初始标题(至少 1 个字符);否则会话无标题 |
agent_config | body | object | main agent 的部分配置,字段与 POST /api/v1/sessions/{session_id}/profile 相同,另加 profile(Agent 档案,默认 agent,创建后不可更改),在返回会话之前应用。无法应用时不创建会话,直接返回错误。tower_mode: true 会被拒绝(返回 40001):进入 Tower 模式会改动仓库,创建失败时无法撤销,请在会话建好后通过 POST /api/v1/sessions/{session_id}/profile 开启 |
成功时,data 为新会话的 session 对象。
40001:workspace_id与metadata.cwd都未提供,metadata.cwd与工作区根目录不一致,或agent_config设置了tower_mode: true(details会列出该字段);agent_config.model未配置、agent_config.profile未知,或模型不支持agent_config.thinking时也返回此码40113:没有可用模型,而agent_config设置了profile或thinking40409:工作目录不存在或不是目录40410:没有以该workspace_id注册的工作区40913–40918、40920:agent_config因目标相关错误无法应用
GET /api/v1/sessions
跨工作区列出会话,按 updated_at 最新在前。游标分页遵循 分页,但有一个特例:不提供 page_size(且不提供 archived_only)时,响应是单个不分页的窗口,其 has_more 恒为 false,因此要真正翻页请传入 page_size。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
before_id | query | string | 只保留早于该 id 的会话;与 after_id 互斥 |
after_id | query | string | 只保留晚于该 id 的会话;与 before_id 互斥 |
page_size | query | integer | 1–100。分页生效时默认为 20;不分页的默认行为见上文说明 |
busy | query | boolean | 只保留忙碌(或只保留空闲)的会话 |
include_archive | query | boolean | 在活跃会话之外同时包含已归档会话。默认 false |
archived_only | query | boolean | 只保留已归档会话;与 include_archive 互斥;即使不提供 page_size 也会启用游标分页 |
exclude_empty | query | boolean | 去掉没有任何用户提示词的会话 |
workspace_id | query | string | 限定到单个工作区(别名会被解析) |
成功时,data 为 { items, has_more },其中每个元素为 session 对象。
40001:校验失败——例如before_id与after_id同用,或archived_only与include_archive同用40410:未知的workspace_id
GET /api/v1/sessions/{session_id}
从索引中读取单个会话。会话已加载到本进程时会包含实时状态字段;冷会话上报为不忙碌,并携带其最后持久化的轮次结果。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时,data 为 session 对象。
40401:会话不存在,或其工作区已无法解析
GET /api/v1/sessions/{session_id}/profile
读取会话档案——与 GET /api/v1/sessions/{session_id} 相同的线上载荷。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时,data 为 session 对象。
40401:会话不存在
POST /api/v1/sessions/{session_id}/profile
更新会话档案:标题、自定义元数据以及 main agent 的配置。在这里设置的标题会成为自定义标题,优先级高于生成的标题;设置标题会广播全局 session.meta.updated 事件。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
title | body | string | 新标题(至少 1 个字符);会成为自定义标题 |
metadata | body | object | 合并进会话自定义元数据的键 |
agent_config | body | object | main agent 的部分配置;字段如下,均为可选 |
每个 agent_config 字段都会立即应用到 main agent:
| 字段 | 类型 | 说明 |
|---|---|---|
model | string | 模型别名 id;空字符串会被忽略 |
thinking | string | Thinking 强度等级 |
permission_mode | string | manual / yolo / auto |
plan_mode | boolean | 进入或退出 Plan 模式 |
swarm_mode | boolean | 进入或退出 swarm 模式 |
goal_objective | string | 以该文本为内容创建一个目标 |
goal_control | string | pause / resume / cancel 当前目标 |
成功时,data 为更新后的 session 对象。
40401:会话不存在
POST /api/v1/sessions/{session_id}/title/generate
通过托管供应商的 chat_title 工具根据会话的提示词生成标题并应用,同时广播 session.meta.updated。生成需要托管 OAuth 登录;未提供 force 时,已有自定义标题或已生成标题的会话会上报为不可用,而不会被覆盖。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
force | body | boolean | 即使已有自定义或生成的标题也重新生成。默认 false |
source | body | string | 标题输入:user_prompts(默认)/ first_turn / digest |
成功时,data 为 { title }——当前应用到会话的标题。
40401:会话不存在40923:生成不可用——开关未开启、没有托管 OAuth 登录或尚无任何提示词内容、已有标题但未提供force,或后端请求失败
POST /api/v1/sessions/{session_id}:{action}
会话动作通过同一条路由分发:路径尾部解析为 {session_id}:{action},请求体按该动作的 schema 校验,动作缺失或未知时返回 40001(unsupported action: ...)。每个动作都会先解析会话,因此会话未知时都可能返回 40401。支持的动作在下面逐一说明。
POST /api/v1/sessions/{session_id}:fork
将会话——其对话、Agent 状态与文件——复制到同一工作区中的新会话,并广播 event.session.created。源会话会继续运行;如果存在进行中的轮次,fork 会保留该轮次之前最近一个已完成的边界,并将当前轮次的用户 prompt 保存为一个仅含 prompt 的 cancelled 轮次,不包含 Assistant 输出、工具活动、排队输入或后续事件。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
title | body | string | fork 的标题(至少 1 个字符)。默认 Fork: <source title> |
metadata | body | object | fork 的自定义元数据 |
turn_index | body | integer | 要保留到的持久化 engine turnId(包含该轮次),允许编号空洞。必须是非负安全整数,且该轮次已经完成 |
成功时,data 为新会话的 session 对象。
40001:turn_index无效、不存在或选中了进行中的轮次40901:另一项会话历史操作正在进行
POST /api/v1/sessions/{session_id}:compact
对 main agent 的上下文发起一次手动全量压缩。调用立即返回;进度与完成通过 compaction.* WebSocket 事件投递。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
instruction | body | string | 给压缩摘要的额外指引;空值会被忽略 |
成功时,data 为空对象。
40910:有轮次或其他上下文变更正在进行,或历史中没有可压缩的内容
POST /api/v1/sessions/{session_id}:undo
撤销 agent 对话中的某一轮及其之后的所有轮次(包括其间的 system 轮与由定时任务等触发的轮),并同步修正派生的会话状态(包括会话的 last_prompt)。不回滚文件。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
turn_id | body | string | 要撤销的轮。必须是 agent 轮,且开场 user_message 来自用户、用户以斜杠调用的 skill 或 plugin command |
agent_id | body | string | 要撤销其对话的 agent。默认 main |
成功时,data 为 { removed_turn_ids }:按 ordinal 升序列出被删除的轮,第一个即 turn_id。订阅者会收到 turn_ids 相同的 turns.removed 帧;响应与该帧到达的先后顺序不固定。
40421:这一轮不存在40901:agent 正在工作(有运行中的轮、排队的输入或正在压缩上下文)——等其结束后重试40911:无法撤销这一轮:开场不是用户输入,或要删除的范围跨过了上下文压缩
POST /api/v1/sessions/{session_id}:abort
取消 main agent 正在运行的轮次——等同于用户在 TUI 中中止轮次的程序化版本。
成功时,data 为 { aborted: true }。
POST /api/v1/sessions/{session_id}:btw
开启一个 "by the way" 旁路对话:把 main agent fork 成一个仅可使用只读工具(Read、Grep、Glob)的子 Agent,让快速的临时问题在隔离环境中运行,不触碰工作上下文。需要可用的模型配置。
成功时,data 为 { agent_id }——新子 Agent 的 id。
POST /api/v1/sessions/{session_id}:archive
将会话标记为已归档:它从默认会话列表中消失(使用 include_archive 或 archived_only 时仍会列出),并且服务端广播全局 event.session.archived 事件。
成功时,data 为 { archived: true }。
POST /api/v1/sessions/{session_id}:restore
取消会话的归档状态并恢复它。会话原本已归档时,服务端广播全局 event.session.restored 事件。
成功时,data 为 archived: false 的 session 对象。
POST /api/v1/sessions/{session_id}:reload
以磁盘上的最新配置重新加载会话:重读 config.toml 与插件,重载工作区的 Skill 与 subagent 目录,然后关闭并从磁盘恢复会话。同时会通过系统提醒(system-reminder)把 AGENTS.md、Skill、subagent 及模型的外部变更告知 main agent。
成功时,data 为 session 对象。
40901:会话有正在运行的轮次,无法重新加载
POST /api/v1/sessions/{session_id}:takeover
移除其他 Kimi Code 进程在该会话上持有的锁,之后可以重试返回 40931 的请求。只应在该进程已退出、锁残留时使用:如果它仍在运行,两个进程会同时写入该会话直到它空闲,会话历史可能交错。
成功时,data 为 { taken_over: true }。
40401:会话不存在
GET /api/v1/sessions/{session_id}/children
列出会话的子会话——即通过 POST /api/v1/sessions/{session_id}/children 创建的会话。游标分页遵循 分页。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
before_id | query | string | 只保留早于该 id 的子会话;与 after_id 互斥 |
after_id | query | string | 只保留晚于该 id 的子会话;与 before_id 互斥 |
page_size | query | integer | 1–100。默认 100 |
busy | query | boolean | 只保留忙碌(或只保留空闲)的子会话 |
成功时,data 为 { items, has_more },其中每个元素为 session 对象。
40401:会话不存在
POST /api/v1/sessions/{session_id}/children
创建子会话:fork 当前会话并记录为其子会话,因此会出现在 GET /api/v1/sessions/{session_id}/children 下。运行中的源会话采用与 :fork 相同的已完成轮次边界,以及仅含 prompt 的 cancelled 当前轮次;创建子会话不接受历史 turn_index 参数。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
title | body | string | 子会话的标题(至少 1 个字符)。默认 Child: <source title> |
metadata | body | object | 子会话的自定义元数据 |
成功时,data 为新会话的 session 对象,并且服务端广播 event.session.created。
40901:另一项会话历史操作正在进行
GET /api/v1/sessions/{session_id}/goal
读取会话当前的目标快照;没有活跃目标时为 null。注意,与本 API 的大多数载荷不同,该载荷使用 camelCase 键。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时,data 为 null 或 { goalId, objective, completionCriterion?, status, turnsUsed, tokensUsed, wallClockMs, budget, terminalReason? },其中 status 为 active / paused / blocked / complete,budget 报告 token、轮次与 wall-clock 三项预算,以及各自的剩余量与每项预算的 reached 标志(未设置对应预算时各项为 null)。
40401:会话不存在
PATCH /api/v1/sessions/{session_id}/goal
替换当前目标的 objective,goalId、状态、进度和预算均保持不变。适用于 active、paused、blocked 状态的目标。正在运行的 turn 不会被打断,agent 在下一个 turn 收到新的 objective。已连接的客户端通过 goal.updated 事件获知变化。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
objective | body | string | 必填。 新的 objective,首尾空白会被去除 |
成功时 data 是更新后的目标快照,形状与 GET /api/v1/sessions/{session_id}/goal 相同(camelCase)。
40401: 会话不存在40914: 当前没有目标40915: 目标已完成40917: objective 为空40918: objective 超过 4000 字符
GET /api/v1/sessions/{session_id}/warnings
读取会话级告警。目前的产生者只有 AGENTS.md 过大检查(agents-md-oversized),因此大多数会话的列表为空。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时,data 为 { warnings },每个条目为 { code, message, severity },其中 severity 为 info / warning / error 之一。
40401:会话不存在
GET /api/v1/sessions/{session_id}/environment
读取 main agent 的环境绑定——即该会话的 Agent 循环运行在哪个环境上。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时,data 为 { workspace_id, environment_id, cwd? };cwd 是被绑定环境上的工作目录,绑定带有该值时返回。
40401:会话不存在
GET /api/v1/sessions/{session_id}/environments
列出会话可用的环境。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时,data 为 { environments }。environments 每项为 { environment_id, type, status, connect_error? },其中 type 取 local / ssh / docker / command 之一,status 取 pending / connecting / ready / disconnected / disposed 之一;pending 表示没有可用连接且未观察到失败(尚未连接过),connect_error 记录 disconnected 条目的失败原因。
40401:会话不存在
POST /api/v1/sessions/{session_id}/export
将会话连同诊断日志一起导出为 zip 附件(kimi-session-<id>.zip)。响应是二进制流,不是 JSON 信封——能力与失败语义见 二进制与流式端点。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
web_log | body | string | 要包含在归档中的客户端日志文本,最多 256 KB UTF-8 |
desktop | body | boolean | 同时包含桌面宿主的日志。默认 false |
GET /api/v1/sessions/{session_id}/media/{file_id}
按文件 id 下载提示词媒体文件(会话提示词引用的图片或其他附件);尚未提交到会话的 id 会回退到暂存的上传中查找。响应为二进制并支持 Range(范围请求返回 206)——共享约定见 二进制与流式端点;与那里走信封的端点不同,会话或文件不存在时会返回真正的 404 状态码并携带信封体。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
file_id | path | string | 必填。 媒体文件 id |
GET /api/v1/sessions/{session_id}/file-history/changes
从轮次级文件历史中列出 main agent 某一轮改动过的文件:把这一轮开始时记录的内容,与结束时记录的内容比较;轮次仍在进行时,与磁盘上的当前文件比较。没有变化的文件不列出。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
turn_number | query | integer | 必填。 轮次的 turn_number(见 对话协议) |
成功时,data 为 { changes, recorded }。每项变更为 { path, status, additions, deletions, binary?, oversize? }:status 为 added / modified / deleted,additions / deletions 是变更的行数。binary 表示文件不是文本或内容已不再保存,oversize 表示文件过大没有记录,两者的行数都为 0。轮次的文件历史不完整时——从未记录,或部分已记录的内容后来被清理——recorded 为 false,此时 changes 可能为空或不全。
40001:turn_number缺失或无效40401:会话不存在
GET /api/v1/sessions/{session_id}/file-history/content
读取 main agent 的文件历史在某一轮开始或结束时记录的文件内容,例如用来展示这一轮的 diff。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
turn_number | query | integer | 必填。 轮次的 turn_number |
path | query | string | 必填。 文件路径,与 file-history/changes 列出的一致 |
phase | query | string | start(默认)取这一轮之前的内容,end 取这一轮之后的内容 |
成功时,data 为 { content }。content 为 { version, content?, binary? },version 是文件在历史中的版本号:文本放在 content 中,文件不是文本时 binary 为 true,两者都没有表示文件在这个时间点不存在。phase=end 时,这一轮没有改动的文件按开始时的内容返回。这一轮没有该阶段的记录,或文件没有被记录、过大、已保存的内容已不存在时,content 为 null。
40001:turn_number或path缺失或无效40401:会话不存在
POST /api/v1/sessions/{session_id}/rating
驱动客户端在一轮结束后可能显示的满意度问卷:一轮完成后,客户端先询问要不要显示,再上报问卷何时显示、用户如何回答。是否给出问卷取决于 Kimi Code 服务设定的抽样规则和本地冷却时间,因此多数询问不会给出问卷。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
op | body | string | 必填。 evaluate / shown / respond / abandon |
turn_id | body | string | evaluate 时必填:刚完成的轮次的 turn_id |
appearance_id | body | string | shown / respond / abandon 时必填:evaluate 返回的 id |
response | body | string | respond 时必填:bad / fine / good / dismissed |
evaluate 时,data 为 { appearance }:客户端此时应显示问卷时为 { id, survey },survey 为 session 或 long_context;否则为 null——包括该轮不是 main agent 最近完成的轮次、开启了 disable_feedback_survey,或关闭了遥测。问卷显示后上报 shown,用户作答后上报 respond(用户关掉问卷时为 dismissed),问卷没有得到回答就消失时上报 abandon,例如用户转去了别处;这三种操作返回 data: null。
40001:校验失败
消息与轮次
messages 端点分页返回 main agent 的扁平化消息历史,turns 端点则按轮次与条目分页返回某个 Agent 的对话——与 WebSocket 对话协议 实时推送的是同一套模型。更早的历史用这些端点读取,turns 帧之后的内容都走 WebSocket 订阅。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/sessions/{session_id}/messages | 消息分页(before_id / after_id / role) |
GET /api/v1/sessions/{session_id}/messages/{message_id} | 读取单条消息 |
GET /api/v1/sessions/{session_id}/agents/{agent_id}/turns | 某个 Agent 的轮次分页(before_ordinal / page_size) |
GET /api/v1/sessions/{session_id}/messages
分页返回 main agent 的消息历史——扁平化的上下文转录——最新在前。游标分页遵循 分页;读取历史会在会话为冷态时将其恢复。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
before_id | query | string | 只保留早于该消息 id 的消息;与 after_id 互斥 |
after_id | query | string | 只保留晚于该消息 id 的消息;与 before_id 互斥 |
page_size | query | integer | 1–100。默认 50 |
role | query | string | 只保留单一角色:user / assistant / tool / system。过滤在分页切片之后应用,因此过滤后的一页可能少于 page_size 条而 has_more 仍为 true——持续翻页直到 has_more 为 false |
成功时,data 为 { items, has_more },其中每个元素是消息对象 { id, session_id, role, content, created_at, prompt_id?, parent_message_id?, metadata? };content 是按 提示词 中说明的线上格式组成的内容块数组(text、tool_use、tool_result、image、video、file、thinking)。
40001:校验失败——例如before_id与after_id同用40401:会话不存在
GET /api/v1/sessions/{session_id}/messages/{message_id}
按 id 从同一历史中读取单条消息。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
message_id | path | string | 必填。 消息 id |
成功时,data 为上文 GET /api/v1/sessions/{session_id}/messages 中说明的元素形态的消息对象。
40401:会话不存在40403:该会话中不存在此 id 的消息
GET /api/v1/sessions/{session_id}/agents/{agent_id}/turns
返回某个 Agent 的一页轮次,最旧在前,轮次与条目的形状见 对话协议。会话或已结束的 subagent 不在内存时,读取会将其载入。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
agent_id | path | string | 必填。 Agent id;不含路径分隔符 |
before_ordinal | query | integer | 只保留 ordinal 小于该值的轮次;不要求存在该 ordinal 的轮次,例如撤销之后。默认返回最新的一页 |
page_size | query | integer | 1–200 个轮次。默认 50 |
成功时,data 为 { turns, has_more };has_more 表示还有更早的轮次,把这一页第一轮的 ordinal 作为 before_ordinal 传入即可读取。一页不超过 1 MiB:放不下 page_size 个轮次时,其中最旧的轮次不放入、has_more 为 true,最新的一轮总会放入。最新一页包含正在运行的轮次(如有)及其到此刻为止的内容。任务、Agent 的运行状态与设置、上下文用量、目标、待办和待处理交互都不属于轮次,分别通过 WebSocket 的 task、agent、usage、goal、todo、interaction 帧到达(见 事件)。
40001:校验失败40401:会话或 Agent 不存在
提示词
提示词是一次用户输入的单位:提交一条提示词会把它排入会话的 main agent(或指定 Agent)的队列,排队中的提示词可以插入进行中的轮次,运行中的提示词可以中止。轮次进度本身通过 WebSocket 事件 流式推送,不经过这些端点。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/sessions/{session_id}/prompts | 进行中与排队中的提示词 |
POST /api/v1/sessions/{session_id}/prompts | 提交提示词(内容块数组,可带模型 / 权限模式覆盖) |
POST /api/v1/sessions/{session_id}/steer | 直接把消息内容插入进行中的轮次 |
POST /api/v1/sessions/{session_id}/prompts:steer | 把排队的提示词插入进行中的轮次 |
POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:abort | 中止运行中的提示词 |
POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:steer | 插入单条排队的提示词 |
GET /api/v1/sessions/{session_id}/prompts
读取 main agent 的提示词队列快照。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时,data 为 { active, queued }:active 是运行中的提示词(空闲时为 null),queued 按顺序列出等待中的提示词。提示词为 { prompt_id, user_message_id, status, content, created_at },其中 status 为 running / queued / blocked / failed 之一,content 采用 POST /api/v1/sessions/{session_id}/prompts 接受的内容块格式。
40401:会话不存在
POST /api/v1/sessions/{session_id}/prompts
向会话提交一条用户提示词。先校验媒体引用,然后按 model、thinking、permission_mode、swarm_mode 和 disabled_tools 应用可选覆盖项,随后提示词入队;响应在提示词被接受后立即返回,不等待轮次执行。提供 skills 时,提示词以打包的 Skill 激活方式运行,而不是普通用户提示词。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
content | body | array | 必填。 非空的内容块数组;变体见下 |
agent_id | body | string | 目标 Agent。默认为 main agent |
prompt_id | body | string | 客户端选定的提示词 id,使提交幂等,带 skills 时同样可用:用同一个 id 再次发送同一个请求,会返回第一次提交的结果(第一次还在处理时等它完成),不会重复提交;同一个 id 用于不同的请求返回 40927 |
skills | body | array | 打包的 Skill 激活,至少 1 个 { name, path?, args? } 条目;每个 Skill 必须存在且可由用户激活。path 用于选择会话目录中的同名变体 |
model | body | string | 要切换到的模型别名 |
thinking | body | string | Thinking 强度等级 |
permission_mode | body | string | manual / yolo / auto |
swarm_mode | body | boolean | 进入或退出 swarm 模式 |
disabled_tools | body | array | 要为会话禁用的工具名 |
schema 还接受 metadata(随提示词保存)及 plan_mode、goal_objective 和 goal_control(提交路由当前不应用这些模式/目标字段)。每个 content 内容块是按 type 区分的对象:
| 内容块 | 字段 | 说明 |
|---|---|---|
text | text | 纯文本 |
image / video | source | 媒体输入;source 为 { kind: "url", url, id? }、{ kind: "base64", media_type, data }、{ kind: "file", file_id }(来自 POST /api/v1/files 的上传)或 { kind: "session_media", file_id }(已提交到本会话的媒体)之一 |
file | file_id、name、media_type、size | 通过 POST /api/v1/files 上传的文件附件 |
schema 还接受共享消息格式中的 tool_use、tool_result 和 thinking 内容块,但它们在用户提示词中没有意义。未知或 kind 不匹配的 file_id 引用会在提示词创建之前、任何覆盖项应用之前被拒绝。
成功时,data 为被接受的提示词 { prompt_id, user_message_id, status, content, created_at }。会话空闲时,响应会等到提示词开始执行轮次或未开始轮次就结束:hook 拒绝了该提示词时 status 为 blocked,提交在轮次开始前失败时为 failed,例如提示词 hook 出错或附件无法准备。
40001:校验失败——例如未知的model、不支持的thinking等级,或传入了profile(Agent 档案只能在创建会话时通过agent_config.profile指定)40110:尚未配置供应商——请先完成登录40111:解析出的供应商没有凭据(details.provider_id)40112:供应商的凭据被拒绝(details.provider_id)40113:模型无法解析(已知时带details.model_id/details.provider_id)40401:会话不存在40407:引用的file_id不存在(或与内容块的媒体 kind 不匹配)40415:某个skills条目指向未知的 Skill40912:Skill 存在但无法由用户激活40927:prompt_id已被另一个请求使用
POST /api/v1/sessions/{session_id}/steer
直接把消息内容插入进行中的轮次,只需一次请求,无需先提交再按 id steer。请求体字段与 POST /api/v1/sessions/{session_id}/prompts 相同,包括 content、agent_id、prompt_id、skills、profile、model、thinking、permission_mode 和 disabled_tools。媒体引用与打包 Skill 也复用提示词提交的校验和准备流程。
成功时,data 与 POST /api/v1/sessions/{session_id}/prompts 返回的被接受提示词结构相同。错误也与提示词提交一致,包括校验、媒体、档案、环境和幂等错误。
POST /api/v1/sessions/{session_id}/prompts:steer
把排队的提示词插入进行中的轮次,让运行中的轮次立即消费它们,而不是先运行结束。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
prompt_ids | body | array | 必填。 非空的排队提示词 id 数组 |
成功时,data 为 { steered: true, prompt_ids }。
40001:校验失败40401:会话不存在40402:所列提示词 id 不在队列中
POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:abort
中止运行中的提示词。本端点与下面的 :steer 通过同一条路由 POST /api/v1/sessions/{session_id}/prompts/{tail} 分发:尾部解析为 {prompt_id}:{action},动作缺失或未知时返回 40001(unsupported action: ...)。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
prompt_id | path | string | 必填。 提示词 id |
成功时,data 为 { aborted: true }。
40401:会话不存在40402:不存在该 id 的提示词40903:提示词已完成;data携带{ aborted: false }
POST /api/v1/sessions/{session_id}/prompts/{prompt_id}:steer
把单条排队的提示词插入进行中的轮次——是 POST /api/v1/sessions/{session_id}/prompts:steer 的单提示词形式。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
prompt_id | path | string | 必填。 排队中的提示词 id |
成功时,data 为 { steered: true, prompt_ids: [prompt_id] }。
40401:会话不存在40402:没有该 id 的排队提示词
审批与提问
审批与提问是会话的两类交互:审批是为工具调用请求许可,提问是请求带标签选项的结构化输入。待处理的交互通过 WebSocket 以 interaction 帧下发(见 事件),用这个端点答复。
| 方法与路径 | 说明 |
|---|---|
POST /api/v1/sessions/{session_id}/interactions/{interaction_id} | 答复待处理的审批或提问 |
POST /api/v1/sessions/{session_id}/interactions/{interaction_id}
答复一个待处理的交互,让等待中的工具调用继续。请求体的 kind 必须与交互的类型一致。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
interaction_id | path | string | 必填。 interaction 帧中的 interaction_id |
kind | body | string | 必填。 approval 或 question |
答复审批时使用这些字段:
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
decision | body | string | 必填。 approved / rejected / cancelled |
scope | body | string | 配合 approved 使用,session(唯一取值)还会让该审批规则在会话的剩余时间内被记住 |
feedback | body | string | 回传给 Agent 的自由文本反馈 |
selected_label | body | string | 当请求提供了带标签的选项时(例如计划审阅),所选选项的标签 |
答复提问时,answers 和 dismissed 二选一:
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
answers | body | object | 提问条目 id(来自帧中的 request.questions)到答案对象的映射;变体见下 |
dismissed | body | boolean | 为 true 时忽略该提问,不作回答 |
method | body | string | 答案的产生方式:enter / space / number_key / click |
每个答案是按 kind 区分的对象:
| kind 值 | 字段 | 说明 |
|---|---|---|
single | option_id | 选中的单个选项 |
multi | option_ids | 选中的多个选项(至少 1 个) |
other | text | 自由文本回答 |
multi_with_other | option_ids、other_text | 选项加自由文本 |
skipped | — | 跳过了该条目 |
成功时,data 为 { outcome, ended_at }:审批的 outcome 为 approved / rejected / cancelled,提问的为 answered / dismissed。订阅者同时会收到这个交互的最后一帧 interaction。
40001:校验失败(details列出每个字段),或kind与交互的类型不一致40401:会话不存在40404:会话中没有该 id 的交互40902:交互已经结束
技能、工具与 MCP
这组端点暴露会话或工作区可见的技能目录、当前生效 agent 的工具列表及其 MCP 服务。技能激活与 MCP 重启使用 :{action} 约定;激活即斜杠命令 /<skill> 的 REST 等价形式。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/sessions/{session_id}/skills | 会话级技能目录 |
GET /api/v1/workspaces/{workspace_id}/skills | 无会话的工作区技能目录 |
POST /api/v1/sessions/{session_id}/skills/{skill_name}:activate | 激活技能(开启一个轮次) |
GET /api/v1/tools | 列出当前生效 agent 的工具 |
GET /api/v1/mcp/servers | 列出 MCP 服务 |
POST /api/v1/mcp/servers/{mcp_server_id}:restart | 重启 MCP 服务 |
GET /api/v1/sessions/{session_id}/skills
列出单个会话可用的技能,按会话的优先级合并所有来源(内置、插件、extra、用户、项目)。会话处于冷态时,读取目录会恢复该会话。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
成功时 data 为 { skills },每项是一个技能描述符 { name, description, path, source, workspace_dir?, type?, disable_model_invocation? }:source 为 project / user / extra / builtin;type 标识技能类别(只有用户可激活的类型才能被激活);disable_model_invocation 会让技能对模型不可见。workspace_dir 是项目级技能的根目录,其他来源省略该字段。同名技能可以以不同 path 作为多个变体返回。
40401:会话不存在(或未激活)
GET /api/v1/workspaces/{workspace_id}/skills
列出该工作区中的会话将看到的技能目录,但不创建或恢复会话——即针对工作区根目录计算出的同一套内置、插件、extra、用户、项目来源合并结果。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | path | string | 必填。 已注册工作区 id |
成功时 data 为 { skills },技能描述符见上文 GET /api/v1/sessions/{session_id}/skills 的说明。
40410:工作区不存在
POST /api/v1/sessions/{session_id}/skills/{skill_name}:activate
在会话中激活技能——即斜杠命令 /<skill> 的 REST 等价形式——以技能内容加上 args 与附件在 main agent 上开启一个轮次。该端点经单一路由 POST /api/v1/sessions/{session_id}/skills/{tail} 分发:尾部按 {skill_name}:{action} 解析,activate 是唯一动作;只给名称或动作未知时返回 40001(unsupported action: ...)。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
skill_name | path | string | 必填。 要激活的技能名 |
path | body | string | 可选。会话技能目录中某个 SKILL.md 的精确路径,用于选择同名变体;必须与目录返回的条目匹配 |
args | body | string | 传给技能的自由文本参数,相当于斜杠命令后的文本 |
prompt_id | body | string | 客户端选定的激活消息 id,会出现在对话中对应 user_message 条目的 prompt_ids 里。和提交提示词一样,用同一个 id 再次发送同一个请求会返回第一次的结果,不会重复激活 |
attachments | body | array | 随激活携带的媒体块。image / video 块带 source 对象(kind 为 url / base64 / file / session_media,与提示词内容块同形);file 块带顶层 file_id、name、media_type、size |
成功时 data 为 { activated: true, skill_name }。
40001:校验失败或动作后缀不支持40401:会话不存在(或未激活)40407:引用的附件文件不存在40415:没有该名称的技能40912:技能存在,但其类型不允许用户激活40927:prompt_id已被另一个请求使用
GET /api/v1/tools
列出当前生效 agent 的工具——即 session_id 指定会话的 main agent;省略参数时取最近创建的会话。若该会话不在本服务进程中存活,列表为空。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | query | string | 要查看其 main agent 的会话。默认最近创建的会话 |
成功时 data 为 { tools },每项为 { name, description, input_schema, source, mcp_server_id?, active? }:source 为 builtin / skill / mcp;mcp_server_id 仅 MCP 工具携带(从 mcp__<server>__<tool> 名称解析);active 报告工具策略的判定结果。input_schema 目前恒为 null。
GET /api/v1/mcp/servers
列出当前生效 agent 配置的 MCP 服务(与 GET /api/v1/tools 相同,取最近创建的存活会话的 main agent)。没有存活会话时列表为空。
成功时 data 为 { servers },每项为 { id, name, transport, status, last_error?, tool_count }:transport 为 stdio / http / sse;status 为 connected / connecting / disconnected / error;服务处于 error 时 last_error 携带失败信息。
POST /api/v1/mcp/servers/{mcp_server_id}:restart
重新连接当前生效 agent 的某个 MCP 服务。该端点经 POST /api/v1/mcp/servers/{tail} 分发,restart 是唯一动作——只给服务 id 或动作未知时返回 40001。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
mcp_server_id | path | string | 必填。 MCP 服务 id(即其配置名称) |
成功时 data 为 { restarting: true }。
40001:缺少动作后缀或动作未知40408:没有该 id 的 MCP 服务(无存活会话时同样返回此错误)
能力与插件
能力是带有分层就绪状态的内置特性——由检测步骤加后台安装组成;当前版本注册了 kimi-cu(Kimi Computer Use)与 kimi-webbridge(Kimi Browser Extension)。插件是已安装的技能、MCP 服务、hook 与命令的打包集合。这组端点报告能力状态、驱动能力安装,并管理插件从市场列表到移除的整个生命周期。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/capabilities | 列出内置能力及其就绪状态 |
GET /api/v1/capabilities/{capability_id} | 读取单个能力的状态 |
POST /api/v1/capabilities/{capability_id}:install | 开始安装能力(后台进行,轮询 GET 查看进度) |
GET /api/v1/plugins | 列出已安装插件 |
GET /api/v1/plugins/{plugin_id} | 读取已安装插件及其声明的能力 |
POST /api/v1/plugins | 安装自定义插件或指定预期版本的市场条目 |
POST /api/v1/plugins/preview | 只读检查市场条目的能力,不安装插件 |
GET /api/v1/plugins/marketplace | 插件市场目录,合并实时安装状态 |
POST /api/v1/plugins/{plugin_id}:{action} | 插件动作:enable / disable / remove |
GET /api/v1/capabilities
列出所有已注册能力及其就绪状态。
成功时 data 为 { capabilities },每项是一个能力状态对象 { id, pluginId?, displayName, description, supported, state, version?, steps, install }。state 为 ready(所有必需检测步骤均为 ok)/ partial(部分步骤 ok)/ not_installed / unsupported(当前平台/架构不可用);steps 以 { id, state, detail?, optional? } 列出各检测步骤,其 state 为 ok / missing / failed 之一;install 为安装进度 { running, step?, percent?, error?, note? },其中 percent 取值 0 到 100。
GET /api/v1/capabilities/{capability_id}
读取单个能力的就绪状态——即 :install 动作的轮询对应端点。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
capability_id | path | string | 必填。 能力 id |
成功时 data 为上文 GET /api/v1/capabilities 说明的能力状态对象。
40418:没有该 id 的能力
POST /api/v1/capabilities/{capability_id}:install
在后台开始安装能力并立即返回当前状态(install.running 为 true);轮询 GET /api/v1/capabilities/{capability_id} 查看进度。该端点经 POST /api/v1/capabilities/{tail} 分发,install 是唯一动作——只给 id 或动作未知时返回 40001。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
capability_id | path | string | 必填。 能力 id |
成功时 data 为上文 GET /api/v1/capabilities 说明的能力状态对象。
40001:缺少动作后缀或动作未知40418:没有该 id 的能力40924:该能力的安装已在进行中40925:当前平台/架构不支持该能力
GET /api/v1/plugins
列出已安装插件。
成功时 data 为 { plugins },每项为 { id, displayName, description?, shortDescription?, longDescription?, version?, enabled, state, skillCount, mcpServerCount, enabledMcpServerCount, hookCount, commandCount, hasErrors, source, originalSource?, github? }:state 为 ok / error(加载失败也会置 hasErrors);source 为 local-path / zip-url / github;GitHub 来源的插件由 github 携带来源信息 { owner, repo, ref, installedSha? },其中 ref 为 { kind: branch|tag|sha, value }。每项还包含 origin(marketplace / custom / unknown)、可选的 catalogId,以及 ISO 时间戳 installedAt。
POST /api/v1/plugins
安装插件并返回其摘要。请求体有两种形式:
- 自定义安装:
{ "source": "<本地绝对路径、http(s) ZIP URL 或 GitHub URL>" }。GitHub URL 可通过/tree/<branch-or-sha>、/releases/tag/<tag>或/commit/<sha>锁定版本。 - 市场安装:
{ "marketplaceId": "<目录条目 id>", "expectedVersion": "<用户看到的版本>", "expectedSha256": "<用户看到的 sha256sum>" }。daemon 从同一目录快照解析source、sha256sum和预期插件 ID,在解压前校验压缩包,并校验 manifest ID。ZIP 条目声明了sha256sum时,必须传入与目录一致的expectedSha256;无版本的自定义条目可省略expectedVersion,本地目录和 GitHub 条目无需传expectedSha256。
成功时 data 为上文 GET /api/v1/plugins 说明的插件摘要。
40001:校验失败——例如source既不是 URL 也不是绝对路径,或插件加载失败40409:本地路径不存在40934:目录条目已相对用户看到的版本发生变化,请刷新目录后重试
GET /api/v1/plugins/marketplace
列出插件市场目录并合并实时安装状态。默认目录 URL 由当前 managed baseURL 派生为 ${baseURL}/plugins/marketplace,不再注入内置能力条目。目录中的 clients 将条目限制为 desktop、cli 或两者;缺省时两种宿主均可用。Web 和 Remote Control 使用所连接 server 的宿主身份。platforms 独立按 daemon 操作系统过滤:包含 daemon 所在平台或全部为 cloud 时保留条目;包含 cloud 但本机平台为其他平台的条目会被过滤。客户端与操作系统条件必须同时满足。cloud-only 条目不能在本机安装。旧 kimi-webbridge 条目不再返回,Computer Use 只返回当前平台对应的接线插件。
安装记录和托管文件仍共享在 daemon 的数据目录下。当前宿主不可用的条目也会从该宿主的已安装列表和运行能力中隐藏。daemon 将最近一次成功获取的可用性配置缓存到 plugins/availability.json;目录刷新成功后,客户端规则变化会隐藏或恢复已有安装,无需重新安装,也不会删除插件文件。
成功时 data 为 { entries },每项包含 id、tier、classification、displayName、description?、shortDescription?、longDescription?、cliDescription?、homepage?、keywords?、version?、source、iconUrl?、sha256sum?、filename?、locale?、defaultLocale?、platforms?、distribution?、billing?、installed?、updateAvailable? 和 capabilityId?。defaultLocale 声明顶层 description / cliDescription 的语言,locale 存放各语言的 displayName、shortDescription、longDescription 和 cliDescription 翻译。distribution.category 为 official 或 third_party;platforms 使用 darwin / win32 / linux / cloud。市场安装传 marketplaceId、可用时的 expectedVersion,以及带摘要 ZIP 的 expectedSha256,不直接传 source;自定义安装传 source。capability 只由 daemon 标注:kimi-browser-extension 映射到 kimi-webbridge capability,kimi-cu / kimi-cu-win 映射到 kimi-cu。
50001:市场不可达或返回了非法目录
GET /api/v1/plugins/{plugin_id}
读取已安装插件的详情与能力。skills 包含实际发现的 Skill 调用名称,以及可选的展示名称与描述;mcpServers 包含 manifest 声明的 MCP 服务及其名称、运行时名称、启停状态、传输方式、非敏感连接配置,以及可选的展示名称、描述和图标 URL。两份清单都来自插件的真实文件与 manifest。interface.skillOverrides 和 interface.mcpOverrides 只覆盖展示信息,不改变调用名称或运行配置。
成功时 data 为上文 GET /api/v1/plugins 的插件摘要,加上 root、updatedAt?、manifestKind?、manifestPath?、skills、mcpServers、shadowedManifestPath? 和 diagnostics。可选 query 参数 locale(例如 en-US 或 zh-CN)用于读取 interface.locales 中对应语言的翻译,只影响能力的展示文案;未匹配的字段回退到默认 interface。
40419:没有该 id 的已安装插件
POST /api/v1/plugins/preview
只读检查市场条目的能力,不安装插件。请求体为 { "marketplaceId": "<目录条目 id>", "expectedVersion": "<用户看到的版本>", "expectedSha256": "<用户看到的 sha256sum>", "locale": "<可选语言>" }。expectedSha256 必须与当前目录一致。daemon 将压缩包下载到临时目录,在解压前校验 SHA-256,校验 manifest ID,并发现其中的 Skill 与 MCP 服务。不会写入安装记录、安装运行时或保留解压后的插件。
成功时 data 为 { "skills": [{ "name": "<技能名称>", "description": "<可选描述>" }], "mcpServers": [{ "name": "<manifest 中的名称>", "runtimeName": "<运行时名称>", "enabled": true, "transport": "stdio" }] }。两类条目还可包含 overrides 提供的 displayName、description,MCP 条目还可包含 iconUrl。locale 的选择规则与已安装详情相同。MCP 条目的字段结构与 GET /api/v1/plugins/{plugin_id} 相同,示例只列出常用字段。
40001:请求、压缩包、SHA-256 或 manifest 无效40419:没有该 id 的市场条目40934:目录条目已相对用户看到的版本发生变化,请刷新目录后重试
POST /api/v1/plugins/{plugin_id}:enable
启用一个已安装插件。插件动作经单一路由 POST /api/v1/plugins/{tail} 分发:尾部按 {plugin_id}:{action} 解析,动作为 enable / disable / remove;只给 id 或动作未知时返回 40001(unsupported action: ...)。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
plugin_id | path | string | 必填。 已安装插件 id |
成功时 data 为 { ok: true }。
40001:缺少动作后缀或动作未知40419:没有该 id 的已安装插件
POST /api/v1/plugins/{plugin_id}:disable
停用一个已安装插件但不移除它;分发约定同上文 :enable。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
plugin_id | path | string | 必填。 已安装插件 id |
成功时 data 为 { ok: true }。
40001:缺少动作后缀或动作未知40419:没有该 id 的已安装插件
POST /api/v1/plugins/{plugin_id}:remove
移除一个已安装插件;分发约定同上文 :enable。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
plugin_id | path | string | 必填。 已安装插件 id |
成功时 data 为 { ok: true }。
40001:缺少动作后缀或动作未知40419:没有该 id 的已安装插件
工作区
工作区是已注册的项目目录,会话都落在其中。这组端点管理注册表——列出、注册、重命名与更新源文件夹、注销——以及控制项目级 MCP 配置是否加载的每工作区信任状态。所有返回工作区的端点都使用 workspace 对象 中统一说明的传输结构。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/workspaces | 列出已注册工作区 |
POST /api/v1/workspaces | 注册工作区(每次调用创建新条目;重试经 idempotency_key 去重) |
PATCH /api/v1/workspaces/{workspace_id} | 重命名或整体替换源文件夹 |
POST /api/v1/workspaces/{workspace_id}/primary | 将某个源文件夹提升为主目录 |
GET /api/v1/workspaces/project-config-dirs | 只读获取项目 local.toml 的附加目录 |
DELETE /api/v1/workspaces/{workspace_id} | 注销(保留磁盘内容) |
GET /api/v1/workspaces/{workspace_id}/trust | 读取信任状态 |
POST /api/v1/workspaces/{workspace_id}/trust | 授予信任 |
POST /api/v1/workspaces/{workspace_id}/untrust | 撤销信任 |
workspace 对象
所有返回工作区的端点都使用此传输结构。注册与更新会广播全局事件 event.workspace.created / event.workspace.updated。
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 工作区 id:隐式渠道(CLI/VS Code 按目录进入)为 wd_<slug>_<hash12>,经 POST /api/v1/workspaces 显式创建为 wm_<uuid> |
root | string | 主目录的绝对路径 |
name | string | 显示名,1–100 个字符;默认取主目录的基名 |
kind | string | 工作区类别:managed(经显式创建,wm_ id;会话不合并项目 local.toml)或 implicit(按目录隐式注册,wd_ id;会话合并项目 local.toml 以兼容旧配置) |
additional_dirs | string[] | 注册表管理的额外源文件夹绝对路径(不含项目 local.toml 与临时来源) |
created_at | string | 注册时间,ISO 8601 |
last_opened_at | string | 最近一次打开或重新注册工作区的时间,ISO 8601 |
session_count | integer | 工作区内的会话数 |
GET /api/v1/workspaces
列出所有已注册工作区。
成功时 data 为 { items },每项是一个 workspace 对象。
POST /api/v1/workspaces
注册一个新工作区并返回它。每次调用都创建新条目(wm_<uuid> id)——即使同一路径已是其他工作区的主目录也不会折叠或提示。客户端重复提交(网络重试、重复点击)应携带同一个 idempotency_key,服务端按键去重并返回首次创建的条目。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
root | body | string | 必填。 已存在目录的绝对路径,作为主目录 |
name | body | string | 显示名,1–100 个字符。默认主目录的基名 |
additional_dirs | body | string[] | 额外源文件夹。每项按 add-dir 相同规则解析(绝对路径、相对主目录或 ~ 展开),须已存在且为目录,不得与主目录或彼此重复,最多 64 项 |
idempotency_key | body | string | 客户端生成的幂等键,1–200 个字符。相同键的重试返回首次创建的工作区 |
成功时 data 为 workspace 对象。
40001:root缺失或不是绝对路径,或其他请求校验失败(details会列出该字段)40006:additional_dirs含重复项或与主目录相同。msg为Duplicate source folder: <实际路径>;details为[{ "path": "additional_dirs.N", "directory": "<解析后的绝对路径>" }],其中path是请求字段位置,directory是重复目录40409:root或additional_dirs中的路径不存在或不是目录
PATCH /api/v1/workspaces/{workspace_id}
更新工作区的显示名与/或源文件夹。additional_dirs 为整体替换语义——提交编辑后的完整列表,省略该字段则保持不变;主目录不可修改。name 与 additional_dirs 至少提供其一。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | path | string | 必填。 工作区 id |
name | body | string | 新的显示名,1–100 个字符 |
additional_dirs | body | string[] | 替换后的完整额外源文件夹列表,解析与校验规则同 POST /api/v1/workspaces |
成功时 data 为 workspace 对象。
40001:两个字段都缺失,或其他请求校验失败(details逐字段说明)40006:目录项重复或与主目录相同,msg、details.path和details.directory的含义同POST /api/v1/workspaces40409:additional_dirs中的路径不存在或不是目录40410:工作区不存在
POST /api/v1/workspaces/{workspace_id}/primary
将目录集内的某个源文件夹提升为主目录。服务端做原子交换:该路径成为新的 root,原主目录进入 additional_dirs;工作区 id 与会话桶不变,全部会话保留。交换后原主目录 local.toml 中的附加目录将不再并入(local.toml 跟随主目录生效)。
对于已在 local 环境上运行且未显式设置 environmentCwd 的既有会话,后续工具调用的默认工作目录和相对路径会跟随新的主目录。显式 environmentCwd 和远程环境绑定仍使用其配置的目录。附加目录只扩大允许访问的范围,不会成为相对路径的候选根目录;访问这些目录时请使用绝对路径或显式 cwd。切换过程中已注册的工具保持可用,工作区原有的信任决定也会在重启后保留。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | path | string | 必填。 工作区 id |
path | body | string | 必填。 要提升的目录,解析规则同 add-dir;必须在当前目录集(root ∪ additional_dirs)内 |
成功时 data 为 workspace 对象。
40001:path不在目录集内40409:path不存在或不是目录40410:工作区不存在
GET /api/v1/workspaces/project-config-dirs
只读返回指定项目 local.toml 的 workspace.additional_dir:解析为绝对路径、去重、剔除 root 自身。不修改注册表,也不修改 local.toml;local.toml 缺失时返回空数组,TOML 损坏或配置的目录已不存在时请求失败,不会按空配置返回。客户端可凭此把项目旧配置并入新建或编辑工作区的表单,随保存生效。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
root | query | string | 必填。 项目主目录的绝对路径 |
成功时 data 为 { additional_dirs: string[] }。
40001:root缺失或为空
DELETE /api/v1/workspaces/{workspace_id}
注销工作区。只移除注册表条目——磁盘上的目录不受影响。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | path | string | 必填。 工作区 id |
成功时 data 为 { deleted: true }。
40410:工作区不存在
GET /api/v1/workspaces/{workspace_id}/trust
读取工作区信任状态。信任状态决定是否为该工作区加载项目级 MCP 配置。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | path | string | 必填。 工作区 id |
成功时 data 为 { trusted }。
40410:工作区不存在
POST /api/v1/workspaces/{workspace_id}/trust
将工作区标记为信任,并加载其项目级 MCP 配置。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | path | string | 必填。 工作区 id |
成功时 data 为 { trusted: true }。
40410:工作区不存在
POST /api/v1/workspaces/{workspace_id}/untrust
撤销与当前目录集关联的持久化工作区信任记录。如果进程或配置覆盖没有使工作区保持受信任,则同时卸载其项目级 MCP 配置。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace_id | path | string | 必填。 工作区 id |
成功时 data 为 { trusted },表示撤销后的有效信任状态。通常为 { trusted: false };如果 KIMI_CODE_TRUST_WORKSPACE 或 [workspace] require_trust = false 生效,则仍为 true。
40410:工作区不存在40409:path不存在或不是目录40410:工作区不存在
文件系统
会话内文件操作走 POST /api/v1/sessions/{session_id}/fs:{action},请求体为 JSON;动作包括 list / read / list_many / stat / stat_many / mkdir / search / grep / git_status / git_status:batch / pull_request / pull_request:batch / diff / open / open-in / reveal。动作在会话创建时所在的环境上执行;open、open-in 与 reveal 仅对 local 环境上的会话可用。另有:
| 方法与路径 | 说明 |
|---|---|
POST /api/v1/workspace/fs:list | 无会话的工作区目录列举 |
POST /api/v1/workspace/fs:search | 无会话的工作区搜索(body 携带工作区引用) |
POST /api/v1/workspace/fs:suggest | 无会话的文件补全候选(用于 @ 文件提及) |
POST /api/v1/fs:suggest | 跨一个或多个绝对路径根目录的文件补全候选,不需要会话或工作区 |
GET /api/v1/sessions/{session_id}/fs/{path}:download | 下载会话文件(二进制,见下文) |
GET /api/v1/fs:browse | 列出本机目录(文件夹选择器用) |
GET /api/v1/fs:home | 用户主目录与最近工作区 |
GET /api/v1/fs:content | 读取本机任意文件原始字节(仅受 token 保护,谨慎暴露端口) |
POST /api/v1/fs:mkdir | 按绝对路径创建目录 |
POST /api/v1/sessions/{session_id}/fs:list
列出会话工作区目录下的条目,可选递归子目录。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | body | string | 要列出的目录,相对于会话工作目录。默认 . |
depth | body | integer | 递归深度,1–10。默认 1 |
limit | body | integer | 最大条目数,1–1000。默认 200 |
show_hidden | body | boolean | 包含点文件。默认 false |
follow_gitignore | body | boolean | 跳过 gitignore 的路径。默认 true |
exclude_globs | body | string[] | 额外要跳过的 glob |
allow_ignored_globs | body | string[] | 即使被 gitignore 也指定放行的 glob(如 .tmp)。命中项被忽略的祖先目录会自动保留以保证可达。放行点开头路径还需同时传 show_hidden: true |
sort | body | string | type_first(默认)/ name_asc / name_desc / mtime_desc / size_desc |
include_git_status | body | boolean | 附带每个条目的 git 状态。默认 false |
成功时 data 为 { items, truncated }——depth 大于 1 时另附 children_by_path(路径 → 条目的映射)。每项是一个条目对象 { path, name, kind, size?, modified_at, etag?, mime?, language_id?, is_binary?, is_symlink_to?, git_status?, child_count? },其中 kind 为 file / directory / symlink;git_status(仅 include_git_status: true 时存在)为 clean / modified / added / deleted / renamed / untracked / ignored / conflicted 之一;truncated 表示 limit 截断了列表。
40001:请求体校验失败40401:会话不存在40409:路径不存在(包括path不是目录的情况)41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:read
以文本或 base64 读取会话文件的一段内容。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | body | string | 必填。 文件路径,相对于会话工作目录 |
offset | body | integer | 起始字节偏移。默认 0 |
length | body | integer | 读取字节数,1–10485760(10 MiB)。默认 1048576(1 MiB) |
encoding | body | string | auto(默认)/ utf-8 / base64 |
成功时 data 为 { path, content, encoding, size, truncated, etag, mime, language_id?, line_count?, is_binary },其中 encoding 报告实际使用的编码(utf-8 或 base64),size 为文件完整大小。encoding: "auto" 时文本以 utf-8 返回(非 UTF-8 文本会被转码),二进制内容以 base64 返回;encoding: "utf-8" 强制按文本读取并拒绝二进制文件。
40001:请求体校验失败40401:会话不存在40409:路径不存在40906:路径是目录40907:二进制文件却指定了encoding: "utf-8"41302:文件超过 10 MiB 读取上限41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:list_many
一次调用列出多个会话目录;失败的路径会折进响应里,而不是让整个请求失败。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
paths | body | string[] | 必填。 要列出的目录,1–100 条 |
其余请求体字段(depth、limit、show_hidden、follow_gitignore、exclude_globs、sort、include_git_status)的类型、取值范围与默认值同 fs:list。成功时 data 为 { results }——每个请求路径到其条目数组(条目对象见 fs:list 的说明)的映射,另附 truncated_paths(达到 limit 的路径)与 partial_errors(失败路径到其 { code, msg } 错误的映射)。
40001:请求体校验失败40401:会话不存在
POST /api/v1/sessions/{session_id}/fs:stat
查询会话工作区内单个路径的元信息。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | body | string | 必填。 要查询的路径,相对于会话工作目录 |
成功时 data 为 fs:list 中说明的条目对象。
40001:请求体校验失败40401:会话不存在40409:路径不存在41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:stat_many
一次调用查询多个会话路径的元信息;不存在的路径返回 null,不会让整个请求失败。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
paths | body | string[] | 必填。 要查询的路径,1–1000 条 |
成功时 data 为 { entries }——每个请求路径到其条目对象(见 fs:list 的说明)的映射,路径不存在时为 null。
40001:请求体校验失败40401:会话不存在
POST /api/v1/sessions/{session_id}/fs:mkdir
在会话工作区内创建目录。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | body | string | 必填。 要创建的目录,相对于会话工作目录 |
recursive | body | boolean | 创建缺失的父目录。默认 false |
成功时 data 为所建目录的条目对象(见 fs:list 的说明)。
40001:请求体校验失败40401:会话不存在40409:父目录不存在(非递归创建)40919:路径已存在(非递归创建)41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:search
在会话工作区内模糊搜索文件与目录名。query 为空时改为列出顶层条目。当 {session_id} 位置携带的是工作区引用(已注册工作区 id 或绝对根路径)而非会话 id 时,搜索针对该工作区执行——这是为尚未创建的草稿会话准备的无会话形式;正式的无会话端点是 POST /api/v1/workspace/fs:search。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id,或工作区引用 |
query | body | string | 必填。 搜索文本;"" 表示列出顶层 |
limit | body | integer | 最大命中数,1–200。默认 50 |
include_globs | body | string[] | 只保留匹配这些 glob 之一的路径 |
exclude_globs | body | string[] | 跳过匹配这些 glob 的路径 |
follow_gitignore | body | boolean | 为 true 时跳过 gitignore 路径。默认 false |
成功时 data 为 { items, truncated },每项为 { path, name, kind, score, match_positions }——kind 为 file / directory / symlink,score 为 0 到 1 之间的模糊匹配得分,match_positions 列出匹配到的字符偏移。命中优先按匹配质量排序,同一匹配质量内普通命中排在忽略命中之前;包含忽略命中时可能执行一次补充扫描。truncated 表示超出 limit 的命中被丢弃。
40001:请求体校验失败40401:该引用既不是会话,也不是可解析的工作区
POST /api/v1/sessions/{session_id}/fs:grep
在会话工作区内搜索文件内容——默认按字面字符串,regex: true 时按正则表达式。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
pattern | body | string | 必填。 要搜索的文本或正则 |
regex | body | boolean | 将 pattern 视为正则表达式。默认 false |
case_sensitive | body | boolean | 默认 true |
include_globs | body | string[] | 只保留匹配这些 glob 之一的文件 |
exclude_globs | body | string[] | 跳过匹配这些 glob 的文件 |
follow_gitignore | body | boolean | 跳过 gitignore 的路径。默认 true |
max_files | body | integer | 最多扫描的文件数,1–10000。默认 200 |
max_matches_per_file | body | integer | 每个文件保留的匹配数,1–10000。默认 50 |
max_total_matches | body | integer | 总共保留的匹配数,1–100000。默认 5000 |
context_lines | body | integer | 每个匹配携带的上下文行数,0–10。默认 2 |
成功时 data 为 { files, files_scanned, truncated, elapsed_ms },其中 files 的每项为 { path, matches },每个匹配为 { line, col, text, before, after }(before / after 最多携带 context_lines 行上下文);truncated 表示某个匹配配额截断了结果。
40001:请求体校验失败40401:会话不存在41305:搜索超时
POST /api/v1/sessions/{session_id}/fs:git_status
读取 git 状态,可选限定在一组路径内。提供 root 时,返回条目的路径相对于该目录;省略时,查询整个 Git worktree,条目路径相对于仓库根目录。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
root | body | string | 要限定查询范围的工作区目录;省略时查询整个 Git worktree,相对路径从会话工作目录解析 |
paths | body | string[] | 将状态限定在这些路径;相对路径在提供 root 时从该目录解析,否则从会话工作目录解析 |
include_pull_request | body | boolean | 是否包含关联的 Pull Request。默认 true |
成功时 data 为 { branch, ahead, behind, entries, additions, deletions, pullRequest },其中 entries 把每个变更路径映射到其状态(clean / modified / added / deleted / renamed / untracked / ignored / conflicted),pullRequest 为 { number, state, url }(state 为 open / merged / closed / draft)或 null。
40001:请求体校验失败40401:会话不存在40908:git 不可用(不是仓库,或没有 git 可执行文件)41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:git_status:batch
一次调用读取多个工作区目录的 git 状态;失败的目录会折进 errors,而不是让整个请求失败。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
roots | body | string[] | 必填。 要查询的工作区目录,1–32 条 |
include_pull_request | body | boolean | 是否在每项结果中包含关联的 Pull Request。默认 true |
成功时 data 为 { results, errors }。results 把每个成功的 root 映射到与 fs:git_status 相同的状态对象;errors 把每个失败的 root 映射到其 { code, msg } 错误,错误码与单目录动作一致。
40001:请求体校验失败40401:会话不存在
POST /api/v1/sessions/{session_id}/fs:pull_request
读取会话工作区中指定目录关联的 Pull Request。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
root | body | string | 要查询的工作区目录,默认是会话工作目录;相对路径从会话工作目录解析 |
成功时 data 为 { number, state, url }(state 为 open / merged / closed / draft);未找到 Pull Request 时为 null。
40001:请求体校验失败40401:会话不存在40908:git 不可用(不是仓库,或没有 git 可执行文件)41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:pull_request:batch
一次调用读取多个工作区目录关联的 Pull Request;失败的目录会折进 errors,而不是让整个请求失败。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
roots | body | string[] | 必填。 要查询的工作区目录,1–32 条 |
成功时 data 为 { results, errors }。results 把每个成功的 root 映射到与 fs:pull_request 相同的对象或 null;errors 把每个失败的 root 映射到其 { code, msg } 错误。
40001:请求体校验失败40401:会话不存在
POST /api/v1/sessions/{session_id}/fs:diff
返回会话工作区中指定目录内单个文件的 unified git diff。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | body | string | 必填。 要 diff 的文件,相对于 root |
root | body | string | 要查询的工作区目录,默认是会话工作目录;相对路径从会话工作目录解析 |
成功时 data 为 { path, diff, truncated },其中 diff 为 unified diff 文本,truncated 表示过长的 diff 被截断。
40001:请求体校验失败40401:会话不存在40908:git 不可用(不是仓库,或没有 git 可执行文件)41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:open
用宿主操作系统的默认程序打开会话文件。仅限 local 环境。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | body | string | 必填。 要打开的文件,相对于会话工作目录 |
line | body | integer | 在处理程序支持时跳转到的行号(正整数) |
成功时 data 为 { opened: true }。
40001:请求体校验失败40401:会话不存在40409:路径不存在41304:路径越出会话工作区
POST /api/v1/sessions/{session_id}/fs:open-in
在指定的宿主应用程序中打开会话文件或目录。仅限 local 环境。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
app_id | body | string | 必填。 目标应用:finder / cursor / vscode / iterm / terminal |
path | body | string | 必填。 要打开的文件或目录,相对于会话工作目录 |
line | body | integer | 在应用支持时跳转到的行号(正整数) |
成功时 data 为 { opened: true }。
40001:请求体校验失败40401:会话不存在40409:路径不存在41304:路径越出会话工作区50001:应用启动失败
POST /api/v1/sessions/{session_id}/fs:reveal
在宿主操作系统的文件管理器中显示会话文件。仅限 local 环境。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | body | string | 必填。 要显示的文件,相对于会话工作目录 |
成功时 data 为 { revealed: true }。
40001:请求体校验失败40401:会话不存在40409:路径不存在41304:路径越出会话工作区
GET /api/v1/sessions/{session_id}/fs/{path}:download
从会话工作区下载文件;{path} 是相对于工作区的文件路径,并带字面量 :download 后缀。响应为支持 Range 与 ETag 的二进制流——见 二进制与流式端点。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
session_id | path | string | 必填。 会话 id |
path | path | string | 必填。 相对于工作区的文件路径,加 :download 后缀 |
allow_external_symlinks | query | string | 传 true 时允许通过工作区外的软链接下载。默认 false |
40001:路径缺失或为空40401:会话不存在40409:路径不存在41304:路径越出会话工作区
POST /api/v1/workspace/fs:list
fs:list 的无会话形式:工作区改由请求体而非 URL 携带。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace | body | string | 必填。 已注册工作区 id 或绝对根路径(当场注册) |
path | body | string | 要列举的目录,相对于工作区根。默认 . |
depth | body | integer | 递归深度,1–10。默认 1 |
limit | body | integer | 最大条目数,1–1000。默认 200 |
show_hidden | body | boolean | 是否包含点文件。默认 false |
follow_gitignore | body | boolean | 是否跳过 gitignore 路径。默认 true |
exclude_globs | body | string[] | 额外要跳过的 glob |
allow_ignored_globs | body | string[] | 即使被 gitignore 也要显示的 glob |
allow_external_symlinks | body | boolean | 是否跟随目标在工作区外的软链接目录。默认 false |
sort | body | string | type_first(默认)/ name_asc / name_desc / mtime_desc / size_desc |
成功时 data 与 fs:list 形状相同。
40001:请求体校验失败40409:路径不存在或不是目录40410:工作区不存在,且不是可用的绝对路径40411:宿主文件系统拒绝访问41304:路径通过软链接越出工作区,且未启用allow_external_symlinks
POST /api/v1/workspace/fs:search
fs:search 的无会话形式:工作区改由请求体而非 URL 携带。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace | body | string | 必填。 已注册工作区 id 或绝对根路径(当场注册) |
query | body | string | 必填。 搜索文本;"" 表示列出顶层 |
limit | body | integer | 最大命中数,1–200。默认 50 |
include_globs | body | string[] | 只保留匹配这些 glob 之一的路径 |
exclude_globs | body | string[] | 跳过匹配这些 glob 的路径 |
follow_gitignore | body | boolean | 为 true 时跳过 gitignore 路径。默认 false |
成功时 data 为 { items, truncated },命中结构与排序同 fs:search。
40001:请求体校验失败40410:工作区不存在,且不是可用的绝对路径
POST /api/v1/workspace/fs:suggest
在无会话的情况下给出工作区内的文件与目录补全候选——即输入框中 @ 文件提及的后端。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
workspace | body | string | 必填。 已注册工作区 id 或绝对根路径(当场注册) |
query | body | string | 必填。 要补全的部分路径文本 |
limit | body | integer | 最大候选数,1–200。默认 50;fd 搜索最多返回 20 条 |
follow_gitignore | body | boolean | 为 true 时跳过 gitignore 路径。默认 false |
show_hidden | body | boolean | 包含点文件。默认 false;fd 搜索始终包含 |
stream | body | boolean | 为 true 时以 NDJSON 返回 preview/final 事件。默认 false |
include_globs | body | string[] | 只保留匹配这些 glob 之一的路径 |
exclude_globs | body | string[] | 跳过匹配这些 glob 的路径 |
成功时 data 为 { items, truncated },每项为 { path, name, kind, score, match_positions },命中结构同 fs:search。候选优先按匹配质量排序,同一匹配质量内普通候选排在忽略候选之前。fd 可用时采用与本地 @ 补全相同的策略:始终包含隐藏路径,每个 root 每轮最多扫描 100 条,最多返回 20 条;超出扫描上限的匹配可能遗漏。包含忽略候选时可能执行一次 --no-ignore-vcs 补充扫描;fd 不可用时回退到 ripgrep/Node 实现。
使用 stream:true 时,响应改为 NDJSON,而不是单个 JSON 对象。每个响应包的 data 包含 phase(preview、final 或 error)以及相同的结果字段。preview 携带普通 fd 候选且 truncated:true;ignored 扫描完成后的 final 用于替换 preview。关闭连接会取消搜索。
40001:请求体校验失败40410:工作区不存在,且不是可用的绝对路径
POST /api/v1/fs:suggest
在一个或多个绝对路径根目录中给出文件与目录补全候选,不需要会话或工作区,也不会登记任何东西。第一个根目录是主根:它下面的候选以相对路径返回,其他根目录下的候选以绝对路径返回。互相重叠的根目录只搜索一次。
请求体用 roots 代替 workspace,其余 query、limit、follow_gitignore、show_hidden、stream、include_globs、exclude_globs 字段与 POST /api/v1/workspace/fs:suggest 相同:
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
roots | body | string[] | 必填。 1–32 个绝对目录路径;第一个是主根 |
响应(包括 stream: true 时的 NDJSON 形式)与 POST /api/v1/workspace/fs:suggest 相同。
40001:请求体校验失败,包括根目录不是绝对路径40409:根目录不存在或不是目录(msg中写明是哪一个)
GET /api/v1/fs:browse
列出某个本机目录的子目录——文件夹选择器的后端。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
path | query | string | 绝对目录路径。默认用户主目录 |
成功时 data 为 { path, parent, entries },其中 path 为解析后的目录,parent 为其父目录(文件系统根处为 null),每条目为 { name, path, is_dir: true }。
40001:path不是绝对路径40409:路径不存在40411:权限不足
GET /api/v1/fs:home
返回文件夹选择器的落地数据。无参数。
成功时 data 为 { home, recent_roots },其中 home 为用户主目录,recent_roots 列出已注册工作区的根目录。
GET /api/v1/fs:content
以流式返回本机文件系统上任意文件的原始字节——仅受 API token 保护,暴露端口时务必谨慎。支持 Range 请求与 ETag 缓存;见 二进制与流式端点。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
path | query | string | 必填。 绝对文件路径 |
40001:path不是绝对路径,或不是普通文件40409:路径不存在40411:权限不足40906:路径是目录
POST /api/v1/fs:mkdir
按绝对路径在本机文件系统上创建一个目录——文件夹选择器「新建文件夹」的后端。非递归:父目录必须已存在。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
path | body | string | 必填。 绝对目录路径 |
成功时 data 为 { path }。
40001:path不是绝对路径40409:父路径不存在40411:权限不足40919:路径已存在
文件上传
| 方法与路径 | 说明 |
|---|---|
POST /api/v1/files | multipart 上传(字段 file,可选 name、expires_in_sec),返回文件元信息 |
GET /api/v1/files/{file_id} | 下载(二进制,错误用真实 HTTP 状态码) |
DELETE /api/v1/files/{file_id} | 删除 |
POST /api/v1/files
以 multipart/form-data 上传文件,供后续引用(例如作为提示词附件)。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
file | body | binary | 必填。 multipart 的文件部分 |
name | body | string | 存储的显示名。默认上传文件名 |
expires_in_sec | body | number | 文件过期前的秒数(非负)。默认永不过期 |
成功时 data 为文件元信息 { id, name, media_type, size, created_at, expires_at? },其中 media_type 取自上传的内容类型。
40001:multipart 请求体缺少file字段
GET /api/v1/files/{file_id}
下载已上传的文件。响应为二进制流,支持 Range 请求但不处理 If-None-Match;失败使用真实 HTTP 状态码——见 二进制与流式端点。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
file_id | path | string | 必填。 上传响应返回的文件 id |
40407(HTTP 404):没有该 id 的文件(包括已过期的文件)
DELETE /api/v1/files/{file_id}
删除已上传的文件。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
file_id | path | string | 必填。 上传响应返回的文件 id |
成功时 data 为 { deleted: true }。
40407(HTTP 404):没有该 id 的文件
GUI 存储
由服务端支撑的键值存储,接口对齐浏览器的 localStorage,持久化在服务的 home 目录下;web UI 用它保存跨客户端的 UI 状态。值是不透明字符串——序列化由调用方负责。
| 方法与路径 | 说明 |
|---|---|
GET /api/v1/gui/store/length | 已存键的数量 |
GET /api/v1/gui/store/getItem | 按键读取值 |
POST /api/v1/gui/store/setItem | 按键写入值 |
POST /api/v1/gui/store/removeItem | 按键删除值 |
POST /api/v1/gui/store/clear | 删除所有值 |
GET /api/v1/gui/store/length
返回已存键的数量(对齐 localStorage.length)。无参数。
成功时 data 为 { length }。
GET /api/v1/gui/store/getItem
读取一个值(对齐 localStorage.getItem)。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
key | query | string | 必填。 要读取的键,1–256 个字符 |
成功时 data 为 { value }——已存字符串,键不存在时为 null。
POST /api/v1/gui/store/setItem
写入一个值(对齐 localStorage.setItem)。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
key | body | string | 必填。 要写入的键,1–256 个字符 |
value | body | string | 必填。 要存储的值 |
成功时 data 为 null。
POST /api/v1/gui/store/removeItem
删除一个值(对齐 localStorage.removeItem)。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
key | body | string | 必填。 要删除的键,1–256 个字符 |
成功时 data 为 null。
POST /api/v1/gui/store/clear
删除所有已存值(对齐 localStorage.clear)。无参数。
成功时 data 为 null。
全局搜索与其他
| 方法与路径 | 说明 |
|---|---|
POST /api/v1/search | 跨会话全文搜索,mode 为 terms(默认)或 literal(精确子串),page_token 分页 |
GET /api/v1/connections | 列出当前在线的 WebSocket 连接 |
GET /api/v2/sessions | 新一代会话列表,见下文 |
POST /api/v2/sessions:archive | 批量归档会话,见下文 |
POST /api/v2/sessions:restore | 批量恢复已归档会话,见下文 |
/api/v2/mcp/* | 统一的 MCP 管理面,见下文 |
/api/v1/debug/* | 反射式调试 RPC,仅 --debug-endpoints 且 loopback 时挂载,不属于稳定协议 |
POST /api/v1/search
跨会话全文搜索,覆盖 User 消息、Assistant 回复与会话标题,由服务端的持久搜索索引支撑。用 container.session_id 限定在单个会话内的搜索同样走索引,因此正在运行的步骤还在生成的文本,要等该步骤保存、索引追上之后才能搜到;index_state.stale 标记仍在追赶的视图。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
query | body | string | 必填。 搜索文本 |
mode | body | string | terms(默认)/ literal |
op | body | string | terms 模式下的词项组合符:AND(默认)/ OR |
container | body | object | 将搜索限定在 { session_id?, agent_id? } |
role | body | string | 限定 user / assistant / title 命中 |
start_time | body | integer | 只看不早于该时间的命中(epoch 毫秒) |
end_time | body | integer | 只看不晚于该时间的命中(epoch 毫秒) |
sort | body | string | score(默认)/ time_desc / time_asc;literal 模式忽略此参数,始终最新在前 |
page_size | body | integer | 每页命中数,1–50。默认 20 |
page_token | body | string | 上一页响应返回的令牌 |
terms 模式下查询会被分词(ASCII 词加 CJK n-gram)、去重,并以至多 32 个词项匹配倒排索引;literal 模式是零误报的精确子串搜索。成功时 data 为 { items, has_more, page_token?, index_state },每项为 { session_id, workspace_id, session_title, agent_id, role, snippet, time, turn?, step_id?, score }。index_state 为 { state, indexed_sessions, total_sessions, documents, stale?, degraded? },其中 state 为 building / ready / readonly 之一;stale 标记仍在追赶的落后视图,degraded 携带最近一次刷新失败的信息。超出预算的页会额外携带 incomplete,取值为 candidate_cap / postings_budget / deadline 之一。分页令牌锁定索引代际与查询条件——索引重建或查询变更会使其失效。
40001:请求体校验失败、查询不可用(为空或超过 32 个词项),或分页令牌非法
GET /api/v1/connections
列出当前连接到本服务的 WebSocket 客户端,按连接时间最早在前。无参数。
成功时 data 为 { connections },每项为 { id, connected_at, remote_address, user_agent, subscriptions }:connected_at 为 ISO 8601 时间戳;remote_address 与 user_agent 未知时为 null;subscriptions 列出该连接订阅的会话 id。
GET /api/v2/sessions
面向列表页的新一代会话查询,筛选、排序、字段组都在查询参数里:
| 参数 | 说明 |
|---|---|
workspace.id | 按工作区过滤,可重复 |
activity.status | 按活动状态过滤:running / approval / question / failed / idle,可重复 |
meta.updated_after | 只看该时间(epoch 毫秒)之后更新过的会话 |
meta.updated_before | 只看该时间(epoch 毫秒)之前更新过的会话 |
meta.archived | true / false(默认)/ all |
meta.has_prompt | true 只保留有用户 prompt 的会话,false 只保留空会话(等价 GET /api/v1/sessions 的 exclude_empty) |
view | flat(默认)/ by_workspace,见下文 |
group.page_size | view=by_workspace 时每个工作区返回的会话数:1–100,默认 5(使用 id,archived 投影时上限 10000);未开分组视图时传入返回 40001 |
sort | meta.updated_at_desc(默认)/ meta.updated_at_asc / meta.created_at_desc |
include | 逗号分隔的附加字段组;目前支持 git(分支与 PR 信息,按环境与工作目录去重并缓存 60 秒) |
fields | 逗号分隔的字段投影;目前仅支持 id,archived,每项裁剪为 { id, archived }(用于全选匹配场景)。不可与 include=git 同传(40001) |
page_size | 1–100,默认 50;使用 id,archived 投影时上限放宽至 10000。view=by_workspace 时按组计数 |
page_token | 上一页返回的翻页令牌 |
page | 无状态的 1 起始页码;与 page_token 互斥(同传返回 40001) |
响应每项固定包含 workspace、meta、activity 三组,include=git 时附加 git 组;fields=id,archived 时仅返回 { id, archived }。activity 组还会带上 model:会话仍加载在当前进程时为其绑定的模型别名,冷会话(未加载)为 null。每页额外携带 total,即过滤后的集合大小。翻页令牌绑定首页查询条件(含投影),中途改条件返回 40922。page 模式是跳页用的无状态替代:每次请求都是独立快照,不签发令牌,next_page_token 恒为 null。
view=by_workspace 时,同一份过滤、排序后的集合会重新投影为按工作区分组的形态,概览页因此可以用一次请求替代「每个工作区各一轮询」:
{
"code": 0,
"msg": "success",
"data": {
"groups": [
{
"workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" },
"sessions": [ { "id": "session_...", "workspace": { "id": "wd_my-app_a1b2c3d4e5f6", "cwd": "/Users/dev/my-app" }, "meta": { "title": "Fix the login page", "last_prompt": "adjust the button spacing", "created_at": 1787000000000, "updated_at": 1787000100000, "archived": false, "archived_at": null }, "activity": { "status": "idle", "model": "kimi-for-coding" } } ],
"total": 42
}
],
"total": 7,
"has_more": true,
"next_page_token": "eyJ2IjoxLCJmIjoi..."
},
"request_id": "req_..."
}每组携带该工作区按请求 sort 排序的前 group.page_size 条会话,以及该工作区匹配过滤条件的会话总数 total(用作「查看全部」入口)。只有至少有一条匹配会话的工作区才会出现;组间按组内首条会话的 sort key 排序,相同则按工作区 id。page 与 page_token 按组翻页(外层 total 为组数),指纹绑定规则相同:令牌同时覆盖 view 与分组参数,翻页途中变更同样返回 40922。
POST /api/v2/sessions:archive 与 POST /api/v2/sessions:restore
面向会话管理页的批量归档/恢复。请求体为 { "ids": ["session_..."] }——非空、去重后不超过 5000 条。仍在线的会话走完整生命周期;未加载的冷会话直接改写磁盘上的元数据,不会被加载。
只有请求体校验失败才会让整个请求失败(40001);其余情况按条返回:data.results 保持输入顺序,每项为 { id, ok } 或 { id, ok: false, error }(不存在的 id 在自身条目里报 40401),并附 succeeded / failed 计数。
{
"code": 0,
"msg": "success",
"data": {
"results": [
{ "id": "session_a", "ok": true },
{ "id": "session_b", "ok": false, "error": { "code": 40401, "message": "session session_b does not exist" } }
],
"succeeded": 1,
"failed": 1
},
"request_id": "req_..."
}MCP 管理(/api/v2/mcp)
/api/v2/mcp/* 路由是服务的统一 MCP 管理面:独立于任何会话,直接管理 MCP server 注册表本身——全局(用户级)CRUD 与逐条校验、连接测试探测、locator 寻址的检查目录、按 server 的授权状态列表,以及完整的 OAuth 流程生命周期。
| 方法与路径 | 说明 |
|---|---|
GET /api/v2/mcp/servers | 列出所有已知 MCP server |
GET /api/v2/mcp/servers/{name} | 按运行时名称获取单个 server |
POST /api/v2/mcp/servers | 向用户级 mcp.json 添加 server |
PUT /api/v2/mcp/servers/{name} | 替换一个用户级条目 |
DELETE /api/v2/mcp/servers/{name} | 删除一个用户级条目 |
POST /api/v2/mcp/servers:test | 对单个 server 发起真实连接探测 |
POST /api/v2/mcp/servers:inspect | locator 寻址的目录及批量连接探测 |
GET /api/v2/mcp/auth-statuses | 目录中各 server 的 OAuth 状态 |
POST /api/v2/mcp/auth:begin | 开始一次交互式 OAuth 流程 |
POST /api/v2/mcp/auth:complete | 等待浏览器回调并完成 code 交换 |
POST /api/v2/mcp/auth:cancel | 终止已开始的 OAuth 流程 |
POST /api/v2/mcp/auth:reset | 清除某个 server 已存储的凭据 |
该管理面有两种寻址方式。CRUD 路由与 servers:test 使用普通的运行时 name;检查与 OAuth 路由使用 locator——文件层条目用 { "source": "global", "name" },插件清单条目用 { "source": "plugin", "pluginId", "serverName" }——因为插件条目和文件条目可能共用同一个运行时名称。检查条目还带有一个稳定的 serverId 线上标识:global:<name> 或 plugin:<pluginId>:<serverName>(URL 编码)。
大多数路由接受可选的 cwd(查询参数,:-action 路由则为请求体字段)。不传时目录只覆盖用户级文件与插件清单;传入后,该目录的项目根层与项目本地层会并入——但仅当工作区受信任时,否则项目层会被跳过。对 stdio server 执行 servers:test 时,cwd 同时是子进程的工作目录。连接探测与 OAuth 调用会等待服务配置加载完成后再执行。
GET /api/v2/mcp/servers 与 GET /api/v2/mcp/servers/{name}
列出管理面已知的全部 MCP server;第二个路由返回该运行时名称对应的单个条目。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
name | path | string | 必填(仅 get)。 server 的运行时名称 |
cwd | query | string | 并入该(受信任)目录的项目层 |
成功时 data 是受管 server 数组(get 路由为单个对象),每项为 { name, config, source, origin, mutable, plugin? }:
source:global(配置文件层)或plugin(插件清单)origin:条目的定义位置——文件路径或插件 idmutable:只有用户级条目可变;插件与项目层条目均为只读config:可变条目携带完整配置,便于编辑界面预填;只读条目被脱敏为排序后的键名列表(envKeys/headerKeys),绝不泄露密钥值plugin:{ id, name },仅插件条目携带40001:校验失败40408:不存在该名称的 server
POST / PUT / DELETE /api/v2/mcp/servers
针对用户级 mcp.json 的全局 CRUD。新增请求体是包含 name 的完整 server 配置——transport(stdio / http / sse)决定配置形状,每条配置写入前都会校验。更新请求体携带同样的配置但不含 name(由路径指定条目);删除无请求体。三者都在 data 中返回刷新后的 server 列表。若写入与项目层的同名条目冲突,会因只读被拒绝——请改为编辑定义它的文件;与同名的插件条目冲突并不阻止写入,新的文件条目会将其遮蔽。
40001:校验失败,或目标条目为只读40408:(更新/删除)不存在该名称的 server
POST /api/v2/mcp/servers:test
对单个 server 发起真实连接探测,不持久化任何内容。传 name 探测注册表条目(含插件与受信任的项目层),或传 server(包含 name 的完整内联配置)按原样探测;两者都传或都不传会报 40001。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
name | body | string | 注册表条目的运行时名称 |
server | body | object | 按原样探测的内联 server 配置 |
cwd | body | string | 项目层并入解析;同时是 stdio 的工作目录 |
成功时 data 为 { success, output }:连接成功时 output 列出该 server 的可用工具,否则携带失败信息。
40001:两种目标形式都传或都不传、内联配置无效,或运行时名称被多个启用的 server 共用40408:不存在该名称的 server
POST /api/v2/mcp/servers:inspect
locator 寻址的目录(脱敏配置),外加对每个 OAuth 候选的批量真实连接探测。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
targets | body | array | 缩小目录范围的 locator 数组;不传则检查全部 server |
cwd | body | string | 并入该(受信任)目录的项目层 |
成功时 data 是检查结果数组,每项为 { serverId, locator, runtimeName, canonicalUrl?, origin, config, enabled, editable, authStatus, checkedAt?, error? }:canonicalUrl 是远程 server 的凭据 URL,config 为脱敏视图,authStatus 取值为 not-applicable / bearer-token / oauth-required / oauth-authorized / oauth-expired / unavailable 之一。运行时名称被多个启用的 server 共用时无法无歧义地探测,会报告 unavailable 并在 error 中给出说明。探测遇到过期授权时,可能刷新或作废已存储的凭据。
40001:校验失败40408:targets中有 locator 未匹配到任何条目
GET /api/v2/mcp/auth-statuses
注册表目录中各 server 的 OAuth 状态——只需要授权维度时,这是比 servers:inspect 更轻量的选择。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
cwd | query | string | 并入该(受信任)目录的项目层 |
verify | query | string | true 对每个 OAuth 候选发起真实连接验证;false 完全离线(仅凭配置与已存储 token 分类);缺省保留隐式 OAuth 探测,只探测未固定且没有已存储凭据的远程 server |
成功时 data 是 { name, authStatus } 数组,authStatus 取值与 servers:inspect 相同。验证探测可能刷新或作废已存储的凭据。
POST /api/v2/mcp/auth:begin / :complete / :cancel / :reset
远程 server 的 OAuth 流程生命周期。auth:begin 接受 locator 请求体(外加可选的 cwd 查询参数),返回 data 为 { status: "authorization-required", flowId, authorizationUrl }——在浏览器中打开该 URL 完成授权——或当授权已存在时返回 { status: "already-authorized" }。目标 server 必须使用远程传输(http / sse)且不含静态 bearer token;静态请求头仅当配置显式设置 auth: "oauth" 时允许。
auth:complete 等待已开始流程的浏览器回调并完成 code 交换。请求体为 { flowId, timeoutMs? }:等待默认 15 分钟(timeoutMs 可覆盖),空闲流程无论如何都会在 15 分钟后过期,关闭 HTTP 连接会中止等待。成功时 data 为 null。
auth:cancel 在未完成的情况下终止已开始的流程({ flowId });未知流程会被忽略。auth:reset 接受 locator 请求体,清除该 server 已存储的凭据——失效事件会送达存活的会话。
40001:校验失败——包括:complete的flowId未知,或:begin的 server 无法使用 OAuth(stdio 传输、静态 bearer token,或未设置auth: "oauth"的静态请求头)40408:(:begin/:reset)locator 未匹配到任何条目40929:OAuth 流程本身失败
WebSocket 协议
建立连接
唯一端点是 ws://<host>:<port>/api/v1/ws;鉴权在升级请求时完成,凭证放在 Authorization: Bearer <token> 请求头或 kimi-code.bearer.<token> 子协议里(见上文 鉴权)。连接不需要握手:建立后即开始接收全局事件,客户端也可以直接发送命令。
心跳
服务端每 10 秒发送一次 { "type": "ping" },客户端回复 { "type": "pong" }。服务端连续 20 秒收不到客户端的任何帧时断开连接。客户端连续 25 秒没有收到任何帧时,应视为连接已断开并重连。
命令
客户端发送平铺的 JSON 帧:字段与 type 并列,每条命令都带 request_id。每条命令收到一条应答 { "type": "response", "request_id", "code", "msg"?, "task"? },code 为 0 表示成功。缺少可读的 request_id 时,服务端以关闭码 1008 断开连接;不认识的帧类型会被忽略。
| 帧 | 字段 | 说明 |
|---|---|---|
subscribe | { request_id, session_id, agent_ids? } | 订阅会话,开始接收所列 agent;agent_ids 默认为 ["main"],之后对同一会话再发 subscribe 会追加 agent。会话无法打开时,应答带上错误码——会话不存在时为 40401,40930、40931 等其他错误码说明无法打开的原因——且不建立任何订阅。会话打开后立即应答,先于该订阅的任何帧;各 agent 的对话在应答之后加载。帧格式错误时应答 40001 |
unsubscribe | { request_id, session_id, agent_ids? } | 停止接收 agent;省略 agent_ids 或移除最后一个 agent 时取消整个会话订阅 |
task.watch | { request_id, session_id, agent_id, task_id, since_offset?, tail_bytes? } | 把某个任务的输出流式推送到本连接,无需订阅会话;agent_id 是任务所属的 agent(即该任务 task 帧上的 agent_id),since_offset 从客户端已有输出之后续传,tail_bytes 是首段输出最多包含的字节数 |
task.unwatch | { request_id, session_id, agent_id, task_id } | 停止推送该任务的输出 |
task.stop | { request_id, session_id, agent_id, task_id } | 停止任务;已结束的任务直接应答其状态 |
task.background | { request_id, session_id, agent_id, task_id } | 让发起任务的工具调用不再等它,任务转入后台继续运行;已在后台或已结束时直接应答其状态,发起方无法不再等它的任务(例如 AgentSwarm 的成员)回复 40933 |
task.watch、task.stop 与 task.background 成功时,task 是任务此刻的状态(形状见下文 task 帧,不含 type、session_id、agent_id 与 event_created_at)。同一个任务的请求按到达顺序逐个处理,因此在 task.watch 尚未应答时发出的 task.unwatch 会在它之后生效;不同任务之间、以及它们与其他命令之间互不等待。task.watch 成功时先应答 code 0,再用一个 task.output 帧发送最后 tail_bytes 字节的输出(默认 32 KiB,最大 1 MiB;since_offset 落在这段范围内时只发它之后的部分;没有可发送的输出时 text 为空),之后推送实时输出;已结束的任务同样可以 watch。错误:40001 帧格式错误(含 tail_bytes 超出范围),40401 会话不存在,40406 该 agent 下没有这个任务,40933 该任务不能转入后台(应答仍带任务状态),50001 内部错误,50003 输出无法读取。
事件
全局事件是事件帧 { "type", "session_id"?, "timestamp", "payload" },type 即事件类型;会话帧是平铺帧 { "type", "session_id", "agent_id", ... }。按投递范围分两类:
- 全局事件:发送到每个已建立连接,无需订阅——
session.meta.updated、event.session.created、event.session.archived、event.session.restored、event.session.work_changed、event.session.status_changed、event.workspace.*、event.config.*、event.model_catalog.*。 - 会话帧:只发给用
subscribe订阅了该会话的连接,且只包含其接收的 agent——turns、turns.removed、turns.failed、turn.*、item.*与notice(见 对话协议),以及task.list、task、agent、usage、goal、todo;interaction帧发给该会话的所有订阅者。task.output只发给用task.watch订阅了该任务输出的连接。
以下全局生命周期事件可以让跨工作区概览免掉逐工作区轮询。event.session.archived 在在线归档与冷归档两条路径上都会发出;其事件帧 session_id 是全局水位 __global__,真实会话 id 在 payload 里:{ "type": "event.session.archived", "workspace_id": "wd_...", "sessionId": "session_..." }(payload 字段为 workspace_id / sessionId)。已归档的会话被恢复时发出 event.session.restored,路径、事件帧和 payload 字段都与 event.session.archived 相同。event.workspace.created / updated 携带完整工作区对象({ id, root, name, created_at, last_opened_at, session_count }——会话创建触碰工作区时也会发 updated),event.workspace.deleted 携带 { "workspace_id", "root" }。这些事件只覆盖本服务进程内的变更;其他进程(例如写同一 home 目录的 CLI)的变更要等索引 reconcile(约一分钟)才可见,因此概览客户端应保留低频兜底轮询。目前没有会话删除事件。
每个 agent 正在跑的任务——Shell 命令(前台与后台)、subagent(含 swarm 成员)及其他异步工作——由 task.list 与 task 两种平铺帧同步,和 interaction 一样不回放。连接开始接收某个 agent 的任务时(subscribe 的 agent_ids 中列出、且此前未接收的 agent),先收到一帧 { type: "task.list", session_id, agent_id, tasks },tasks 是该 agent 此刻正在跑的全部任务,客户端用它整份替换本地列表;之后每次变化收到一帧 { type: "task", session_id, agent_id, event_created_at, ...任务状态 },列出时尚未加入会话的 agent 直接从 task 帧开始。任务状态为 { task_id, kind: "shell" | "subagent" | "other", status: "running" | "ended", outcome?, phase?, detached, description?, child_agent_id?, parent_tool_call_id?, swarm_index?, command?, started_at?, ended_at?, result_summary?, error?, state_reason?, model?, thinking? },每帧都携带完整状态。detached 表示发起它的工具调用已不再等它,即后台任务;outcome(仅已结束的任务)为 completed / failed / timed_out / killed / lost;phase(仅运行中的 subagent)为 working / suspended,挂起原因在 state_reason;child_agent_id 是 subagent 任务的 agent id;swarm_index 是 swarm 成员在其 swarm 中的序号;command 是 Shell 任务的命令。任务结束时推送它最后一帧 task(status: "ended"),之后不再出现在 task.list 里:已结束任务的结果在会话历史中(工具结果与完成通知),需要精确的最终状态时对它发送 task.watch,应答带有其状态。任务与轮次互相独立:撤销轮次不影响任务。任务输出单独推送,形状为 { type: "task.output", session_id, agent_id, task_id, offset, text },offset 是 text 在任务输出中的 UTF-8 字节偏移。
Agent 自身的状态由另外四种平铺帧同步,每帧都携带完整的值,客户端整份替换本地副本;和任务帧一样不回放。连接开始接收某个 agent 时(规则同 task.list),先收到当前的 agent、usage(该 agent 有模型上下文时)、goal(仅主 agent)与 todo 帧,之后每当某个值变化就再收到对应的帧;已列出、之后才加入会话的 agent 也会用这几种帧通告自己。订阅会话时如果主 agent 还不存在,服务端会先创建它,所以订阅之后总能收到主 agent 的这几种帧。四种帧都是 { type, session_id, agent_id, event_created_at, ... }:
agent:{ status: "idle" | "running", compacting, model?, thinking?, permission_mode?, plan_mode, swarm_mode, tower_mode }。agent 处理某一轮时status为running,不处理时为idle。正在压缩该 agent 的上下文时compacting为true,无论是否在某一轮之中。正在运行的轮次以及模型请求失败后的重试状态随对话帧下发。compacting和三个模式字段都是布尔值。usage:{ context_tokens, max_context_tokens? }。只有最新值有意义,因此上下文增长期间服务端每秒最多发送几次。goal:{ goal? },会话没有目标时省略goal,否则为{ objective, status: "active" | "paused" | "blocked" | "complete", completion_criterion?, turns_used, tokens_used, wall_clock_ms }。todo:{ items: [{ title, status: "pending" | "in_progress" | "done" }] },取自 agent 的待办存储,因此会跟随撤销回退,重启后也能恢复。
审批与提问以 interaction 帧下发,发给会话的所有订阅者:{ type: "interaction", session_id, agent_id, event_created_at, interaction_id, kind: "approval" | "question", status: "pending" | "ended", request, response?, outcome?, ended_at?, tool_call_id? }。agent_id 是发起交互的 Agent,tool_call_id 是等待中的工具调用,它的 tool_call 条目带有相同的 interaction_id。审批的 request 为 { tool_name, action, tool_input_display?, expires_at },expires_at 为发起后 24 小时;提问的 request 为 { questions },包含 1–4 个 { id, question, header?, body?, options, multi_select?, allow_other?, other_label?, other_description? } 条目,每个条目带 2–4 个 { id, label, description? } 形式的 options——multi_select 允许选择多个选项,allow_other 允许自由文本回答。用 POST /api/v1/sessions/{session_id}/interactions/{interaction_id} 答复交互。交互结束时——被答复,或因所在的轮次结束而取消——最后一帧带上 status: "ended"、ended_at、outcome(approved / rejected / cancelled / answered / dismissed)和 response:审批为 { decision, scope?, feedback?, selected_label? },已回答的提问为 { answers, method? },其中 answers 把每个问题的文本映射到对应的回答。
断线恢复
订阅不会跨断线保留。重连后对每个会话重新发送 subscribe:每个 agent 会重新从一帧携带最新一页的 turns 开始;应答之后会补发待处理的交互,并重新收到各 agent 的 task.list、agent、usage、goal 与 todo 帧。任务输出的订阅同样会丢失:重新发送 task.watch,并把 since_offset 设为已有输出的末尾。断线期间错过的全局事件不会回放,请通过 REST(例如 GET /api/v1/sessions)刷新本地维护的列表。
对话协议
一个 agent 的对话是一组轮次,每个轮次是一组有序的条目。轮次与条目都由该 agent 已持久化的会话记录投影而来,因此 REST 分页、turns 帧与重启后的重新读取看到的是同样的轮次和同样的 id;唯一只存在于内存里的,是运行中的步骤和工具正在产生的内容。时间均为 ISO 8601 字符串。
轮次为 { turn_id, ordinal, kind, status, outcome?, end_reason?, error?, retry?, turn_number?, started_at, ended_at?, duration_ms?, usage?, steps, items }:
turn_id在会话内唯一且不会复用:撤销之后新开的轮次即使沿用被撤销轮次的ordinal,也会得到新的 id。ordinal是该轮在 agent 当前历史中的位置,决定轮次顺序;更早的分页用before_ordinal读取。turn_number是引擎的轮次编号,供文件历史接口使用。kind为agent;轮次之间只承载一个system条目的轮次为system,即完成的上下文压缩,或分叉出的 agent 开头的分叉分界。system轮次不会处于running,实时推送时连续发送turn.started、item.ended与turn.ended。status为running或ended;agent 不运行的轮次(例如被 hook 拒绝的提示词)一出现就是ended。结束的轮次带outcome:completed;interrupted,end_reason为user_cancelled(用户停止)或aborted(因其他原因中止,例如运行中服务端停止);或failed,end_reason为error、max_steps、filtered(输出被服务商的内容过滤拦截)或blocked(输入被 hook 或策略拦下)。失败的轮次带error,形如{ code, message, name?, status_code?, request_id?, retryable? }。- 运行中的轮次在模型请求失败、等待重试时带
retry,形如{ attempt, next_attempt, max_attempts, delay_ms, error: { name, message, status_code? } },attempt是刚失败的那一次。下一步开始、一步结束或该轮结束时清除。 steps按index列出已结束的步骤(模型请求),形如{ index, outcome, started_at, ended_at?, finish_reason?, usage? }。步骤的outcome为completed、interrupted或failed;usage为{ input_other, output, input_cache_read, input_cache_creation }。轮次的usage是各步骤之和。
每个条目都有 { item_id, type, step_index?, status, outcome?, created_at, debug? }。条目按出现的先后排列,结束的条目除下文另有说明外 outcome 为 completed。服务端以 KIMI_CODE_DEBUG=1 运行时,每个已结束步骤的最后一个条目带 debug:{ finish_reason?, usage?, timing? },描述该步骤的模型请求;timing 在有测量值时包含 first_token_ms、stream_ms、request_build_ms、server_first_token_ms、server_decode_ms、client_consume_ms 与 client_blocked_ms。步骤结束时该条目会以 item.ended 再次下发:
user_message:{ prompt_ids, placement: "opener" | "steer", origin, text, attachments, skills, metadata? }。prompt_ids列出这条输入承载的 prompt id——包括打包技能提交和技能激活带的prompt_id——客户端可据此撤下本地的乐观气泡;系统触发的输入为空数组。origin为{ kind: "user" }、{ kind: "skill", name, path?, args? }、{ kind: "plugin_command", plugin_id, command, args? }、{ kind: "cron", job_id, schedule, recurring, coalesced_count, stale }、{ kind: "hook", hook_event }、目标续跑的{ kind: "goal" }、{ kind: "retry" }或{ kind: "system" }。text用换行拼接可见的文本块,不含打包技能的说明、提示词 hook 的输出、提示模型读取附件文件的说明和图片压缩说明;重试和内部触发的输入为空串。attachments按顺序列出输入中的文件和媒体,形如{ kind: "image" | "video" | "audio" | "file", file_id?, url?, name?, media_type?, size?, ordinal }:上传的文件带file_id,内联和远程媒体带url,服务端存储的媒体在分页中以data:URL 下发,按服务端本地路径附加的文件只带name、media_type和size。skills列出随输入激活的技能,形如{ name, path?, args? };metadata原样回显提交时的metadata。CLI 的 shell 命令(!)和它的输出以原始文本出现在origin: { kind: "system" }的user_message中,各自单独成一个已结束的轮。assistant_message:{ text }。reasoning:{ text, started_at, duration_ms? };duration_ms是思考输出的时长,条目结束后才有。隐藏的思考不会下发。tool_call:{ item_id: 工具调用 id, name, stage?, input?, input_text?, display?, output?, media?, error?, note?, fields?, task_id?, interaction_id?, agent_refs?, started_at, ended_at? }。调用运行时,模型流式生成参数期间stage为input(input_text为参数原文),等待审批时为awaiting_approval,其余时候为executing;output流式追加工具的实时输出,fields为 handler 最新字段快照组成的 JSON 对象。结束后output为结果文本,media列出结果中的图片、视频和音频,形如{ kind, file_id?, url?, media_type? };结果为错误时outcome为failed,带error而不带output;该轮在产生结果前结束时为interrupted。note是工具随结果附给模型的补充说明,例如ReadMediaFile读取图片时的大小和尺寸。这次调用的工作以后台任务运行时(一开始就在后台,或之后被转到后台),会带上task_id;任务离开task.list之后,仍可以用它发task.watch、task.stop。前台运行中的调用,通过任务的parent_tool_call_id找到对应的任务。interaction_id关联为该调用发起的审批或提问,其内容随interaction帧下发;agent_refs列出该调用启动的 subagent,形如{ agent_id, role: "child" | "member", swarm_index?, task_id? }。ExitPlanMode调用带display:{ kind: "plan_review", plan, path?, options: [{ label, description }], review: { state: "pending" | "approved" | "rejected" | "cancelled", selected_option?, feedback? } }。notification:{ notification_id, title, body, severity: "info" | "warning" | "error", notification_type, source: { kind, id }, task_id?, agent_id?, output?: { file?, preview?, bytes?, truncated? }, answer?: { answers, note? } },投递进对话的后台任务通知。answer是用户对后台提问的回答:answers把每个问题映射到它的回答,note是可选的备注。system:完成的上下文压缩为{ kind: "compaction", trigger: "manual" | "auto", instruction?, tokens_before?, tokens_after?, compacted_count?, summary? },在一轮运行中途完成的压缩放在该轮内;{ kind: "fork_boundary", source: "btw" | "fork", forked_from: { agent_id } }位于从其他 agent 分叉出的 agent(例如侧边对话)的对话开头,分叉时继承的对话不显示。被取消或失败的压缩不在对话中留下任何内容。
连接开始接收某个 agent 时,先收到 { type: "turns", session_id, agent_id, event_created_at, turns, has_more },携带最近 10 个轮次,与 REST 分页一样不超过 1 MiB,包括运行中的轮次及其到此刻为止的内容。该 agent 的对话无法加载时,改为收到 { type: "turns.failed", session_id, agent_id, event_created_at, code, msg }——例如 agent 不在该会话中时为 40401,或 agent 关闭后被重新加载时恢复失败——该 agent 仍保持订阅。之后再收到的 turns 帧会替换客户端最新的这些轮次,agent 关闭后被重新加载时会再发一次。之后:
{ type: "turns.removed", session_id, agent_id, event_created_at, turn_ids }按 ordinal 升序列出离开对话的轮次:撤销之后是被撤销的轮次(与撤销接口响应的removed_turn_ids一致),清空上下文之后是全部轮次。客户端按turn_id删除;撤销接口的响应与该帧到达的先后顺序不固定。turn.started与turn.ended携带不含items的turn,客户端用它替换本地的轮次并保留已有条目;已结束的轮次被修正时会再发一次turn.ended。turn.updated携带turn_id、每个已结束步骤一次的step(按index写入steps),以及替换该轮重试状态的retry;不带retry时清除重试状态。item.started与item.ended携带turn_id与完整的item,客户端用它替换本地同item_id的条目,本地没有的条目追加到该轮末尾。不流式产生的条目(例如user_message)只发item.ended。流式产生的条目保持running,直到所在步骤落盘后,以落盘后的值发唯一一次item.ended;同一步骤里下一段内容开始时,前面的条目不会提前结束,客户端以最后一个块判断是否仍在输出。item.updated携带turn_id、item_id与set,即运行中的tool_call发生变化的字段,浅合并到条目上。item.delta携带turn_id、item_id、field(text、input_text或output)与delta,是追加到该字段的文本。item.removed携带turn_id与item_id:一个不会完成的运行中条目,例如请求重试导致该步骤重新开始。notice为{ level: "info" | "warning" | "error", title, detail?, code? },是 agent 实时发出的警告或错误,例如上下文压缩未完成时的compaction.cancelled。通知不属于轮次,订阅时也不补发。
事件可能重复 turns 帧中已有的内容;按替换的方式应用即可保证结果正确。
二进制与流式端点
以下端点返回二进制流而非 JSON 载荷,各端点的 HTTP 能力并不相同:
| 方法与路径 | 说明 | Range 分段(206) | ETag / 304 |
|---|---|---|---|
GET /api/v1/files/{file_id} | 下载已上传文件 | 支持 | 不支持(会发送 etag 头,但不处理 If-None-Match) |
GET /api/v1/sessions/{session_id}/fs/{path}:download | 下载会话工作区文件 | 支持 | 支持 |
GET /api/v1/fs:content | 读取本机任意文件(仅受 token 保护,谨慎暴露端口) | 支持 | 支持 |
POST /api/v1/sessions/{session_id}/export | 导出会话与诊断信息(zip 流) | 不支持 | 不支持 |
错误语义也不相同:GET /api/v1/files/{file_id}、GET /api/v1/fs:content 与会话 :download 对失败返回真实 4xx / 500 状态码,响应体仍是标准 响应信封。会话导出仍以 HTTP 200 返回错误信封。普通 JSON RPC 端点继续保持几乎总是 200 的约定,客户端仍需检查信封中的 code。