路径
POST /task
公网入口 https://agentapi.kira.art/task。浏览器直连,不经 kira-be 透传。
认证
eitherAuth() 中间件,二选一:
| 模式 | Header | 说明 |
|---|---|---|
| 客户端 | Authorization: Bearer <Supabase JWT> | hono/jwk 验 ES256,userId = jwtPayload.sub |
| 服务器到服务器 | X-Internal-Key: <INTERNAL_KEY> | 内部调用方(user 归因走 W3C Baggage) |
请求 Body
由StreamingRequestSchema(src/hono/agent/models.ts)校验:
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
message | ResponseMessageSchema | 是 | — | 本轮用户消息:{ id, role: "user"|"assistant", parts?: any[] } |
threadId | string | 是 | — | 目标线程 ID |
model | "lite" | "nova" | "ultra" | 否 | "lite" | 期望的 KiraModel tier |
anchorMessageId | string | 否 | — | rewind 锚点:删除该消息之后的所有 message / version / 资源 |
响应
- 201 Created
- 409 Conflict
成功启动后台 agent run,返回新
taskId。客户端随后用它打开 GET /stream/:taskId。状态码
| 码 | 含义 |
|---|---|
201 | 启动成功,返回 { taskId } |
409 | thread 已在跑,返回 { taskId, reason: "running" } |
401 | 缺少有效 JWT / jwtPayload.sub |
404 | user_profiles 查不到该用户 |
500 | 拉取 user profile 失败 |
503 | 实例正在 graceful drain(instance draining) |
处理流程
抢 dedup 锁
acquireLock(threadId, "<instanceId>:<newTaskId>")(SET NX agent:lock:{threadId} EX 60)。抢不到 → 读现役锁值解析出 taskId,返回 409 { taskId, reason: "running" }。Plan 校验与 model 降级
拉
user_profiles.plan,按下表把请求的 model 收敛成 effectiveModel:| Plan | 可用 tier |
|---|---|
| free / basic | lite |
| pro / pro_year | lite, nova |
| max / max_year | lite, nova, ultra |
anchorMessageId rewind(可选)
若带
anchorMessageId,调用 rewindAfter():删除锚点 created_at 之后的 messages + thread_version 行,并清理对应 CDN assets(图片/视频/缩略图 + 用户上传 ref)与 video task(purgeVideoTasks + cdn.deleteTask)。用户消息在 run 期间不立即 upsert DB;只有
onFinish(非 aborted、有内容)才写回 messages + thread_version,并对生成的 video 通过 tasks.trigger(@trigger.dev/sdk/v3)在 kira-video-worker 上触发对应的 Trigger.dev task(publishVideoTask,按 toolName[:provider] 路由到 video-* task id)。示例
源
src/hono/agent/index.ts:85(handler)、rewindAfter at :658、src/hono/agent/models.ts:65(StreamingRequestSchema)