非同步任務

7.1 建立任務

客戶端透過傳送它想要執行的回應請求來建立任務,請求要包在任務信封中。建議攜帶 Idempotency-Key 請求標頭(第 9.2 節)。

POST /lmsp/v1/tasks
Authorization: Bearer <token>
Idempotency-Key: 01J8M7C4Y3N5P8R2T6V9X1Z4BH
{
  "type": "response",
  "input": {
    "model": "qwen3:14b-q4_k_m",
    "input": [
      {
        "type": "message",
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "Write a long report."
          }
        ]
      }
    ]
  },
  "on_restart": "fail"
}
欄位 必需 含義
type 是 response,1.0 中唯一的任務型別。
input 是 一個回應請求,與 POST /lmsp/v1/responses 的請求相同。其中的 stream 欄位會被忽略。
on_restart 否 fail(預設)、retry 或 resume。參見第 7.5 節。

服務必須先持久化任務,再作出應答。隨後回傳:

HTTP/1.1 202 Accepted
{
  "id": "task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC",
  "object": "task",
  "type": "response",
  "status": "queued",
  "created_at": 1794200100,
  "updated_at": 1794200100,
  "response_id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW",
  "events_url": "/lmsp/v1/tasks/task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC/events",
  "on_restart": "fail",
  "response": null,
  "error": null
}
任務欄位 含義
id 任務識別碼,例如 task_...。
object 始終為 "task"。
type response。
status 當前狀態(第 7.2 節)。
created_at、updated_at 時間,自 Unix 紀元起的秒數。
response_id 該任務所產生的回應的 id,在建立任務時分配。
events_url 事件流的路徑。event_resume 能力為 true 時存在。
on_restart 該任務的重啟策略。
response status 為 succeeded 後是回應物件,否則為 null。
error status 為 failed 時是一個 problem 物件(第 9.3 節),否則為 null。

GET /lmsp/v1/tasks/{task_id} 回傳任務物件。不使用事件流的客戶端輪詢該介面。未知的 id 回傳 404 和 task_not_found。已結束的任務如下所示:

{
  "id": "task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC",
  "object": "task",
  "type": "response",
  "status": "succeeded",
  "created_at": 1794200100,
  "updated_at": 1794200162,
  "response_id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW",
  "events_url": "/lmsp/v1/tasks/task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC/events",
  "on_restart": "fail",
  "response": {
    "id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW",
    "object": "response",
    "created_at": 1794200100,
    "status": "completed",
    "model": "qwen3:14b-q4_k_m",
    "output": [
      {
        "id": "msg_01J8M8R6A2C5E8G1J4M7P0S3VY",
        "type": "message",
        "role": "assistant",
        "content": [
          {
            "type": "output_text",
            "text": "Local model services make on-device inference a shared, discoverable utility..."
          }
        ]
      }
    ],
    "usage": {
      "input_tokens": 12,
      "output_tokens": 1480,
      "total_tokens": 1492
    },
    "error": null,
    "incomplete_details": null
  },
  "error": null
}

7.2 狀態機

queued --> loading --> running --> succeeded
  |           |           |
  |           |           +--> failed
  |           |           +--> cancelling --> cancelled
  |           +--------------> failed
  +--------------------------> cancelled
狀態 含義 後續狀態
queued 已接受並持久化,等待開始。 loading、cancelled、failed
loading 正在載入模型。 running、cancelling、failed
running 模型正在生成。 succeeded、failed、cancelling
cancelling 已請求取消,後端尚未停止。 cancelled
succeeded 終態。回應已完成。 無
failed 終態。 無
cancelled 終態。 無

終態只有 succeeded、failed 和 cancelled。處於終態的任務不得再發生變化。回應以 incomplete 結束的任務(例如達到 token 上限)是 succeeded。

每次狀態轉換都是原子的,因此任務不會既被取消又已完成,先提交的轉換生效。

7.3 取消

POST /lmsp/v1/tasks/{task_id}/cancel

服務回傳 200 OK 和當前任務物件。queued 任務立即變為 cancelled;loading 或 running 任務先變為 cancelling,直到後端停止後再變為 cancelled。

取消操作必須冪等:重複取消已處於 cancelling 或 cancelled 的任務,仍回傳當前任務,不產生新錯誤。

取消已經 succeeded 或 failed 的任務,回傳 409 和 task_not_cancelable。未知的 id 回傳 404 和 task_not_found。

7.4 事件流

GET /lmsp/v1/tasks/{task_id}/events
Accept: text/event-stream

該介面是可選的,在 event_resume 能力為 true 時可用。

  • 事件是第 6.3 節中的回應事件,對應該任務所產生的回應。序號與恢復規則遵循第 6.4 節。
  • 事件流以 response.created 開始,它在任務被接受時記錄。流以與結果相符的一個最終事件結束:response.completed、response.incomplete、response.failed 或 response.cancelled。
  • 較晚連線的客戶端先收到自己錯過的事件,再收到即時事件。服務在最終事件之後關閉流。
  • 事件會保留一段保留期(第 11.2 節)。更早的事件回傳 410 Gone 和 event_history_expired。

7.5 重啟語義

on_restart 規定服務重啟時對未完成任務如何處理:

取值 行為
fail 預設值。服務把未完成的任務標記為 failed,錯誤碼為 server_restarted。
retry 服務從頭重新執行該任務。
resume 服務從快照繼續執行。僅當後端明確支援可恢復快照時才允許,否則建立請求會被拒絕,回傳 400 和 unsupported_capability。

服務重啟時處於 cancelling 的任務,無論其策略如何,都會完成取消並變為 cancelled。

不建議把 retry 作為預設值,因為任務可能已經執行了工具或產生了外部副作用。選擇 retry 的客戶端必須同時使用 Idempotency-Key,並使其工具呼叫冪等。