# Respuestas y streaming

> La interfaz de conversación principal de LMSP, con solicitudes y elementos de salida al estilo Responses, generación síncrona y en streaming, eventos enviados por el servidor, reconexión y llamadas a herramientas.

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

## 6.1 Solicitud {#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
}
```

El protocolo principal usa una estructura `input` y `output` al estilo Responses en lugar de una simple lista de cadenas de mensajes, de modo que una única forma de solicitud pueda transportar:

- mensajes de varios turnos;
- texto, imágenes, audio y archivos;
- llamadas a herramientas y resultados de herramientas;
- salida estructurada;
- resúmenes de razonamiento;
- salida multimodal.

LMSP 1.0 define solo contenido de texto. Los tipos de contenido de imagen, audio y archivo se reservan para versiones posteriores.

| Campo | Obligatorio | Significado |
| --- | --- | --- |
| `model` | Sí | Id del modelo que se usará. |
| `input` | Sí | Matriz de elementos de entrada. Un elemento `message` tiene un `role` (`system`, `user` o `assistant`) y una matriz `content` de partes, como `input_text`. El uso de herramientas añade los elementos `function_call` y `function_call_output` ([sección 6.5](https://madeforagent.com/es/lmsp/1.0/responses.md#tools)). |
| `stream` | No | `true` para recibir eventos enviados por el servidor. Por defecto es `false`. |
| `max_output_tokens` | No | Límite superior del número de tokens generados. |
| `temperature` | No | Temperatura de muestreo. |
| `response_format` | No | `{"type": "text"}` (el valor por defecto), o `{"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}}` para salida estructurada. Requiere la capacidad `structured_output`. |
| `tools`, `tool_choice` | No | Herramientas de función que el modelo puede invocar ([sección 6.5](https://madeforagent.com/es/lmsp/1.0/responses.md#tools)). Requiere la capacidad `tools`. |
| `store` | No | Pide al servicio que conserve la respuesta, para poder recuperarla más tarde y usarla como `previous_response_id`. Por defecto es `false`. Los servicios sin la capacidad `conversations` lo ignoran. |
| `previous_response_id` | No | Continúa desde una respuesta almacenada. Requiere la capacidad `conversations`. |
| `extensions` | No | Extensiones privadas ([sección 9.1](https://madeforagent.com/es/lmsp/1.0/common-rules.md#versioning)). |

Una solicitud que necesita una capacidad de la que el modelo carece se rechaza con `400` y `unsupported_capability`. Una solicitud que no cabe en la ventana de contexto se rechaza con `400` y `context_length_exceeded`.

Un servicio que pueda almacenar conversaciones **PUEDE** admitir también `previous_response_id`. En caso contrario, cada solicitud **DEBE** llevar el contexto completo. Un servicio **NO DEBE** depender de la conexión HTTP para mantener el estado de la conversación.

## 6.2 Respuesta síncrona {#sync}

Cuando `stream` es `false`, el servicio devuelve `200 OK` con un objeto de respuesta una vez terminada la generación.

```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
}
```

| Campo | Significado |
| --- | --- |
| `id` | Identificador de la respuesta, como `resp_...`. |
| `object` | Siempre `"response"`. |
| `created_at` | Hora de creación, en segundos desde la época Unix. |
| `status` | `in_progress`, `completed`, `incomplete`, `failed` o `cancelled`. Una respuesta síncrona se devuelve en un estado final. |
| `model` | Id del modelo que produjo la respuesta. |
| `output` | Matriz de elementos de salida. |
| `usage` | Recuentos de tokens: `input_tokens`, `output_tokens` y `total_tokens`. |
| `error` | `null`, o un objeto de problema ([sección 9.3](https://madeforagent.com/es/lmsp/1.0/common-rules.md#errors)) cuando `status` es `failed`. |
| `incomplete_details` | `null`, o un objeto con un `reason` como `max_output_tokens` cuando `status` es `incomplete`. |

Tipos de elemento de salida:

| Tipo de elemento | Forma |
| --- | --- |
| `message` | `id`, `role` (`assistant`) y `content`, una matriz de partes `output_text` que tienen cada una un `text`. |
| `function_call` | `id`, `call_id`, `name` y `arguments`, una cadena codificada en JSON. |
| `reasoning` | `id` y `summary`, una matriz de partes `summary_text` que tienen cada una un `text`. |

Si la generación falla, una solicitud síncrona recibe como respuesta un estado de error y un documento de problema ([sección 9.3](https://madeforagent.com/es/lmsp/1.0/common-rules.md#errors)), no un objeto de respuesta. El estado `failed` aparece en los flujos, las tareas y las respuestas almacenadas.

`GET /lmsp/v1/responses/{response_id}` devuelve una respuesta que se almacenó con `store: true`. Es opcional y requiere la capacidad `conversations`. Un id desconocido produce `404` con `response_not_found`.

## 6.3 Streaming {#streaming}

Para recibir la respuesta en streaming, establece `stream` en la solicitud:

```json
{
  "stream": true
}
```

El servicio responde `200 OK` con `Content-Type: text/event-stream` y envía eventos semánticos. Cada evento tiene un `id`, un nombre `event` y un objeto 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}}
```

Se definen al menos estos eventos:

| Evento | Significado | Campos de datos |
| --- | --- | --- |
| `response.created` | Se creó la respuesta. | `response_id`, `status` (`in_progress`) |
| `response.output_item.added` | Comenzó un nuevo elemento de salida. | `response_id`, `output_index`, `item` |
| `response.output_text.delta` | Se añadió texto a un elemento de mensaje. | `response_id`, `item_id`, `delta` |
| `response.output_item.done` | Un elemento de salida está completo. | `response_id`, `output_index`, `item` |
| `response.completed` | La respuesta terminó. Evento final. | `response_id`, `status`, `usage` |
| `response.incomplete` | La generación se detuvo antes de tiempo, por ejemplo al llegar al límite de tokens. Evento final. | `response_id`, `status`, `incomplete_details`, `usage` |
| `response.failed` | La generación falló. Evento final. | `response_id`, `status`, `error` |
| `response.cancelled` | Se canceló la respuesta. Evento final. | `response_id`, `status` |
| `error` | Un problema no vinculado a una sola respuesta, tras el cual el flujo no puede continuar. | `error`, un objeto de problema |

Un servicio cierra el flujo después de un evento final o de un evento `error`.

Los servicios **PUEDEN** enviar eventos adicionales, por ejemplo para argumentos de llamadas a herramientas, imágenes, audio y deltas JSON estructurados. Los clientes **DEBEN** ignorar los tipos de evento que no conozcan.

Si el cliente cierra la conexión de una solicitud en streaming, el servicio **DEBERÍA** dejar de generar.

## 6.4 Ids de evento y reconexión {#reconnection}

El `id` de un evento **DEBE** ser un número de secuencia entero estrictamente creciente dentro de la respuesta, que empieza en 1.

Tras una conexión interrumpida, un cliente reanuda enviando el último id que recibió. Lo hace con una cabecera:

```http
Last-Event-ID: 2
```

o con un parámetro de consulta:

```http
GET /lmsp/v1/tasks/{task_id}/events?after=2
```

Ambos van al endpoint de eventos de una tarea ([sección 7.4](https://madeforagent.com/es/lmsp/1.0/tasks.md#events)). El servicio reproduce solo los eventos cuyo número de secuencia es mayor que 2. Si están presentes los dos, prevalece `after`.

Si los eventos solicitados son anteriores al período de retención, el servicio responde `410 Gone` con el error `event_history_expired`. El cliente obtiene entonces el resultado final con `GET /lmsp/v1/tasks/{task_id}`.

Una respuesta transmitida directamente desde `POST /lmsp/v1/responses` pertenece a esa conexión HTTP y no se puede reanudar. Un cliente que necesite una salida reanudable **DEBERÍA** crear una [tarea](https://madeforagent.com/es/lmsp/1.0/tasks.md) y seguir sus eventos.

## 6.5 Llamadas a herramientas {#tools}

LMSP 1.0 define herramientas de función que ejecuta el cliente. El servicio no ejecuta herramientas por sí mismo. El ámbito `tools:execute` se reserva para las extensiones que sí lo hacen ([sección 10.3](https://madeforagent.com/es/lmsp/1.0/security.md#scopes)).

Primero, el cliente enumera las herramientas. Cada entrada tiene `type` con el valor `function`, un `name`, una `description` y `parameters`, un objeto JSON Schema. `tool_choice` es `auto` (el valor por defecto), `none`, `required` o `{"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"
}
```

Cuando el modelo decide llamar a una herramienta, la respuesta contiene un elemento `function_call`. Sus `arguments` son una cadena codificada en JSON. En un flujo, el elemento llega completo en `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
}
```

El cliente ejecuta la herramienta y luego envía una nueva solicitud que lleva el contexto completo: los elementos de entrada anteriores, el elemento `function_call` tal como se recibió y un elemento `function_call_output` con el mismo `call_id`. Su `output` es una cadena, normalmente codificada en JSON.

```json
{
  "type": "function_call_output",
  "call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM",
  "output": "{\"temperature_c\":17,\"condition\":\"light rain\"}"
}
```
