Règles communes

9.1 Versions et extensions

Chaque requête LMSP PEUT porter ces en-têtes :

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

LMSP-Version est la version du protocole visée par le client. LMSP-Client identifie le logiciel client à des fins de diagnostic, sous la forme name/version. Un service NE DOIT PAS modifier le comportement du protocole d’après ce dernier.

Règles :

  • Le v1 du chemin désigne la version majeure.
  • Une requête qui nomme une version majeure inconnue reçoit la réponse 426 Upgrade Required avec le code d’erreur unsupported_protocol_version.
  • Les nouveaux champs facultatifs NE DOIVENT PAS rompre la compatibilité 1.x.
  • Les services et les clients DOIVENT ignorer les champs qu’ils ne connaissent pas.
  • Les extensions privées vont dans un objet extensions et sont nommées en notation de domaine inversé :
{
  "extensions": {
    "com.example.cache": {
      "enabled": true
    }
  }
}

9.2 Idempotence

Les requêtes qui créent quelque chose, comme créer une réponse, créer une tâche ou charger un modèle, acceptent une clé d’idempotence :

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

Le service stocke la clé avec une empreinte du corps de la requête et le résultat :

  • La même clé avec le même corps renvoie le résultat d’origine.
  • La même clé avec un corps différent reçoit la réponse 409 Conflict avec idempotency_conflict.

Une clé est propre au client et au point de terminaison. Elle DEVRAIT être une valeur unique d’au plus 255 caractères, telle qu’un ULID ou un UUID. Un service DEVRAIT conserver les clés au moins 24 heures.

Un service PEUT ignorer la clé sur les requêtes en streaming. Un client qui a besoin de nouvelles tentatives sûres utilise une tâche.

9.3 Erreurs

Chaque erreur de l’interface LMSP utilise application/problem+json (RFC 9457) :

{
  "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
}
Champ Obligatoire Signification
type Oui URI qui identifie le type d’erreur. LMSP utilise urn:lmsp:error: suivi du code avec des tirets à la place des traits de soulignement.
title Oui Résumé court et lisible.
status Oui Le code d’état HTTP.
code Oui Code d’erreur lisible par machine, tiré de la liste ci-dessous.
detail Non Explication lisible de cette occurrence. Il NE DOIT PAS contenir de secrets, de prompts ni de contenu généré.
request_id Non Identifiant de la requête, pour la corréler avec les journaux du service.
retryable Oui Indique si répéter la requête plus tard peut réussir.

Codes d’erreur courants :

Code État HTTP Réessayable Signification
invalid_request 400 Non La requête est mal formée ou comporte des paramètres invalides.
unauthorized 401 Non Le jeton est absent, invalide, expiré ou révoqué, ou un code d’appairage est erroné.
forbidden 403 Non Le jeton n’a pas la portée requise, ou la vérification de Origin ou de Host a échoué.
model_not_found 404 Non Aucun modèle local n’a cet identifiant.
model_not_ready 409 Oui Le modèle n’est pas chargé et n’est pas chargé à la demande.
model_load_failed 500 Oui Le chargement du modèle a échoué.
context_length_exceeded 400 Non L’entrée ne tient pas dans la fenêtre de contexte du modèle.
unsupported_capability 400 ou 501 Non Le modèle ou le service ne prend pas en charge ce dont la requête a besoin. Un point de terminaison facultatif non implémenté répond 501.
unsupported_protocol_version 426 Non Le service ne prend pas en charge la version majeure demandée.
response_not_found 404 Non Aucune réponse stockée n’a cet identifiant.
task_not_found 404 Non Aucune tâche n’a cet identifiant.
task_not_cancelable 409 Non La tâche a déjà réussi ou échoué.
idempotency_conflict 409 Non La clé d’idempotence a déjà été utilisée avec un corps de requête différent.
event_history_expired 410 Non Les événements demandés sont plus anciens que la durée de conservation.
rate_limited 429 Oui Trop de requêtes.
resource_exhausted 503 Oui L’appareil manque de mémoire ou d’une autre ressource.
backend_unavailable 503 Oui L’environnement d’exécution du modèle est injoignable.
server_restarted 503 Oui Le service a redémarré alors que la tâche était inachevée.
internal_error 500 Variable Une défaillance inattendue à l’intérieur du service.

Le champ retryable fait foi. La colonne ci-dessus indique la valeur habituelle. Un service PEUT définir d’autres codes. Un client DOIT traiter un code qu’il ne connaît pas d’après son état HTTP et son champ retryable.

9.4 Contrôle d’état

GET /lmsp/v1/health
{
  "status": "ready",
  "service_id": "svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2",
  "uptime_seconds": 86420,
  "loaded_models": 1,
  "active_tasks": 2,
  "storage": "ok"
}
Champ Signification
status starting, ready, degraded ou stopping.
service_id L’identifiant du service tiré de la description du service.
uptime_seconds Secondes écoulées depuis le démarrage du service.
loaded_models Nombre de modèles à l’état ready.
active_tasks Nombre de tâches à l’état queued, loading, running ou cancelling.
storage ok ou error.

L’état HTTP est 200 OK lorsque status vaut ready ou degraded, et 503 Service Unavailable sinon.

Le point de terminaison de santé ne renvoie que l’état opérationnel. Il NE DOIT PAS renvoyer de chemins de modèles, de prompts, de jetons d’accès ni d’autres informations sensibles.