# Reglas comunes

> Reglas compartidas por todos los endpoints de LMSP, con las cabeceras de versión y las extensiones, las claves de idempotencia, el formato de error problem+json y sus códigos, y la comprobación de estado.

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

## 9.1 Versiones y extensiones {#versioning}

Cada solicitud LMSP **PUEDE** llevar estas cabeceras:

```http
LMSP-Version: 1.0
LMSP-Client: example-client/1.2.0
```

`LMSP-Version` es la versión del protocolo a la que se dirige el cliente. `LMSP-Client` identifica el software cliente con fines de diagnóstico, como `name/version`. Un servicio **NO DEBE** cambiar el comportamiento del protocolo en función de esta última.

Reglas:

- La `v1` de la ruta indica la versión mayor.
- Una solicitud que nombra una versión mayor desconocida se responde con `426 Upgrade Required` y el código de error `unsupported_protocol_version`.
- Los nuevos campos opcionales **NO DEBEN** romper la compatibilidad 1.x.
- Los servicios y los clientes **DEBEN** ignorar los campos que no conocen.
- Las extensiones privadas van en un objeto `extensions` y se nombran con notación de dominio inverso:

```json
{
  "extensions": {
    "com.example.cache": {
      "enabled": true
    }
  }
}
```

## 9.2 Idempotencia {#idempotency}

Las solicitudes que crean algo, como crear una respuesta, crear una tarea o cargar un modelo, aceptan una clave de idempotencia:

```http
Idempotency-Key: <client-generated-unique-value>
```

El servicio almacena la clave junto con un resumen criptográfico del cuerpo de la solicitud y el resultado:

- La misma clave con el mismo cuerpo devuelve el resultado original.
- La misma clave con un cuerpo distinto se responde con `409 Conflict` y `idempotency_conflict`.

Una clave se limita al cliente y al endpoint. **DEBERÍA** ser un valor único de como máximo 255 caracteres, como un ULID o un UUID. Un servicio **DEBERÍA** conservar las claves al menos 24 horas.

Un servicio **PUEDE** ignorar la clave en las solicitudes en streaming. Un cliente que necesita reintentos seguros usa una [tarea](https://madeforagent.com/es/lmsp/1.0/tasks.md).

## 9.3 Errores {#errors}

Todo error de la interfaz LMSP usa `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)):

```json
{
  "type": "urn:lmsp:error:model-not-found",
  "title": "Model not found",
  "status": 404,
  "code": "model_not_found",
  "detail": "No local model with id 'qwen3:14b-q4_k_m'",
  "request_id": "req_01J8M9S6Y4W8C3P5R1V7Z2A0DH",
  "retryable": false
}
```

| Campo | Obligatorio | Significado |
| --- | --- | --- |
| `type` | Sí | URI que identifica el tipo de error. LMSP usa `urn:lmsp:error:` seguido del código con guiones en lugar de guiones bajos. |
| `title` | Sí | Resumen breve y legible. |
| `status` | Sí | El código de estado HTTP. |
| `code` | Sí | Código de error legible por máquina, de la lista siguiente. |
| `detail` | No | Explicación legible de esta ocurrencia. **NO DEBE** contener secretos, prompts ni contenido generado. |
| `request_id` | No | Identificador de la solicitud, para correlacionarla con los registros del servicio. |
| `retryable` | Sí | Si repetir la solicitud más tarde puede tener éxito. |

Códigos de error habituales:

| Código | Estado HTTP | Reintentable | Significado |
| --- | --- | --- | --- |
| `invalid_request` | 400 | No | La solicitud está mal formada o tiene parámetros no válidos. |
| `unauthorized` | 401 | No | Falta el token, no es válido, ha caducado o se ha revocado, o un código de emparejamiento es incorrecto. |
| `forbidden` | 403 | No | El token no tiene el ámbito necesario, o falló la comprobación de `Origin` o `Host`. |
| `model_not_found` | 404 | No | Ningún modelo local tiene este id. |
| `model_not_ready` | 409 | Sí | El modelo no está cargado y no se carga bajo demanda. |
| `model_load_failed` | 500 | Sí | Falló la carga del modelo. |
| `context_length_exceeded` | 400 | No | La entrada no cabe en la ventana de contexto del modelo. |
| `unsupported_capability` | 400 o 501 | No | El modelo o el servicio no admite lo que necesita la solicitud. Un endpoint opcional no implementado responde 501. |
| `unsupported_protocol_version` | 426 | No | El servicio no admite la versión mayor solicitada. |
| `response_not_found` | 404 | No | Ninguna respuesta almacenada tiene este id. |
| `task_not_found` | 404 | No | Ninguna tarea tiene este id. |
| `task_not_cancelable` | 409 | No | La tarea ya ha terminado correctamente o con un fallo. |
| `idempotency_conflict` | 409 | No | La clave de idempotencia ya se usó con un cuerpo de solicitud distinto. |
| `event_history_expired` | 410 | No | Los eventos solicitados son anteriores al período de retención. |
| `rate_limited` | 429 | Sí | Demasiadas solicitudes. |
| `resource_exhausted` | 503 | Sí | Al dispositivo se le acabó la memoria u otro recurso. |
| `backend_unavailable` | 503 | Sí | No se puede acceder al entorno de ejecución del modelo. |
| `server_restarted` | 503 | Sí | El servicio se reinició mientras la tarea estaba sin terminar. |
| `internal_error` | 500 | Varía | Un fallo inesperado dentro del servicio. |

El campo `retryable` es el que prevalece. La columna anterior muestra el valor habitual. Un servicio **PUEDE** definir más códigos. Un cliente **DEBE** tratar un código que no conoce según su estado HTTP y su campo `retryable`.

## 9.4 Comprobación de estado {#health}

```http
GET /lmsp/v1/health
```

```json
{
  "status": "ready",
  "service_id": "svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2",
  "uptime_seconds": 86420,
  "loaded_models": 1,
  "active_tasks": 2,
  "storage": "ok"
}
```

| Campo | Significado |
| --- | --- |
| `status` | `starting`, `ready`, `degraded` o `stopping`. |
| `service_id` | El id del servicio de la descripción del servicio. |
| `uptime_seconds` | Segundos desde que se inició el servicio. |
| `loaded_models` | Número de modelos en estado `ready`. |
| `active_tasks` | Número de tareas que están `queued`, `loading`, `running` o `cancelling`. |
| `storage` | `ok` o `error`. |

El estado HTTP es `200 OK` cuando `status` es `ready` o `degraded`, y `503 Service Unavailable` en caso contrario.

El endpoint de estado devuelve solo el estado operativo. **NO DEBE** devolver rutas de modelos, prompts, tokens de acceso ni otra información sensible.
