Job Hub API
接口说明
Job 代表一个完整任务,step 代表任务里的阶段状态。创建 job 后,后续主要通过 step 上报自动推进 job 进度;最终 step 映射到 100% 时,会用当前 step output 写入 job output 并完成 job。
/api/jobs/:jobId创建或更新 job
用于初始化 job,或特殊情况下手动修正整体状态。日常执行过程建议通过 steps 接口推进。
请求 body
{
"name": "整理文章",
"description": "抓取网页并生成摘要",
"input": {
"url": "https://example.com/article"
},
"metadata": {
"traceId": "trace_123"
}
}curl -X PUT https://job-hub.kokoship.com/api/jobs/demo-job \
-H 'content-type: application/json' \
-d '{"name":"整理文章","description":"抓取网页并生成摘要","input":{"url":"https://example.com/article"}}'/api/jobs/:jobId/steps/:stepKey创建或更新 step
根据 jobId + stepKey upsert 一个 step。jobId、stepKey、stepName 和 jobProgressStart/jobProgressEnd 应由主逻辑/orchestrator 分配后传给具体执行逻辑,worker 内不要重新生成。这个接口同时用于创建 step、更新 step 进度和 step 完成上报;同一个 stepKey 重复 PUT 会更新同一条 step。progress 是 step 自身进度;jobProgressStart/jobProgressEnd 用于换算整体 job 进度,不落库。
请求 body
{
"stepName": "提取正文",
"status": "running",
"progress": 50,
"jobProgressStart": 0,
"jobProgressEnd": 30,
"message": "正在提取正文"
}响应示例
{
"stepId": "uuid",
"jobId": "demo-job",
"stepKey": "extract",
"stepName": "提取正文",
"status": "running",
"progress": 50,
"message": "正在提取正文",
"createdAt": "2026-06-17T10:00:03.000Z",
"updatedAt": "2026-06-17T10:00:03.000Z",
"startedAt": "2026-06-17T10:00:03.000Z"
}请求示例:step 完成,job progress 到 30
{
"status": "completed",
"progress": 100,
"jobProgressStart": 0,
"jobProgressEnd": 30,
"output": {
"content": "正文..."
}
}请求示例:step 完成,job progress 到 100
{
"stepName": "生成最终结果",
"status": "completed",
"progress": 100,
"jobProgressStart": 80,
"jobProgressEnd": 100,
"output": {
"summary": "...",
"tags": ["AI"]
}
}请求示例:step 失败并终止 job
{
"stepName": "提取正文",
"status": "failed",
"progress": 40,
"message": "目标网页无法访问",
"failJob": true
}curl -X PUT https://job-hub.kokoship.com/api/jobs/demo-job/steps/extract \
-H 'content-type: application/json' \
-d '{"stepName":"提取正文","status":"running","progress":50,"jobProgressStart":0,"jobProgressEnd":30,"message":"正在提取正文"}'/api/jobs/:jobId获取单个 job
返回 job 核心信息、当前 running step 和最终 output。默认不返回完整 steps 列表。
curl https://job-hub.kokoship.com/api/jobs/demo-job/api/jobs/:jobId?stepKey=:stepKey获取 job 并带出指定 step
轻量探测接口。返回 job 核心信息、currentStep,并额外返回指定 stepKey 对应的 step。适合主流程只关心某个上游 step output 的场景。
响应示例
{
"jobId": "demo-job",
"status": "running",
"progress": 30,
"currentStep": null,
"step": {
"stepId": "uuid",
"jobId": "demo-job",
"stepKey": "extract",
"stepName": "提取正文",
"status": "completed",
"progress": 100,
"output": {
"content": "正文..."
},
"durationMs": 7000
}
}curl 'https://job-hub.kokoship.com/api/jobs/demo-job?stepKey=extract'/api/jobs/:jobId?include=steps获取 job 详情
返回 job 核心信息、currentStep、output 和完整 steps timeline。这个接口适合详情页和调试,不建议主流程高频探测时使用。
curl 'https://job-hub.kokoship.com/api/jobs/demo-job?include=steps'/api/jobs获取 job 列表
返回 job 列表,按创建时间倒序排列,避免运行中任务因为频繁更新而在列表中跳动。支持 status=running|completed|failed 过滤。
curl https://job-hub.kokoship.com/api/jobs?status=running/api/jobs/:jobId/steps获取 step 列表
返回指定 job 的所有 steps,按创建时间升序排列。
curl https://job-hub.kokoship.com/api/jobs/demo-job/steps/api/jobs/:jobId/steps/:stepKey获取单个 step
返回指定 stepKey 对应的 step。下游 step 如果需要读取上游 step output,可以用这个接口精准读取。
curl https://job-hub.kokoship.com/api/jobs/demo-job/steps/extract/api/jobs/:jobId删除 job
删除 job,并级联删除该 job 下的 steps。
响应示例
{
"ok": true
}curl -X DELETE https://job-hub.kokoship.com/api/jobs/demo-job/api/jobs清理所有 jobs
删除所有 jobs,并级联删除所有 steps。这个接口用于清理任务列表,请谨慎使用。
响应示例
{
"ok": true
}curl -X DELETE https://job-hub.kokoship.com/api/jobs进度规则
step.progress 表示 step 自身进度,不等于 job.progress。
当请求同时包含 progress、jobProgressStart、jobProgressEnd 时,服务端计算:jobProgressStart + progress / 100 * (jobProgressEnd - jobProgressStart)。
jobs.progress 只前进不后退,使用 max(existing, calculated)。
step 更新只要包含 message,服务端会同步刷新 jobs.message,dashboard 顶部显示最近一次上报的状态信息。
计算结果达到 100 时,当前请求必须包含 output;服务端会写入 step.output 和 jobs.output,并完成 job。
具体执行逻辑应避免过密或重复上报。不要在 tight loop 中每处理一小块就 PUT,也不要反复发送相同的 progress/message。建议只在阶段切换、进度有明显变化(例如至少 5%)、完成或失败时上报。
失败处理
step 失败时,使用同一个 step upsert 接口上报 status=failed,并把简短失败原因放在 message 中。
默认情况下,step failed 只会标记当前 step 失败,不会自动让整个 job 失败,因为某些 step 可能可重试、可跳过或可降级。
如果需要终止整个 job,传 failJob=true。服务端会把 jobs.status 更新为 failed,并把 step 的 message 同步到 jobs.message。
job failed 时不会强制 progress=100,也不会自动写 jobs.output。
stepKey 和 step 依赖
stepKey 是一个 job 内部的 step 幂等键,应由主逻辑/orchestrator 分配并通过路径传入,要求同一个 job 内唯一。重复 PUT 同一个 stepKey 会更新同一条 step。
stepName 是给人看的步骤名称,必须由主逻辑/orchestrator 在请求体中传入。具体 step 执行逻辑应复用主逻辑传入的 stepKey 和 stepName,不应自行随机生成。
如果 stepKey 是动态生成的,也应由主逻辑生成,并在重试或恢复时复用同一个 stepKey,避免产生重复 step。
jobProgressStart / jobProgressEnd 也建议由主逻辑分配,因为只有主逻辑知道每一步在整体 job 进度中的位置。
把 jobId、stepKey、stepName、jobProgressStart 和 jobProgressEnd 交给具体执行逻辑时,应把它们当成 workflow 契约复用。这样失败重试、进程恢复和多次上报都会落到同一条 step 记录上。
为了让 dashboard 保持轻快,也为了减少数据库写入压力,step worker 应主动去重:如果 progress 和 message 没有变化,就不需要再次上报。
Job Hub 不负责调度或唤醒下一个 step。step 的执行顺序、依赖传递、重试和分支逻辑由外层 workflow/orchestrator 负责。
下一个 step 如果需要上一个 step 的 output,可以使用 GET /api/jobs/:jobId?stepKey=:stepKey 或 GET /api/jobs/:jobId/steps/:stepKey 精准读取。
字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| job.output | object | 最终结果,由最终 step 映射到 100% 时自动写入,或 PUT job 时手动写入 |
| step.output | object | 当前 step 的输出结果 |
| message | string | job 或 step 当前状态的人类可读描述;status=failed 时用于放简短失败原因 |
| failJob | boolean | step failed 时可传;true 表示同时把 job 标记为 failed |
| jobProgressStart / jobProgressEnd | number | 请求参数,用于把 step progress 换算成 job progress,不落库 |
| stepKey | string | 路径参数,由主逻辑分配的 job 内 step 幂等键 |
| stepName | string | 请求 body 必填,由主逻辑传入的可读步骤名称 |
| progress 上报频率 | 约定 | 由具体执行逻辑控制;建议阶段边界、至少约 5% 变化、完成或失败时上报,避免重复 PUT 相同 progress/message |
| currentStep | object | null | 当前最新 running step;默认 GET job 时返回 |
| step | object | null | 仅 GET job 时传 stepKey 参数返回,表示指定 stepKey 的 step |
| steps | array | 仅 include=steps 或 steps 列表接口返回 |