# Tareas asíncronas

> Cómo LMSP ejecuta generaciones largas como tareas persistentes, con creación de tareas, la máquina de estados de la tarea, cancelación idempotente, flujos de eventos y políticas de reinicio para las tareas sin terminar.

Source: https://madeforagent.com/es/lmsp/1.0/tasks/
Language: es
Specification: LMSP 1.0 (draft)
Updated: 2026-11-08

## 7.1 Crear una tarea {#create}

Un cliente crea una tarea enviando por POST la solicitud de respuesta que quiere ejecutar, envuelta en un sobre de tarea. Se recomienda una cabecera `Idempotency-Key` ([sección 9.2](https://madeforagent.com/es/lmsp/1.0/common-rules.md#idempotency)).

```http
POST /lmsp/v1/tasks
Authorization: Bearer <token>
Idempotency-Key: 01J8M7C4Y3N5P8R2T6V9X1Z4BH
```

```json
{
  "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"
}
```

| Campo | Obligatorio | Significado |
| --- | --- | --- |
| `type` | Sí | `response`, el único tipo de tarea en 1.0. |
| `input` | Sí | Una solicitud de respuesta, exactamente igual que para `POST /lmsp/v1/responses`. Su campo `stream` se ignora. |
| `on_restart` | No | `fail` (el valor por defecto), `retry` o `resume`. Consulta la [sección 7.5](https://madeforagent.com/es/lmsp/1.0/tasks.md#restart). |

El servicio **DEBE** persistir la tarea antes de responder. Después devuelve:

```http
HTTP/1.1 202 Accepted
```

```json
{
  "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
}
```

| Campo de la tarea | Significado |
| --- | --- |
| `id` | Identificador de la tarea, como `task_...`. |
| `object` | Siempre `"task"`. |
| `type` | `response`. |
| `status` | El estado actual ([sección 7.2](https://madeforagent.com/es/lmsp/1.0/tasks.md#states)). |
| `created_at`, `updated_at` | Horas en segundos desde la época Unix. |
| `response_id` | Id de la respuesta que produce la tarea. Se asigna al crear la tarea. |
| `events_url` | Ruta del flujo de eventos. Presente cuando la capacidad `event_resume` es `true`. |
| `on_restart` | La política de reinicio de la tarea. |
| `response` | El objeto de respuesta una vez que `status` es `succeeded`; en caso contrario, `null`. |
| `error` | Un objeto de problema ([sección 9.3](https://madeforagent.com/es/lmsp/1.0/common-rules.md#errors)) cuando `status` es `failed`; en caso contrario, `null`. |

`GET /lmsp/v1/tasks/{task_id}` devuelve el objeto de tarea. Los clientes que no usan flujos de eventos consultan periódicamente este endpoint. Un id desconocido produce `404` con `task_not_found`. Una tarea terminada tiene este aspecto:

```json
{
  "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 Máquina de estados {#states}

```text
queued --> loading --> running --> succeeded
  |           |           |
  |           |           +--> failed
  |           |           +--> cancelling --> cancelled
  |           +--------------> failed
  +--------------------------> cancelled
```

| Estado | Significado | Estados siguientes |
| --- | --- | --- |
| `queued` | Aceptada y persistida, a la espera de empezar. | `loading`, `cancelled`, `failed` |
| `loading` | Se está cargando el modelo. | `running`, `cancelling`, `failed` |
| `running` | El modelo está generando. | `succeeded`, `failed`, `cancelling` |
| `cancelling` | Se solicitó la cancelación y el backend aún no se ha detenido. | `cancelled` |
| `succeeded` | Final. La respuesta está completa. | ninguno |
| `failed` | Final. | ninguno |
| `cancelled` | Final. | ninguno |

Los estados terminales son `succeeded`, `failed` y `cancelled`. Una tarea en estado terminal **NO DEBE** volver a cambiar. Una tarea cuya respuesta termina como `incomplete`, por ejemplo al llegar al límite de tokens, está `succeeded`.

Todas las transiciones son atómicas, así que una tarea nunca está a la vez cancelada y completada. Gana la transición que se confirme primero.

## 7.3 Cancelación {#cancel}

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

El servicio devuelve `200 OK` y el objeto de tarea actual. Una tarea `queued` pasa a `cancelled` de inmediato. Una tarea `loading` o `running` pasa a `cancelling` hasta que el backend se haya detenido, y después a `cancelled`.

La cancelación **DEBE** ser idempotente. Cancelar una tarea que ya está `cancelling` o `cancelled` devuelve la tarea actual y no produce ningún error nuevo.

Cancelar una tarea que ya está `succeeded` o `failed` se responde con `409` y `task_not_cancelable`. Un id desconocido produce `404` con `task_not_found`.

## 7.4 Flujos de eventos {#events}

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

Este endpoint es opcional. Está disponible cuando la capacidad `event_resume` es `true`.

- Los eventos son los eventos de respuesta de la [sección 6.3](https://madeforagent.com/es/lmsp/1.0/responses.md#streaming), correspondientes a la respuesta que produce la tarea. La numeración y la reanudación siguen la [sección 6.4](https://madeforagent.com/es/lmsp/1.0/responses.md#reconnection).
- El flujo empieza con `response.created`, que se registra cuando se acepta la tarea. Termina con un único evento final que corresponde al resultado: `response.completed`, `response.incomplete`, `response.failed` o `response.cancelled`.
- Un cliente que se conecta tarde recibe primero los eventos que se perdió y después los eventos en vivo. El servicio cierra el flujo después del evento final.
- Los eventos se conservan durante un período de retención ([sección 11.2](https://madeforagent.com/es/lmsp/1.0/persistence.md#rules)). Los eventos más antiguos producen `410 Gone` con `event_history_expired`.

## 7.5 Semántica de reinicio {#restart}

`on_restart` indica qué ocurre con una tarea sin terminar cuando el servicio se reinicia:

| Valor | Comportamiento |
| --- | --- |
| `fail` | El valor por defecto. El servicio marca la tarea sin terminar como `failed`, con el código de error `server_restarted`. |
| `retry` | El servicio ejecuta la tarea de nuevo desde el principio. |
| `resume` | El servicio continúa desde una instantánea. Esto solo se permite cuando el backend admite explícitamente instantáneas reanudables. En caso contrario, la solicitud de creación se rechaza con `400` y `unsupported_capability`. |

Una tarea que está `cancelling` cuando el servicio se reinicia completa su cancelación y pasa a `cancelled`, sea cual sea su política.

`retry` no se recomienda como valor por defecto, porque la tarea puede haber ejecutado ya herramientas o producido efectos secundarios externos. Un cliente que elige `retry` **DEBE** combinarlo con un `Idempotency-Key` y hacer que sus llamadas a herramientas sean idempotentes.
