# 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 <token>
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\"}"
}
```
