# Local Model Service Protocol (LMSP) 1.0, Brouillon > Made for Agent publie des protocoles ouverts et lisibles par machine qui permettent aux agents IA, aux modèles et aux outils de se découvrir et de dialoguer entre eux. Il commence avec LMSP, le Local Model Service Protocol. Source: https://madeforagent.com/fr/llms-full.txt Updated: 2026-11-08 --- # Protocole de service de modèles locaux (LMSP) > LMSP est un protocole ouvert pour découvrir et appeler les modèles de langage de votre appareil. Il définit découverte de services, catalogue de modèles, streaming, tâches persistantes et compatibilité OpenAI. Source: https://madeforagent.com/fr/lmsp/ Language: fr Updated: 2026-11-08 ## Ce que fait LMSP {#what} LMSP (Local Model Service Protocol) est un protocole ouvert destiné aux logiciels qui exécutent des modèles de langage sur l’appareil ou le réseau local de l’utilisateur, et aux clients qui utilisent ces logiciels. Un service local résident se décrit à une adresse bien connue et liste ses modèles. Il répond aux requêtes de génération en JSON ou par des événements envoyés par le serveur, et exécute les longues générations sous forme de tâches persistantes qui peuvent être annulées et suivies de nouveau après une déconnexion. Le même service parle aussi l’API OpenAI, de sorte que les clients qui existent aujourd’hui continuent de fonctionner. LMSP ne remplace ni l’API OpenAI, ni Ollama, ni MCP. Il combine leurs points forts dans une couche de protocole conçue pour les services locaux résidents. ## En un coup d’œil {#glance} | Sujet | Résumé | | --- | --- | | Adresse par défaut | `http://127.0.0.1:17832` | | Description du service | `GET /.well-known/lmsp.json` | | Interface principale | `/lmsp/v1`, JSON sur HTTP, streaming avec des événements envoyés par le serveur | | Interfaces de compatibilité | `/v1` pour les clients OpenAI, `/api` facultatif pour les clients Ollama | | Découverte | Adresse manuelle, sondage des adresses locales, mDNS et DNS-SD facultatifs (`_lmsp._tcp.local.`) | | Authentification | Jetons porteurs obtenus par appairage local | | Persistance | SQLite intégré, avec des tâches qui survivent à un redémarrage | | Contrat | OpenAPI 3.2 | ## Essayez {#try} Si un service LMSP s’exécute sur votre machine, voici tout le déroulé. Appairez-vous d’abord pour obtenir un jeton, comme décrit à la [section 10.2](https://madeforagent.com/fr/lmsp/1.0/security.md#pairing), et conservez-le dans `LMSP_TOKEN`. ```sh # 1. Découvrir le service curl http://127.0.0.1:17832/.well-known/lmsp.json # 2. Lister les modèles locaux curl http://127.0.0.1:17832/lmsp/v1/models \ -H "Authorization: Bearer $LMSP_TOKEN" # 3. Générer une réponse curl http://127.0.0.1:17832/lmsp/v1/responses \ -H "Authorization: Bearer $LMSP_TOKEN" \ -H "Content-Type: application/json" \ -d '{"model":"qwen3:14b-q4_k_m","input":[{"type":"message","role":"user","content":[{"type":"input_text","text":"Hello"}]}]}' ``` ## Place de LMSP parmi les autres protocoles {#related} | Protocole | Ce qu’il couvre | Lien avec LMSP | | --- | --- | --- | | API OpenAI | Modèles hébergés. L’API Responses est son interface la plus récente. | LMSP suit la structure de Responses pour son interface principale, et un service propose à côté une interface compatible OpenAI. | | Ollama | Un environnement d’exécution local qui sert déjà des points de terminaison compatibles OpenAI. | Il peut se placer derrière un service LMSP en tant qu’adaptateur, et LMSP définit des points de terminaison facultatifs compatibles Ollama. | | MCP | Relie les agents aux outils et au contexte. | LMSP relie les agents aux modèles. Tous deux préfèrent la découverte sans état aux sessions obligatoires. | | A2A | Collaboration entre agents. | LMSP emprunte les cartes de service et les états de tâche explicites pour sa description de service et ses tâches. | ## Ressources {#resources} - La [spécification, version 1.0 (brouillon)](https://madeforagent.com/fr/lmsp/1.0.md). - Le contrat OpenAPI, en [JSON](https://madeforagent.com/lmsp/1.0/openapi.json) ou en [YAML](https://madeforagent.com/lmsp/1.0/openapi.yaml). - [llms.txt](https://madeforagent.com/fr/llms.txt) et [llms-full.txt](https://madeforagent.com/fr/llms-full.txt), pour les modèles de langage. - Chaque page est disponible en Markdown. Remplacez la barre oblique finale de son adresse par `.md`, par exemple [`/fr/lmsp/1.0/tasks.md`](https://madeforagent.com/fr/lmsp/1.0/tasks.md). ## Questions fréquentes ### Qu’est-ce que LMSP ? LMSP, le Local Model Service Protocol (protocole de service de modèles locaux), est un protocole ouvert pour les services de modèles de langage qui s’exécutent sur l’appareil de l’utilisateur ou sur son réseau local. Il définit la façon dont les clients découvrent un service, listent ses modèles, demandent des réponses, reçoivent la sortie en streaming et exécutent des tâches longues. ### LMSP remplace-t-il l’API OpenAI, Ollama ou MCP ? Non. LMSP s’appuie sur eux. Son interface principale suit la structure d’OpenAI Responses, un service peut proposer des points de terminaison compatibles OpenAI et Ollama, et le protocole emprunte à MCP la découverte sans état et à A2A les états des tâches. ### Les clients OpenAI existants peuvent-ils utiliser un service LMSP ? Généralement oui. Ils ont besoin d’une autre URL de base et du jeton LMSP comme clé d’API. Ils ne trouvent pas le service automatiquement, car la découverte demande un client qui prend en charge LMSP. ### Comment un client trouve-t-il un service LMSP local ? Il essaie trois choses dans l’ordre. D’abord une adresse saisie à la main, puis l’adresse locale conventionnelle, où il demande /.well-known/lmsp.json, et enfin, en option, la recherche mDNS et DNS-SD de _lmsp._tcp.local. sur le réseau local. ### Un service de modèles sur localhost est-il sûr ? Pas automatiquement, car des pages web peuvent essayer d’atteindre des ports locaux. Les services LMSP écoutent par défaut sur loopback, exigent des jetons porteurs obtenus par appairage local, vérifient les en-têtes Origin et Host, et exigent une authentification en mode LAN. ### Quel est l’état de la spécification ? La version 1.0 est un premier brouillon public et peut encore changer de façon incompatible. Le texte anglais fait foi, et les traductions sont fournies par commodité. --- # Vue d’ensemble > Vue d’ensemble du brouillon de LMSP 1.0. Ce qu’est le Local Model Service Protocol, les conceptions sur lesquelles il s’appuie, son architecture en couches, la façon de lire la spécification et les termes employés. Source: https://madeforagent.com/fr/lmsp/1.0/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 1.1 Résumé {#abstract} Le Local Model Service Protocol (LMSP) définit la façon dont les clients trouvent et utilisent les services de modèles de langage qui s’exécutent sur l’appareil ou le réseau local de l’utilisateur. Il spécifie la découverte de services, un catalogue de modèles, la génération synchrone et en streaming, et des tâches asynchrones qui survivent aux redémarrages. Il définit aussi comment un même service propose une interface compatible OpenAI à côté de l’interface LMSP, afin que les clients existants continuent de fonctionner. LMSP ne remplace ni l’API OpenAI, ni Ollama, ni MCP. Il combine leurs points forts dans une couche de protocole conçue pour un service local résident. ## 1.2 État de ce document {#status} Ceci est le premier brouillon public de LMSP 1.0, publié le 2026-11-08. « LMSP » est un nom de travail. Le texte est ouvert aux retours et peut changer de façon incompatible jusqu’à ce que la version 1.0 soit définitive. Le texte anglais fait foi. Les traductions sont fournies par commodité ; en cas de différence, le texte anglais prévaut. ## 1.3 Fondements de la conception {#design-basis} LMSP réutilise des conceptions éprouvées plutôt que d’en inventer de nouvelles : - **API OpenAI Responses.** Éléments de sortie structurés, événements sémantiques envoyés par le serveur, et exécution en arrière-plan avec interrogation et annulation pour les travaux de longue durée. C’est la référence de l’interface de conversation principale de LMSP. Voir [les réponses en streaming](https://developers.openai.com/api/docs/guides/streaming-responses) et [le mode arrière-plan](https://developers.openai.com/api/docs/guides/background). - **Ollama.** Il sert les points de terminaison compatibles OpenAI `/v1/models`, `/v1/chat/completions` et `/v1/responses`, ce qui montre qu’un service associé à une couche d’adaptation OpenAI réduit fortement le coût d’adoption. Voir [la compatibilité OpenAI d’Ollama](https://docs.ollama.com/api/openai-compatibility). - **Model Context Protocol (MCP).** Sa conception la plus récente abandonne l’initialisation de session obligatoire au profit d’une découverte sans état : chaque requête porte ses propres informations de version, et les clients apprennent les capacités par une interface de découverte. Cela convient aux services locaux, où les redémarrages, les plantages de clients et les connexions interrompues ne doivent pas corrompre l’état du protocole. Voir [MCP](https://modelcontextprotocol.io/). - **Agent2Agent (A2A).** Les cartes de service, les états de tâche explicites, l’abonnement aux tâches et l’annulation ont inspiré la description de service et le modèle de tâches asynchrones de LMSP. Voir [A2A](https://a2a-protocol.org/). ## 1.4 Architecture {#architecture} LMSP est organisé en trois couches, au-dessus des adaptateurs qui dialoguent avec les environnements d’exécution des modèles : ```text +---------------------------------------------------------------+ | Discovery mDNS / DNS-SD + well-known service document | +---------------------------------------------------------------+ | Core model catalog, responses, SSE, async tasks | +---------------------------------------------------------------+ | Compatibility OpenAI API, optional Ollama API | +---------------------------------------------------------------+ | Adapters llama.cpp, Ollama, vLLM, custom runtimes | +---------------------------------------------------------------+ ``` - **Découverte.** mDNS/DNS-SD et un document de description de service à une adresse bien connue ([page 3](https://madeforagent.com/fr/lmsp/1.0/discovery.md)). - **Cœur.** Le catalogue de modèles, les réponses synchrones, les événements envoyés par le serveur et les tâches asynchrones ([pages 5 à 7](https://madeforagent.com/fr/lmsp/1.0/models.md)). - **Compatibilité.** Une API compatible OpenAI et, en option, une API compatible Ollama ([page 8](https://madeforagent.com/fr/lmsp/1.0/compatibility.md)). - **Adaptateurs.** Des passerelles vers llama.cpp, Ollama, vLLM ou un environnement d’exécution sur mesure. Le principe directeur est **un seul cœur d’exécution des modèles, deux familles d’interfaces**. Un service propose l’interface LMSP et l’interface OpenAI au-dessus du même cœur, de sorte qu’il n’y a qu’un seul endroit où les modèles sont chargés, les requêtes exécutées et les tâches suivies. ## 1.5 Vocabulaire de conformité {#conformance} Les mots-clés **DOIT/DOIVENT** (MUST), **NE DOIT PAS/NE DOIVENT PAS** (MUST NOT), **REQUIS** (REQUIRED), **DEVRAIT/DEVRAIENT** (SHOULD), **NE DEVRAIT PAS/NE DEVRAIENT PAS** (SHOULD NOT), **RECOMMANDÉ** (RECOMMENDED), **PEUT/PEUVENT** (MAY) et **OPTIONNEL** (OPTIONAL) de ce document sont à interpréter comme décrit dans le [BCP 14](https://www.rfc-editor.org/info/bcp14) ([RFC 2119](https://www.rfc-editor.org/rfc/rfc2119), [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174)) lorsque, et seulement lorsque, ils apparaissent en gras et en majuscules. Partout ailleurs, ce sont des mots ordinaires. Chaque page est marquée comme normative ou informative. Les pages normatives définissent des exigences ; les pages informatives donnent des indications. Les exemples sont informatifs. Le JSON est en UTF-8, et les noms de champ utilisent `snake_case`. ## 1.6 Terminologie {#terminology} | Terme | Signification | | --- | --- | | Service | Un processus résident qui implémente LMSP et exécute des modèles par l’intermédiaire d’adaptateurs. | | Client | Un logiciel qui découvre et appelle un service : un agent, une application ou un outil. | | Adaptateur | Le composant qui relie le service à un seul environnement d’exécution de modèles, comme llama.cpp, Ollama ou vLLM. | | Modèle | Un modèle disponible localement, identifié par un `id` stable. | | Réponse | Le résultat d’une requête de génération : éléments de sortie, consommation et un état. | | Tâche | Une exécution asynchrone et persistée d’une requête de réponse, avec un état explicite. | | Événement | Un événement envoyé par le serveur, avec un numéro de séquence, émis pendant la génération d’une réponse. | --- # Transport et déploiement > Adresses d’écoute par défaut, transport, format de streaming et organisation des URL d’un service LMSP, et façon dont il s’exécute comme service du système d’exploitation, séparé des processus de modèle. Source: https://madeforagent.com/fr/lmsp/1.0/transport/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 2.1 Déploiement par défaut {#deployment} Un service **DOIT** écouter par défaut sur les adresses de loopback `127.0.0.1` et `::1`. Le port conventionnel est `17832`, ce qui donne l’adresse de base par défaut `http://127.0.0.1:17832`. | Élément | Valeur | | --- | --- | | Adresses d’écoute | `127.0.0.1` et `::1` | | Transport | HTTP/1.1 ou HTTP/2 transportant du JSON | | Streaming | Événements envoyés par le serveur, `Content-Type: text/event-stream` | | Préfixe de l’interface principale | `/lmsp/v1` | | Préfixe compatible OpenAI | `/v1` | | Description du service | `GET /.well-known/lmsp.json` | | Contrat lisible par machine | `GET /lmsp/v1/openapi.json` | | Canal local facultatif | Socket de domaine Unix ou canal nommé Windows | Les requêtes et les réponses utilisent du JSON en UTF-8 (`Content-Type: application/json`), sauf les flux (`text/event-stream`) et les erreurs (`application/problem+json`). Les horodatages sont des entiers : des secondes depuis l’epoch Unix. Les identifiants sont des chaînes opaques ; un préfixe de type tel que `resp_` ou `task_` est **RECOMMANDÉ**. Le contrat de l’interface est un document OpenAPI 3.2. OpenAPI 3.2 sait décrire les événements envoyés par le serveur, le JSON Lines et les JSON Sequences, de sorte que les points de terminaison de streaming sont spécifiés dans le même document que le reste. Le contrat de cette version est publié à l’adresse [`/lmsp/1.0/openapi.json`](https://madeforagent.com/lmsp/1.0/openapi.json). Un service **PEUT** aussi accepter des connexions sur un socket de domaine Unix ou un canal nommé Windows, avec la même sémantique HTTP. Dans la version 1.0, la façon d’annoncer de tels points de terminaison est laissée aux extensions. ## 2.2 Fonctionnement permanent {#operation} Un service **DEVRAIT** être hébergé par le système d’exploitation : launchd sous macOS, systemd sous Linux et le gestionnaire de services sous Windows. Le processus du service et les processus de modèle **DEVRAIENT** être séparés. Le plantage d’un modèle **DEVRAIT** n’affecter que les tâches qui utilisent ce modèle. Il **NE DEVRAIT PAS** rendre indisponibles la découverte du service, le catalogue de modèles ni les requêtes sur les tâches antérieures. --- # Découverte de services > Comment les clients LMSP trouvent un service local par configuration manuelle, sondage de loopback et mDNS/DNS-SD facultatif, et comment lire le document de description de service à l’adresse bien connue. Source: https://madeforagent.com/fr/lmsp/1.0/discovery/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 3.1 Méthodes de découverte {#methods} Un client découvre un service en essayant ces méthodes dans l’ordre : 1. **Configuration manuelle.** L’utilisateur saisit directement l’adresse du service. 2. **Sondage des adresses locales conventionnelles.** Le client demande `/.well-known/lmsp.json` à des adresses candidates. Les candidates conventionnelles sont `http://127.0.0.1:17832` et `http://[::1]:17832`. 3. **Découverte sur le réseau local.** Le client recherche `_lmsp._tcp.local.` avec mDNS et DNS-SD. Une méthode réussit lorsqu’elle fournit une description de service valide ([section 3.3](https://madeforagent.com/fr/lmsp/1.0/discovery.md#service-description)). Une adresse saisie manuellement par l’utilisateur l’emporte toujours sur celles qui sont découvertes. ## 3.2 Annonce sur le réseau local {#mdns} DNS-SD utilise des enregistrements PTR pour trouver les instances de service, des enregistrements SRV pour obtenir l’hôte et le port, et des enregistrements TXT pour transporter un peu d’information supplémentaire. Combiné à mDNS, il permet une découverte sans configuration sur un réseau local ([RFC 6763](https://www.rfc-editor.org/rfc/rfc6763), [RFC 6762](https://www.rfc-editor.org/rfc/rfc6762)). Voici un exemple d’annonce : ```text Service type: _lmsp._tcp.local. Instance name: Workstation LMSP._lmsp._tcp.local. TXT record: v=1 id=svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2 path=/ auth=pairing ``` | Clé TXT | Signification | | --- | --- | | `v` | Version du format d’annonce. `1` pour LMSP 1.0. | | `id` | L’identifiant du service, égal à `service.id` dans la description du service. | | `path` | Chemin d’URL de la racine du service. Les clients demandent `{path}.well-known/lmsp.json`. | | `auth` | Indication d’authentification. `pairing` signifie qu’un client doit s’appairer avant d’utiliser le service. | Règles : - Un service **NE DOIT PAS** placer de jetons d’accès, de listes de modèles, de chemins de fichiers ni aucune autre information sensible dans l’enregistrement TXT. L’enregistrement sert seulement à localiser le service. Les capacités réelles **DOIVENT** être lues dans la description du service. - Un service **DOIT** laisser l’annonce mDNS désactivée par défaut. Elle n’est activée que lorsque l’utilisateur active explicitement la découverte sur le réseau local. Un service utilisé uniquement sur la machine locale ne s’annonce pas. - Un service qui s’annonce sur le réseau local doit écouter au-delà de loopback, ce qui n’est permis qu’en mode LAN ([section 10.5](https://madeforagent.com/fr/lmsp/1.0/security.md#lan)). - Un client **DOIT** traiter l’enregistrement TXT comme une indication non vérifiée, et confirmer le service en lisant sa description. ## 3.3 Description du service {#service-description} ```http GET /.well-known/lmsp.json ``` Un service **DOIT** servir ce document avec le type `application/json`, sans exiger d’authentification. ```json { "protocol": "lmsp", "versions": ["1.0"], "service": { "id": "svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2", "name": "Workstation Local Models", "version": "1.0.0" }, "interfaces": [ { "kind": "lmsp", "version": "1.0", "url": "http://127.0.0.1:17832/lmsp/v1", "transport": "http+json" }, { "kind": "openai", "version": "responses+chat", "url": "http://127.0.0.1:17832/v1", "transport": "http+json" } ], "capabilities": { "streaming": true, "tasks": true, "event_resume": true, "conversations": true, "model_management": true }, "authentication": { "type": "bearer", "pairing_url": "http://127.0.0.1:17832/lmsp/v1/pair" }, "openapi": "http://127.0.0.1:17832/lmsp/v1/openapi.json" } ``` | Champ | Signification | | --- | --- | | `protocol` | Toujours `"lmsp"`. | | `versions` | Les versions de LMSP prises en charge par le service, sous forme de chaînes `major.minor`. | | `service` | `id` est un identifiant de service stable, `name` un nom d’affichage et `version` la version du logiciel du service. | | `interfaces` | Les interfaces proposées. Chacune a un `kind` (`lmsp`, `openai` ou `ollama`), une `version`, une `url` de base et un `transport`. Pour `openai`, `version` nomme les familles d’API servies, comme `responses+chat`. | | `capabilities` | Indicateurs booléens de fonctionnalités, énumérés ci-dessous. | | `authentication` | `type` vaut `bearer`. `pairing_url` est l’adresse où les clients échangent un code d’appairage contre un jeton ([section 10.2](https://madeforagent.com/fr/lmsp/1.0/security.md#pairing)). | | `openapi` | URL du document OpenAPI qui décrit l’interface LMSP. | Indicateurs de capacité : | Indicateur | Signification | | --- | --- | | `streaming` | Les réponses peuvent être diffusées sous forme d’événements envoyés par le serveur. **DOIT** valoir `true` dans la version 1.0. | | `tasks` | Les tâches asynchrones sont disponibles. **DOIT** valoir `true` dans la version 1.0. | | `event_resume` | On peut s’abonner aux flux d’événements des tâches et les reprendre (`GET /lmsp/v1/tasks/{task_id}/events`). | | `conversations` | Le service stocke les réponses : `store` et `previous_response_id` fonctionnent et `GET /lmsp/v1/responses/{response_id}` est disponible. | | `model_management` | Les modèles peuvent être chargés et déchargés explicitement. | ## 3.4 Comportement du client {#client-behavior} Un client : - **DEVRAIT** sélectionner la version la plus élevée de `versions` qu’il prend lui aussi en charge. - **DEVRAIT** choisir l’interface LMSP ou l’interface OpenAI dans `interfaces`, selon ce qu’il sait parler. - **DOIT** utiliser uniquement les capacités que la description déclare. Un indicateur absent signifie `false`. - **DOIT** ignorer les champs d’extension qu’il ne reconnaît pas. - **DEVRAIT** relire périodiquement la description du service, ainsi que lorsqu’une requête échoue, au lieu de la mettre en cache indéfiniment. - **DEVRAIT** mémoriser un service choisi par `service.id` plutôt que par son adresse, car les adresses peuvent changer. --- # Points de terminaison > Le tableau complet des points de terminaison de LMSP 1.0 avec méthode, chemin, niveau d’exigence et rôle, ainsi que les conventions sur les chemins, l’authentification et les points de terminaison facultatifs. Source: https://madeforagent.com/fr/lmsp/1.0/endpoints/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 4.1 Tableau des points de terminaison {#table} Un service conforme **DOIT** implémenter chaque point de terminaison marqué obligatoire. Il **PEUT** implémenter les facultatifs, et les signale par les indicateurs de capacité de sa [description de service](https://madeforagent.com/fr/lmsp/1.0/discovery.md#service-description). | Méthode | Chemin | Exigence | Rôle | | --- | --- | --- | --- | | GET | `/.well-known/lmsp.json` | Obligatoire | [Découverte du service et de ses capacités](https://madeforagent.com/fr/lmsp/1.0/discovery.md#service-description) | | GET | `/lmsp/v1/openapi.json` | Obligatoire | Spécification de l’interface lisible par machine | | GET | `/lmsp/v1/health` | Obligatoire | [Contrôle de vivacité et de disponibilité](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#health) | | POST | `/lmsp/v1/pair` | Obligatoire | [Échanger un code d’appairage contre un jeton porteur](https://madeforagent.com/fr/lmsp/1.0/security.md#pairing) | | GET | `/lmsp/v1/models` | Obligatoire | [Lister les modèles locaux](https://madeforagent.com/fr/lmsp/1.0/models.md#list) | | GET | `/lmsp/v1/models/{model_id}` | Obligatoire | [Obtenir un modèle](https://madeforagent.com/fr/lmsp/1.0/models.md#operations) | | POST | `/lmsp/v1/responses` | Obligatoire | [Génération synchrone ou en streaming](https://madeforagent.com/fr/lmsp/1.0/responses.md#request) | | GET | `/lmsp/v1/responses/{response_id}` | Facultatif | [Récupérer une réponse stockée](https://madeforagent.com/fr/lmsp/1.0/responses.md#sync) | | POST | `/lmsp/v1/tasks` | Obligatoire | [Créer une tâche de génération asynchrone](https://madeforagent.com/fr/lmsp/1.0/tasks.md#create) | | GET | `/lmsp/v1/tasks/{task_id}` | Obligatoire | [Obtenir une tâche asynchrone](https://madeforagent.com/fr/lmsp/1.0/tasks.md#create) | | POST | `/lmsp/v1/tasks/{task_id}/cancel` | Obligatoire | [Annuler une tâche asynchrone](https://madeforagent.com/fr/lmsp/1.0/tasks.md#cancel) | | GET | `/lmsp/v1/tasks/{task_id}/events` | Facultatif | [S’abonner au flux d’événements ou le reprendre](https://madeforagent.com/fr/lmsp/1.0/tasks.md#events) | | POST | `/lmsp/v1/models/{model_id}/load` | Facultatif | [Précharger un modèle](https://madeforagent.com/fr/lmsp/1.0/models.md#operations) | | POST | `/lmsp/v1/models/{model_id}/unload` | Facultatif | [Décharger un modèle](https://madeforagent.com/fr/lmsp/1.0/models.md#operations) | Les points de terminaison compatibles OpenAI sous `/v1` et les points de terminaison facultatifs compatibles Ollama sont listés à la [page 8](https://madeforagent.com/fr/lmsp/1.0/compatibility.md). ## 4.2 Conventions {#conventions} - **Corps.** Les corps des requêtes et des réponses sont en JSON (`application/json`), sauf les flux d’événements (`text/event-stream`) et les erreurs (`application/problem+json`). - **Paramètres de chemin.** Un nom entre accolades, tel que `{model_id}`, est un espace réservé. Les valeurs **DOIVENT** être encodées en pourcentage. Un identifiant de modèle comme `qwen3:14b-q4_k_m` est envoyé sous la forme `qwen3%3A14b-q4_k_m`. - **Authentification.** Chaque point de terminaison exige `Authorization: Bearer `, sauf `/.well-known/lmsp.json`, `/lmsp/v1/openapi.json`, `/lmsp/v1/health` et `/lmsp/v1/pair`. - **Points de terminaison facultatifs.** Un point de terminaison facultatif que le service n’implémente pas **DOIT** répondre `501 Not Implemented` avec le code d’erreur `unsupported_capability`. - **Versions et erreurs.** Les requêtes peuvent porter des en-têtes de version, et chaque erreur utilise un format unique. Les deux sont définis à la [page 9](https://madeforagent.com/fr/lmsp/1.0/common-rules.md). - **Contrat.** Le document OpenAPI publié à l’adresse [`/lmsp/1.0/openapi.json`](https://madeforagent.com/lmsp/1.0/openapi.json) est la forme lisible par machine de cette page. Le texte fait foi lorsque les deux diffèrent. --- # Catalogue de modèles > Comment un service LMSP liste ses modèles locaux, l’objet modèle et ses indicateurs de capacité, les états du cycle de vie d’un modèle, les identifiants de modèle stables et les révisions du catalogue. Source: https://madeforagent.com/fr/lmsp/1.0/models/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 5.1 Lister les modèles {#list} ```http GET /lmsp/v1/models?capability=chat&ready_only=false Authorization: Bearer ``` | Paramètre de requête | Signification | | --- | --- | | `capability` | Ne renvoie que les modèles qui possèdent la capacité nommée, par exemple `chat`, `embeddings` ou `tools`. | | `ready_only` | Si la valeur est `true`, ne renvoie que les modèles dont le `status` est `ready`. Vaut `false` par défaut. | ```json { "object": "list", "catalog_revision": "42", "data": [ { "id": "qwen3:14b-q4_k_m", "object": "model", "display_name": "Qwen3 14B Q4_K_M", "owned_by": "local", "family": "qwen3", "revision": "sha256:8f27c1a4e9b05d36f2a7c8e1b4d90a63c5e2f7b8a1d4c9e60b3f5a7d2c8e1b04", "status": "ready", "capabilities": { "chat": true, "completion": true, "embeddings": false, "tools": true, "vision": false, "structured_output": true, "streaming": true }, "input_modalities": ["text"], "output_modalities": ["text"], "context_window": 32768, "max_output_tokens": 8192, "runtime": { "backend": "llama.cpp", "device": "metal", "load_on_demand": true } } ] } ``` Pour éviter aux clients de récupérer sans cesse le catalogue complet, un service **DEVRAIT** renvoyer un en-tête `ETag`, un champ `catalog_revision`, ou les deux : - `catalog_revision` est une chaîne opaque qui change chaque fois que le catalogue change. - Un service qui envoie `ETag` **DEVRAIT** répondre `304 Not Modified` à un `If-None-Match` correspondant. ## 5.2 Objet modèle {#object} | Champ | Signification | | --- | --- | | `id` | Identifiant stable du modèle, utilisé dans chaque requête qui nomme un modèle. | | `object` | Toujours `"model"`. | | `display_name` | Nom lisible. L’utilisateur peut le modifier. | | `aliases` | Liste facultative de noms alternatifs. Ils sont purement informatifs. | | `owned_by` | Provenance du modèle. `local` pour les modèles installés sur cet appareil. | | `family` | Famille du modèle, comme `qwen3`. | | `revision` | Empreinte du contenu du modèle, comme `sha256:8f27...`. | | `status` | État du cycle de vie ([section 5.3](https://madeforagent.com/fr/lmsp/1.0/models.md#lifecycle)). | | `capabilities` | Indicateurs booléens : `chat`, `completion`, `embeddings`, `tools`, `vision`, `structured_output` et `streaming`. | | `input_modalities`, `output_modalities` | Les types de contenu que le modèle lit et écrit. `text` est la seule modalité définie dans la version 1.0. | | `context_window` | Nombre maximal de tokens de contexte. | | `max_output_tokens` | Nombre maximal de tokens dans une réponse. | | `runtime` | `backend` (par exemple `llama.cpp`), `device` (par exemple `metal`) et `load_on_demand`. | | `error` | Présent lorsque `status` vaut `error`. Un objet problème ([section 9.3](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#errors)). | L’`id` d’un modèle **DOIT** être stable. L’utilisateur peut modifier le nom d’affichage et les alias ; ils **NE DOIVENT PAS** servir de clé primaire. ## 5.3 Cycle de vie du modèle {#lifecycle} ```text installed --> loading --> ready --> unloading --> installed | +-----> error ``` | État | Signification | | --- | --- | | `installed` | Le modèle existe mais n’est pas chargé. | | `loading` | De la mémoire est en cours d’allocation ou l’environnement d’exécution s’initialise. | | `ready` | Le modèle peut traiter immédiatement des requêtes. | | `unloading` | Les ressources sont en cours de libération. | | `error` | Le chargement a échoué. L’objet modèle **DEVRAIT** porter une erreur structurée. | Une nouvelle demande de chargement fait repasser à `loading` un modèle à l’état `error`. Lorsqu’une requête nomme un modèle à l’état `installed` dont le `runtime.load_on_demand` vaut `true`, le service le charge dans le cadre de la requête. Si le modèle ne peut pas être utilisé immédiatement et n’est pas chargé à la demande, le service répond `409` avec `model_not_ready`. Si le chargement échoue, l’erreur est `model_load_failed`. ## 5.4 Opérations sur les modèles {#operations} `GET /lmsp/v1/models/{model_id}` renvoie un objet modèle. Un identifiant inconnu donne `404` avec `model_not_found`. Deux points de terminaison facultatifs contrôlent explicitement le chargement. Ils sont disponibles lorsque la capacité `model_management` vaut `true`, et exigent la portée `models:manage` ([section 10.3](https://madeforagent.com/fr/lmsp/1.0/security.md#scopes)) : | Point de terminaison | Comportement | | --- | --- | | `POST /lmsp/v1/models/{model_id}/load` | Précharge le modèle. Renvoie l’objet modèle avec `202 Accepted` lorsque le chargement a commencé, ou `200` lorsqu’il est déjà `ready`. | | `POST /lmsp/v1/models/{model_id}/unload` | Décharge le modèle. Renvoie l’objet modèle. Répéter la requête est sans conséquence. | Les deux acceptent un `Idempotency-Key` ([section 9.2](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#idempotency)). --- # Réponses et streaming > L’interface de conversation principale de LMSP, avec requêtes et éléments de sortie de style Responses, génération synchrone et en streaming, événements envoyés par le serveur, reconnexion et appels d’outils. Source: https://madeforagent.com/fr/lmsp/1.0/responses/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 6.1 Requête {#request} ```http POST /lmsp/v1/responses Authorization: Bearer Content-Type: application/json Idempotency-Key: 01J8M5T7Z2K4N6Q8S0V3X5B9DG LMSP-Version: 1.0 ``` ```json { "model": "qwen3:14b-q4_k_m", "input": [ { "type": "message", "role": "user", "content": [ { "type": "input_text", "text": "Describe a local model service in one sentence." } ] } ], "stream": false, "max_output_tokens": 512, "temperature": 0.7, "response_format": { "type": "text" }, "store": true } ``` Le protocole principal utilise une structure `input` et `output` de style Responses plutôt qu’une simple liste de chaînes de messages, afin qu’une seule forme de requête puisse transporter : - des messages multi-tours ; - du texte, des images, du son et des fichiers ; - des appels d’outils et des résultats d’outils ; - une sortie structurée ; - des résumés de raisonnement ; - une sortie multimodale. LMSP 1.0 ne définit que le contenu texte. Les types de contenu image, audio et fichier sont réservés à de futures versions. | Champ | Obligatoire | Signification | | --- | --- | --- | | `model` | Oui | Identifiant du modèle à utiliser. | | `input` | Oui | Tableau d’éléments d’entrée. Un élément `message` a un `role` (`system`, `user` ou `assistant`) et un tableau `content` de parties, comme `input_text`. L’usage d’outils ajoute des éléments `function_call` et `function_call_output` ([section 6.5](https://madeforagent.com/fr/lmsp/1.0/responses.md#tools)). | | `stream` | Non | `true` pour recevoir des événements envoyés par le serveur. Vaut `false` par défaut. | | `max_output_tokens` | Non | Borne supérieure du nombre de tokens générés. | | `temperature` | Non | Température d’échantillonnage. | | `response_format` | Non | `{"type": "text"}` (la valeur par défaut), ou `{"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}}` pour une sortie structurée. Exige la capacité `structured_output`. | | `tools`, `tool_choice` | Non | Outils de type fonction que le modèle peut appeler ([section 6.5](https://madeforagent.com/fr/lmsp/1.0/responses.md#tools)). Exige la capacité `tools`. | | `store` | Non | Demande au service de conserver la réponse, afin qu’elle puisse être récupérée plus tard et servir de `previous_response_id`. Vaut `false` par défaut. Ignoré par les services sans la capacité `conversations`. | | `previous_response_id` | Non | Poursuit à partir d’une réponse stockée. Exige la capacité `conversations`. | | `extensions` | Non | Extensions privées ([section 9.1](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#versioning)). | Une requête qui exige une capacité que le modèle n’a pas est rejetée avec `400` et `unsupported_capability`. Une requête qui ne tient pas dans la fenêtre de contexte est rejetée avec `400` et `context_length_exceeded`. Un service capable de stocker des conversations **PEUT** aussi prendre en charge `previous_response_id`. Sinon, chaque requête **DOIT** porter le contexte complet. Un service **NE DOIT PAS** compter sur la connexion HTTP pour conserver l’état de la conversation. ## 6.2 Réponse synchrone {#sync} Lorsque `stream` vaut `false`, le service renvoie `200 OK` avec un objet réponse une fois la génération terminée. ```json { "id": "resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF", "object": "response", "created_at": 1794200000, "status": "completed", "model": "qwen3:14b-q4_k_m", "output": [ { "id": "msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE", "type": "message", "role": "assistant", "content": [ { "type": "output_text", "text": "A local model service is a resident interface layer that discovers, manages and calls models on the user's own device." } ] } ], "usage": { "input_tokens": 28, "output_tokens": 31, "total_tokens": 59 }, "error": null, "incomplete_details": null } ``` | Champ | Signification | | --- | --- | | `id` | Identifiant de la réponse, tel que `resp_...`. | | `object` | Toujours `"response"`. | | `created_at` | Date de création, en secondes depuis l’epoch Unix. | | `status` | `in_progress`, `completed`, `incomplete`, `failed` ou `cancelled`. Une réponse synchrone est renvoyée à un état final. | | `model` | Identifiant du modèle qui a produit la réponse. | | `output` | Tableau d’éléments de sortie. | | `usage` | Compteurs de tokens : `input_tokens`, `output_tokens` et `total_tokens`. | | `error` | `null`, ou un objet problème ([section 9.3](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#errors)) lorsque `status` vaut `failed`. | | `incomplete_details` | `null`, ou un objet avec un `reason` tel que `max_output_tokens` lorsque `status` vaut `incomplete`. | Types d’éléments de sortie : | Type d’élément | Forme | | --- | --- | | `message` | `id`, `role` (`assistant`) et `content`, un tableau de parties `output_text` qui ont chacune un `text`. | | `function_call` | `id`, `call_id`, `name` et `arguments`, une chaîne encodée en JSON. | | `reasoning` | `id` et `summary`, un tableau de parties `summary_text` qui ont chacune un `text`. | Si la génération échoue, une requête synchrone reçoit un état d’erreur et un document problème ([section 9.3](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#errors)), et non un objet réponse. L’état `failed` apparaît dans les flux, les tâches et les réponses stockées. `GET /lmsp/v1/responses/{response_id}` renvoie une réponse qui a été stockée avec `store: true`. Il est facultatif et exige la capacité `conversations`. Un identifiant inconnu donne `404` avec `response_not_found`. ## 6.3 Streaming {#streaming} Pour diffuser en streaming, définissez `stream` dans la requête : ```json { "stream": true } ``` Le service répond `200 OK` avec `Content-Type: text/event-stream` et envoie des événements sémantiques. Chaque événement a un `id`, un nom `event` et un objet JSON `data` : ```text id: 1 event: response.created data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","status":"in_progress"} id: 2 event: response.output_item.added data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","output_index":0,"item":{"id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","type":"message","role":"assistant","content":[]}} id: 3 event: response.output_text.delta data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","item_id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","delta":"A local model "} id: 4 event: response.output_text.delta data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","item_id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","delta":"service is a resident interface layer."} id: 5 event: response.output_item.done data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","output_index":0,"item":{"id":"msg_01J8M6Q4W5C8H2K9P3S7Y1A6ZE","type":"message","role":"assistant","content":[{"type":"output_text","text":"A local model service is a resident interface layer."}]}} id: 6 event: response.completed data: {"response_id":"resp_01J8M6Q4W2T7N5R3V9X1Z8B0DF","status":"completed","usage":{"input_tokens":28,"output_tokens":12,"total_tokens":40}} ``` Au moins ces événements sont définis : | Événement | Signification | Champs de données | | --- | --- | --- | | `response.created` | La réponse a été créée. | `response_id`, `status` (`in_progress`) | | `response.output_item.added` | Un nouvel élément de sortie a commencé. | `response_id`, `output_index`, `item` | | `response.output_text.delta` | Du texte a été ajouté à un élément message. | `response_id`, `item_id`, `delta` | | `response.output_item.done` | Un élément de sortie est complet. | `response_id`, `output_index`, `item` | | `response.completed` | La réponse est terminée. Événement final. | `response_id`, `status`, `usage` | | `response.incomplete` | La génération s’est arrêtée prématurément, par exemple à la limite de tokens. Événement final. | `response_id`, `status`, `incomplete_details`, `usage` | | `response.failed` | La génération a échoué. Événement final. | `response_id`, `status`, `error` | | `response.cancelled` | La réponse a été annulée. Événement final. | `response_id`, `status` | | `error` | Un problème qui n’est pas lié à une seule réponse, après lequel le flux ne peut pas continuer. | `error`, un objet problème | Un service ferme le flux après un événement final ou un événement `error`. Les services **PEUVENT** envoyer des événements supplémentaires, par exemple pour les arguments d’appels d’outils, les images, le son et les deltas JSON structurés. Les clients **DOIVENT** ignorer les types d’événements qu’ils ne connaissent pas. Si le client ferme la connexion d’une requête en streaming, le service **DEVRAIT** cesser de générer. ## 6.4 Identifiants d’événements et reconnexion {#reconnection} L’`id` d’un événement **DOIT** être un numéro de séquence entier, strictement croissant au sein de la réponse, à partir de 1. Après une coupure de connexion, un client reprend en envoyant le dernier identifiant reçu. Il le fait avec un en-tête : ```http Last-Event-ID: 2 ``` ou avec un paramètre de requête : ```http GET /lmsp/v1/tasks/{task_id}/events?after=2 ``` Les deux s’adressent au point de terminaison d’événements d’une tâche ([section 7.4](https://madeforagent.com/fr/lmsp/1.0/tasks.md#events)). Le service ne rejoue que les événements dont le numéro de séquence est supérieur à 2. Si les deux sont présents, `after` l’emporte. Si les événements demandés sont plus anciens que la durée de conservation, le service répond `410 Gone` avec l’erreur `event_history_expired`. Le client récupère alors le résultat final à la place, avec `GET /lmsp/v1/tasks/{task_id}`. Une réponse diffusée directement depuis `POST /lmsp/v1/responses` appartient à cette connexion HTTP et ne peut pas être reprise. Un client qui a besoin d’une sortie reprenable **DEVRAIT** créer une [tâche](https://madeforagent.com/fr/lmsp/1.0/tasks.md) et suivre ses événements. ## 6.5 Appels d’outils {#tools} LMSP 1.0 définit des outils de type fonction que le client exécute. Le service n’exécute pas lui-même d’outils. La portée `tools:execute` est réservée aux extensions qui le font ([section 10.3](https://madeforagent.com/fr/lmsp/1.0/security.md#scopes)). D’abord, le client liste les outils. Chaque entrée a `type` défini à `function`, un `name`, une `description` et `parameters`, un objet JSON Schema. `tool_choice` vaut `auto` (la valeur par défaut), `none`, `required`, ou `{"type": "function", "name": "get_weather"}`. ```json { "model": "qwen3:14b-q4_k_m", "input": [ { "type": "message", "role": "user", "content": [ { "type": "input_text", "text": "What is the weather in Hangzhou?" } ] } ], "tools": [ { "type": "function", "name": "get_weather", "description": "Get the current weather for a city.", "parameters": { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] } } ], "tool_choice": "auto" } ``` Lorsque le modèle décide d’appeler un outil, la réponse contient un élément `function_call`. Ses `arguments` sont une chaîne encodée en JSON. Dans un flux, l’élément arrive complet dans `response.output_item.done`. ```json { "id": "resp_01J8M7B3N6Q9T2V5X8Z1C4D7FH", "object": "response", "created_at": 1794200050, "status": "completed", "model": "qwen3:14b-q4_k_m", "output": [ { "id": "fc_01J8M7B3N8R1S4W7Y0A3E6G9JK", "type": "function_call", "call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM", "name": "get_weather", "arguments": "{\"city\":\"Hangzhou\"}" } ], "usage": { "input_tokens": 74, "output_tokens": 18, "total_tokens": 92 }, "error": null, "incomplete_details": null } ``` Le client exécute l’outil, puis envoie une nouvelle requête qui porte le contexte complet : les éléments d’entrée précédents, l’élément `function_call` tel qu’il a été reçu, et un élément `function_call_output` avec le même `call_id`. Son `output` est une chaîne, généralement encodée en JSON. ```json { "type": "function_call_output", "call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM", "output": "{\"temperature_c\":17,\"condition\":\"light rain\"}" } ``` --- # Tâches asynchrones > Comment LMSP exécute les longues générations sous forme de tâches persistées, avec création de tâche, machine à états, annulation idempotente, flux d’événements et politiques de redémarrage des tâches inachevées. Source: https://madeforagent.com/fr/lmsp/1.0/tasks/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 7.1 Créer une tâche {#create} Un client crée une tâche en envoyant en POST la requête de réponse qu’il veut exécuter, enveloppée dans une enveloppe de tâche. Un en-tête `Idempotency-Key` est recommandé ([section 9.2](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#idempotency)). ```http POST /lmsp/v1/tasks Authorization: Bearer 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" } ``` | Champ | Obligatoire | Signification | | --- | --- | --- | | `type` | Oui | `response`, le seul type de tâche de la version 1.0. | | `input` | Oui | Une requête de réponse, exactement comme pour `POST /lmsp/v1/responses`. Son champ `stream` est ignoré. | | `on_restart` | Non | `fail` (la valeur par défaut), `retry` ou `resume`. Voir la [section 7.5](https://madeforagent.com/fr/lmsp/1.0/tasks.md#restart). | Le service **DOIT** persister la tâche avant de répondre. Il renvoie ensuite : ```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 } ``` | Champ de la tâche | Signification | | --- | --- | | `id` | Identifiant de la tâche, tel que `task_...`. | | `object` | Toujours `"task"`. | | `type` | `response`. | | `status` | L’état courant ([section 7.2](https://madeforagent.com/fr/lmsp/1.0/tasks.md#states)). | | `created_at`, `updated_at` | Dates en secondes depuis l’epoch Unix. | | `response_id` | Identifiant de la réponse que produit la tâche. Il est attribué à la création de la tâche. | | `events_url` | Chemin du flux d’événements. Présent lorsque la capacité `event_resume` vaut `true`. | | `on_restart` | La politique de redémarrage de la tâche. | | `response` | L’objet réponse une fois que `status` vaut `succeeded`, sinon `null`. | | `error` | Un objet problème ([section 9.3](https://madeforagent.com/fr/lmsp/1.0/common-rules.md#errors)) lorsque `status` vaut `failed`, sinon `null`. | `GET /lmsp/v1/tasks/{task_id}` renvoie l’objet tâche. Les clients qui n’utilisent pas les flux d’événements interrogent régulièrement ce point de terminaison. Un identifiant inconnu donne `404` avec `task_not_found`. Une tâche terminée ressemble à ceci : ```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 Machine à états {#states} ```text queued --> loading --> running --> succeeded | | | | | +--> failed | | +--> cancelling --> cancelled | +--------------> failed +--------------------------> cancelled ``` | État | Signification | États suivants | | --- | --- | --- | | `queued` | Acceptée et persistée, en attente de démarrage. | `loading`, `cancelled`, `failed` | | `loading` | Le modèle est en cours de chargement. | `running`, `cancelling`, `failed` | | `running` | Le modèle génère. | `succeeded`, `failed`, `cancelling` | | `cancelling` | L’annulation a été demandée et le backend ne s’est pas encore arrêté. | `cancelled` | | `succeeded` | Final. La réponse est complète. | aucun | | `failed` | Final. | aucun | | `cancelled` | Final. | aucun | Les états terminaux sont `succeeded`, `failed` et `cancelled`. Une tâche dans un état terminal **NE DOIT PAS** changer de nouveau. Une tâche dont la réponse se termine à l’état `incomplete`, par exemple à la limite de tokens, est `succeeded`. Chaque transition est atomique, si bien qu’une tâche n’est jamais à la fois annulée et terminée. La première transition validée l’emporte. ## 7.3 Annulation {#cancel} ```http POST /lmsp/v1/tasks/{task_id}/cancel ``` Le service renvoie `200 OK` et l’objet tâche courant. Une tâche `queued` passe immédiatement à `cancelled`. Une tâche `loading` ou `running` passe à `cancelling` jusqu’à l’arrêt du backend, puis à `cancelled`. L’annulation **DOIT** être idempotente. Annuler une tâche déjà `cancelling` ou `cancelled` renvoie la tâche courante et ne produit aucune nouvelle erreur. Annuler une tâche qui a déjà `succeeded` ou `failed` reçoit la réponse `409` avec `task_not_cancelable`. Un identifiant inconnu donne `404` avec `task_not_found`. ## 7.4 Flux d’événements {#events} ```http GET /lmsp/v1/tasks/{task_id}/events Accept: text/event-stream ``` Ce point de terminaison est facultatif. Il est disponible lorsque la capacité `event_resume` vaut `true`. - Les événements sont les événements de réponse de la [section 6.3](https://madeforagent.com/fr/lmsp/1.0/responses.md#streaming), pour la réponse que produit la tâche. La numérotation et la reprise suivent la [section 6.4](https://madeforagent.com/fr/lmsp/1.0/responses.md#reconnection). - Le flux commence par `response.created`, qui est enregistré à l’acceptation de la tâche. Il se termine par un seul événement final qui correspond à l’issue : `response.completed`, `response.incomplete`, `response.failed` ou `response.cancelled`. - Un client qui se connecte tardivement reçoit d’abord les événements qu’il a manqués, puis les événements en direct. Le service ferme le flux après l’événement final. - Les événements sont conservés pendant une durée de conservation ([section 11.2](https://madeforagent.com/fr/lmsp/1.0/persistence.md#rules)). Les événements plus anciens donnent `410 Gone` avec `event_history_expired`. ## 7.5 Sémantique du redémarrage {#restart} `on_restart` indique ce qui arrive à une tâche inachevée lorsque le service redémarre : | Valeur | Comportement | | --- | --- | | `fail` | La valeur par défaut. Le service marque la tâche inachevée `failed`, avec le code d’erreur `server_restarted`. | | `retry` | Le service exécute de nouveau la tâche depuis le début. | | `resume` | Le service reprend à partir d’un instantané. Cela n’est permis que lorsque le backend prend explicitement en charge les instantanés reprenables. Sinon, la requête de création est rejetée avec `400` et `unsupported_capability`. | Une tâche à l’état `cancelling` lors du redémarrage du service achève son annulation et passe à `cancelled`, quelle que soit sa politique. `retry` n’est pas recommandé comme valeur par défaut, car la tâche a peut-être déjà exécuté des outils ou produit des effets de bord externes. Un client qui choisit `retry` **DOIT** le combiner avec un `Idempotency-Key` et rendre idempotents ses appels d’outils. --- # Compatibilité OpenAI et Ollama > Comment un service LMSP reste compatible avec les clients OpenAI et Ollama existants grâce à une fine couche de conversion de données au-dessus d’un seul cœur d’exécution, et où s’arrête cette compatibilité. Source: https://madeforagent.com/fr/lmsp/1.0/compatibility/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 8.1 Points de terminaison compatibles OpenAI {#openai} Un service **DEVRAIT** proposer une interface compatible OpenAI à côté de l’interface LMSP, et la déclarer dans `interfaces` avec `kind` défini à `openai`. Pour couvrir les clients existants, un service qui le fait **DOIT** implémenter au moins ces points de terminaison sous le préfixe `/v1` : | Point de terminaison | Remarques | | --- | --- | | `GET /v1/models` | Liste les modèles du catalogue LMSP. Chaque `id` est l’identifiant de modèle LMSP. | | `POST /v1/chat/completions` | Chat Completions, avec et sans streaming. | | `POST /v1/responses` | La forme OpenAI Responses. | | `POST /v1/embeddings` | L’interface principale de LMSP 1.0 n’a pas de point de terminaison d’embeddings. L’adaptateur sert ce point de terminaison directement, pour les modèles dont `capabilities.embeddings` vaut `true`. | Ces points de terminaison acceptent les mêmes jetons porteurs que l’interface LMSP. Un client qui parle le protocole OpenAI définit le jeton LMSP comme clé d’API. Une première implémentation peut commencer par `/v1/models` et `/v1/chat/completions` ([page 12](https://madeforagent.com/fr/lmsp/1.0/mvp.md)). ## 8.2 Points de terminaison compatibles Ollama {#ollama} Un service **DEVRAIT** aussi fournir ces points de terminaison, afin que les clients écrits pour Ollama fonctionnent eux aussi : | Point de terminaison | Remarques | | --- | --- | | `GET /api/tags` | Liste les modèles du catalogue LMSP. | | `POST /api/chat` | Chat. | | `POST /api/generate` | Génération de texte simple. | Un service qui les fournit déclare une interface avec `kind` défini à `ollama`. ## 8.3 Un seul cœur d’exécution {#core} La couche de compatibilité **DOIT** se contenter de convertir des données. Elle **NE DOIT PAS** créer une seconde logique de gestion des modèles. Une requête sur une interface de compatibilité est transposée en une réponse LMSP, s’exécute sur le même cœur et le même adaptateur qu’une requête native, et utilise le même catalogue de modèles et la même authentification. ```text OpenAI Chat Completions | conversion de la requête v LMSP Response | adaptation au backend v llama.cpp / Ollama / vLLM / autres environnements d’exécution ``` Sur les points de terminaison `/v1` et `/api`, un service **DEVRAIT** signaler les erreurs dans le format que définit l’API correspondante, afin que les clients non modifiés puissent les interpréter. L’interface LMSP utilise toujours `application/problem+json`. ## 8.4 Limites {#boundaries} La compatibilité a des limites, et il vaut mieux les énoncer clairement : - Un client compatible OpenAI existant n’a généralement besoin que d’un `base_url` modifié. Il ne bénéficie pas automatiquement de la découverte LMSP. - Seuls les clients qui prennent en charge LMSP peuvent découvrir un service automatiquement, lire ses capacités détaillées, reprendre des flux d’événements et gérer des tâches asynchrones. - Aucun protocole côté serveur ne peut faire fonctionner un client qui n’est pas configurable et n’accepte que les adresses officielles du cloud. --- # Règles communes > Règles partagées par tous les points de terminaison LMSP, avec les en-têtes de version et les extensions, les clés d’idempotence, le format d’erreur problem+json et ses codes, et le contrôle d’état. Source: https://madeforagent.com/fr/lmsp/1.0/common-rules/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 9.1 Versions et extensions {#versioning} Chaque requête LMSP **PEUT** porter ces en-têtes : ```http 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é : ```json { "extensions": { "com.example.cache": { "enabled": true } } } ``` ## 9.2 Idempotence {#idempotency} 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 : ```http Idempotency-Key: ``` 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](https://madeforagent.com/fr/lmsp/1.0/tasks.md). ## 9.3 Erreurs {#errors} Chaque erreur de l’interface LMSP utilise `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 } ``` | 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 {#health} ```http GET /lmsp/v1/health ``` ```json { "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. --- # Sécurité locale > Exigences de sécurité des services LMSP, avec liaison à loopback, appairage et jetons porteurs, portées, vérifications d’Origin et de Host contre les pages web malveillantes, mode LAN et règles de journalisation. Source: https://madeforagent.com/fr/lmsp/1.0/security/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 10.1 Socle {#baseline} Écouter uniquement sur localhost n’offre pas une sécurité absolue : une page web malveillante peut toujours essayer d’atteindre les ports locaux. LMSP combine donc plusieurs mesures. - Un service **DOIT** se lier par défaut aux adresses de loopback. Il **NE DOIT PAS** écouter sur `0.0.0.0`, ni sur aucune autre adresse hors loopback, sauf si le mode LAN est activé ([section 10.5](https://madeforagent.com/fr/lmsp/1.0/security.md#lan)). - Au premier lancement, un service **DEVRAIT** générer un secret de service aléatoire à forte entropie, et l’utiliser, plutôt que toute valeur par défaut intégrée, pour émettre et vérifier les jetons. - Chaque requête vers l’interface principale **DOIT** porter un jeton porteur valide, sauf pour les points de terminaison d’amorçage listés à la [section 4.2](https://madeforagent.com/fr/lmsp/1.0/endpoints.md#conventions). Provenir de loopback ne suffit jamais à lui seul. ## 10.2 Appairage et jetons {#pairing} Un client obtient son propre jeton porteur grâce à un code d’appairage local. L’utilisateur demande au service d’afficher un code d’appairage, de la manière que le service propose, et le client le soumet : ```http POST /lmsp/v1/pair Content-Type: application/json ``` ```json { "client_name": "example-client", "pairing_code": "K7QD-4M2X", "scopes": ["inference"] } ``` | Champ de la requête | Signification | | --- | --- | | `client_name` | Nom d’affichage du client, montré à l’utilisateur. | | `pairing_code` | Le code que l’utilisateur a obtenu auprès du service. | | `scopes` | Liste facultative de portées demandées. Vaut `["inference"]` par défaut. | Le service répond avec un jeton. Le `token_type` vaut toujours `Bearer` : ```json { "client_id": "cli_01J8MAT3W6X9B2D5F8H1K4N7QZ", "access_token": "lmsp_example_3f9a1c52e7d84b60", "token_type": "Bearer", "scopes": ["inference"] } ``` Le client envoie ensuite `Authorization: Bearer ` avec chaque requête. - Un code d’appairage **DOIT** être à usage unique et **DEVRAIT** expirer en 5 minutes. Il **DEVRAIT** porter au moins 40 bits d’entropie. Un service **DOIT** limiter le débit des tentatives échouées. Un code erroné ou expiré reçoit la réponse `401` avec `unauthorized`. - Les jetons sont indépendants pour chaque client, de sorte que l’utilisateur peut en révoquer un sans affecter les autres. Un service **DEVRAIT** permettre à l’utilisateur de lister et de révoquer les clients appairés. - Un client **DEVRAIT** conserver son jeton dans le trousseau ou le gestionnaire d’identifiants du système d’exploitation. Un service **DEVRAIT** ne stocker qu’une empreinte de chaque jeton. - Un jeton absent, invalide ou révoqué reçoit la réponse `401`, `unauthorized` et un en-tête `WWW-Authenticate: Bearer`. Un jeton valide qui n’a pas la portée dont un point de terminaison a besoin reçoit la réponse `403` avec `forbidden`. ## 10.3 Portées {#scopes} Les autorisations sont réparties en portées distinctes. Télécharger des modèles, supprimer des modèles et exécuter des outils ne passent jamais par la portée d’inférence. | Portée | Autorise | | --- | --- | | `inference` | Lire le catalogue de modèles, créer des réponses et des tâches, et lire et annuler les tâches du client lui-même. | | `models:manage` | Charger et décharger des modèles. | | `models:install` | Réservé. Télécharger et supprimer des modèles. | | `tools:execute` | Réservé. Exécuter des outils côté service. | Les tâches et les réponses stockées appartiennent au client qui les a créées. Un service **DEVRAIT** répondre à la requête d’un autre client comme si elles n’existaient pas (`task_not_found` ou `response_not_found`). ## 10.4 Protections du navigateur et du réseau {#browser} - Un service **DOIT** rejeter par défaut les requêtes de navigateur inter-origines, et n’autoriser que les valeurs d’`Origin` explicitement configurées. Une requête avec toute autre `Origin` reçoit la réponse `403` avec `forbidden`. - Lorsqu’une origine est autorisée, le service répond à ses requêtes de pré-vérification CORS et envoie `Access-Control-Allow-Origin` avec cette origine exacte, jamais avec `*`. - Un service **DOIT** valider l’en-tête `Host`, pour empêcher le DNS rebinding. Il n’accepte que les noms d’hôte qu’il sert : les noms et adresses de loopback, plus les noms configurés pour le mode LAN. Toute autre valeur reçoit la réponse `403` avec `forbidden`. ## 10.5 Mode LAN {#lan} Le mode LAN signifie écouter au-delà des adresses de loopback. - Un service **NE DOIT PAS** activer le mode LAN sauf si l’utilisateur l’active explicitement. - En mode LAN, un service **DOIT** exiger une authentification, et **DEVRAIT** aussi activer TLS. Un client **NE DEVRAIT PAS** envoyer de jeton en HTTP non chiffré à une adresse hors loopback, sauf si l’utilisateur l’autorise explicitement. - L’annonce mDNS n’est permise qu’en mode LAN, lorsque l’utilisateur a aussi activé la découverte sur le réseau local ([section 3.2](https://madeforagent.com/fr/lmsp/1.0/discovery.md#mdns)). ## 10.6 Journalisation et vie privée {#logging} - Les chemins de modèles, les journaux, les prompts et le contenu généré **NE DOIVENT PAS** apparaître dans les annonces mDNS. - Par défaut, un service **DEVRAIT** ne journaliser que des métadonnées (dates, points de terminaison, codes d’état, identifiants, nombres de tokens et durées). Il **NE DEVRAIT PAS** journaliser les prompts complets ni le contenu généré. - Les réponses de santé et les détails d’erreur **NE DOIVENT PAS** contenir de chemins de modèles, de prompts, de jetons d’accès ni d’autres informations sensibles. --- # Persistance > Comment un service LMSP stocke son état, avec une base SQLite intégrée, les tables à conserver, les règles transactionnelles pour les tâches et les événements, la conservation et la reprise au démarrage. Source: https://madeforagent.com/fr/lmsp/1.0/persistence/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 11.1 Stockage {#storage} Un service **DEVRAIT** conserver son état dans une base [SQLite](https://www.sqlite.org/) intégrée. Un jeu de tables suggéré : | Table | Contenu | | --- | --- | | `service_config` | Identité et configuration du service. | | `clients` | Clients appairés, empreintes des jetons et portées. | | `models` | Métadonnées des modèles et empreintes de leur contenu. | | `responses` | Réponses stockées. | | `tasks` | Tâches asynchrones. | | `task_events` | Le journal des événements de chaque tâche, avec des numéros de séquence. | | `idempotency_keys` | Clés d’idempotence, empreintes des requêtes et résultats. | Les fichiers de modèles **DOIVENT** rester en dehors de la base de données. La base ne contient que des métadonnées et des empreintes de contenu. Les noms et la structure des tables relèvent de l’implémentation. Ce que les clients peuvent observer, et ce qui doit être interopérable, c’est le comportement décrit dans les deux sections suivantes. ## 11.2 Règles {#rules} Quel que soit le stockage utilisé, un service : - **DOIT** persister une tâche avant de renvoyer `202 Accepted`. - **DOIT** mettre à jour les numéros de séquence des événements et l’état de la tâche dans la même transaction. - **DOIT** rendre atomique la transition d’annulation, pour éviter la situation de concurrence d’une tâche annulée puis terminée. - **DEVRAIT** conserver les tâches et les événements terminés pendant une durée de conservation configurable. - **NE DOIT PAS** supprimer les tâches inachevées lors du nettoyage des journaux. - **DOIT**, au démarrage, parcourir les tâches `queued`, `loading`, `running` et `cancelling` restantes, et appliquer la politique de redémarrage de chacune ([section 7.5](https://madeforagent.com/fr/lmsp/1.0/tasks.md#restart)). ## 11.3 Reprise au démarrage {#recovery} Le tableau indique l’état vers lequel une tâche restante est déplacée, selon sa politique `on_restart` : | État trouvé au démarrage | `fail` | `retry` | `resume` | | --- | --- | --- | --- | | `queued` | `failed` | `queued` | `queued` | | `loading` | `failed` | `queued` | `queued` | | `running` | `failed` | `queued` | `running`, en reprenant à partir de l’instantané | | `cancelling` | `cancelled` | `cancelled` | `cancelled` | Une tâche déplacée vers `failed` reçoit le code d’erreur `server_restarted` et un événement `response.failed`. Une tâche déplacée vers `cancelled` reçoit un événement `response.cancelled`. Le nouvel état et son événement sont écrits dans une seule transaction ([section 11.2](https://madeforagent.com/fr/lmsp/1.0/persistence.md#rules)). --- # Périmètre minimal viable > Un périmètre suggéré pour une première implémentation de LMSP, avec les dix éléments qui forment une boucle fermée utilisable et les parties de la spécification qui peuvent attendre des versions ultérieures. Source: https://madeforagent.com/fr/lmsp/1.0/mvp/ Language: fr Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 12.1 Première version {#scope} La première version n’a pas à implémenter toutes les fonctions multimodales, le téléchargement de modèles ni la voix en temps réel. Elle forme une boucle fermée utilisable dès qu’elle fournit : 1. La découverte du service via `/.well-known/lmsp.json`. 2. L’annonce facultative sur le réseau local de `_lmsp._tcp.local.`. 3. `GET /lmsp/v1/models`. 4. `POST /lmsp/v1/responses`, à la fois en synchrone et sous forme de flux SSE. 5. Les tâches asynchrones : créer, consulter et annuler, avec persistance SQLite. 6. La reprise des flux interrompus avec `Last-Event-ID` ou `after`. 7. Les jetons porteurs, l’appairage local, et la protection `Origin` et `Host`. 8. Les points de terminaison `/v1/models` et `/v1/chat/completions` compatibles OpenAI. 9. Un fichier de contrat OpenAPI 3.2 et des tests de conformité multilingues. 10. Au moins un vrai backend, et une vérification que les tâches se rétablissent correctement après un redémarrage du service. L’idée de cette conception : LMSP fournit l’ensemble complet des capacités, l’interface OpenAI fournit une compatibilité prête à l’emploi, mDNS et la description du service fournissent la découverte automatique, et le modèle de tâches SQLite fournit la persistance locale. ## 12.2 Ce qui peut attendre {#later} Tout ce que la liste ci-dessus ne mentionne pas peut suivre dans des versions ultérieures. Cela comprend les points de terminaison facultatifs (réponses stockées, et chargement et déchargement de modèles), les points de terminaison `/v1/responses` et `/v1/embeddings` d’OpenAI, l’API compatible Ollama, et tous les types de contenu autres que le texte. Ce périmètre est un chemin vers une première version utilisable, pas un profil de conformité. Un service qui se réclame de LMSP 1.0 implémente toujours chaque point de terminaison obligatoire de la [page 4](https://madeforagent.com/fr/lmsp/1.0/endpoints.md) et le comportement obligatoire décrit dans les autres pages.