Respuestas y streaming

6.1 Solicitud

POST /lmsp/v1/responses
Authorization: Bearer <token>
Content-Type: application/json
Idempotency-Key: 01J8M5T7Z2K4N6Q8S0V3X5B9DG
LMSP-Version: 1.0
{
  "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).
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). 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).

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

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

{
  "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) 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), 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

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

{
  "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:

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

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:

Last-Event-ID: 2

o con un parámetro de consulta:

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

Ambos van al endpoint de eventos de una tarea (sección 7.4). 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 y seguir sus eventos.

6.5 Llamadas a herramientas

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).

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"}.

{
  "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.

{
  "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.

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