# 响应与流式传输

> LMSP 的核心对话接口：Responses 风格的请求与输出项、同步与流式生成、服务器发送事件的类型、事件 id、断线重连以及工具调用。

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

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

核心协议采用 Responses 风格的 `input`/`output` 结构，而不是只支持简单的 messages 字符串，以便用同一种请求格式统一承载：

- 多轮消息；
- 文本、图片、音频和文件；
- 工具调用及工具结果；
- 结构化输出；
- 推理摘要；
- 多模态输出。

LMSP 1.0 只定义文本内容。图片、音频和文件的内容类型留待后续版本。

| 字段 | 必需 | 含义 |
| --- | --- | --- |
| `model` | 是 | 要使用的模型 id。 |
| `input` | 是 | 输入项数组。`message` 项包含 `role`（`system`、`user` 或 `assistant`）和由多个部分组成的 `content` 数组，例如 `input_text`。使用工具时会增加 `function_call` 和 `function_call_output` 项（[第 6.5 节](https://madeforagent.com/zh-cn/lmsp/1.0/responses.md#tools)）。 |
| `stream` | 否 | 为 `true` 时接收服务器发送事件，默认为 `false`。 |
| `max_output_tokens` | 否 | 生成 token 数的上限。 |
| `temperature` | 否 | 采样温度。 |
| `response_format` | 否 | `{"type": "text"}`（默认），或用于结构化输出的 `{"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}}`。需要 `structured_output` 能力。 |
| `tools`、`tool_choice` | 否 | 模型可以调用的函数工具（[第 6.5 节](https://madeforagent.com/zh-cn/lmsp/1.0/responses.md#tools)）。需要 `tools` 能力。 |
| `store` | 否 | 请求服务保存该响应，以便之后查询，并可用作 `previous_response_id`。默认为 `false`。没有 `conversations` 能力的服务会忽略它。 |
| `previous_response_id` | 否 | 接着已保存的某个响应继续对话。需要 `conversations` 能力。 |
| `extensions` | 否 | 私有扩展（[第 9.1 节](https://madeforagent.com/zh-cn/lmsp/1.0/common-rules.md#versioning)）。 |

请求需要模型不具备的能力时，返回 `400` 和 `unsupported_capability`。请求放不进上下文窗口时，返回 `400` 和 `context_length_exceeded`。

能够保存会话的服务**可以**额外支持 `previous_response_id`；否则每次请求都**必须**携带完整上下文。服务**不得**依赖 HTTP 连接保存对话状态。

## 6.2 同步响应 {#sync}

当 `stream` 为 `false` 时，服务在生成结束后返回 `200 OK` 和一个响应对象。

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

| 字段 | 含义 |
| --- | --- |
| `id` | 响应标识符，例如 `resp_...`。 |
| `object` | 始终为 `"response"`。 |
| `created_at` | 创建时间，自 Unix 纪元起的秒数。 |
| `status` | `in_progress`、`completed`、`incomplete`、`failed` 或 `cancelled`。同步响应返回时已处于最终状态。 |
| `model` | 生成该响应的模型 id。 |
| `output` | 输出项数组。 |
| `usage` | token 用量：`input_tokens`、`output_tokens` 和 `total_tokens`。 |
| `error` | `null`；当 `status` 为 `failed` 时是一个 problem 对象（[第 9.3 节](https://madeforagent.com/zh-cn/lmsp/1.0/common-rules.md#errors)）。 |
| `incomplete_details` | `null`；当 `status` 为 `incomplete` 时是带有 `reason`（例如 `max_output_tokens`）的对象。 |

输出项类型：

| 项类型 | 结构 |
| --- | --- |
| `message` | `id`、`role`（`assistant`）和 `content`，后者是 `output_text` 部分的数组，每个部分带有 `text`。 |
| `function_call` | `id`、`call_id`、`name` 和 `arguments`，后者是 JSON 编码的字符串。 |
| `reasoning` | `id` 和 `summary`，后者是 `summary_text` 部分的数组，每个部分带有 `text`。 |

如果生成失败，同步请求返回错误状态码和 problem 文档（[第 9.3 节](https://madeforagent.com/zh-cn/lmsp/1.0/common-rules.md#errors)），而不是响应对象。`failed` 状态只出现在流、任务和已保存的响应中。

`GET /lmsp/v1/responses/{response_id}` 返回以 `store: true` 保存的响应。它是可选接口，需要 `conversations` 能力。未知的 id 返回 `404` 和 `response_not_found`。

## 6.3 流式响应 {#streaming}

要使用流式传输，在请求中设置 `stream`：

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

服务返回 `200 OK` 和 `Content-Type: text/event-stream`，并发送语义化事件。每个事件包含 `id`、`event` 名称和一个 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}}
```

最少定义以下事件：

| 事件 | 含义 | 数据字段 |
| --- | --- | --- |
| `response.created` | 响应已创建。 | `response_id`、`status`（`in_progress`） |
| `response.output_item.added` | 开始了一个新的输出项。 | `response_id`、`output_index`、`item` |
| `response.output_text.delta` | 文本被追加到某个 message 项。 | `response_id`、`item_id`、`delta` |
| `response.output_item.done` | 一个输出项已完成。 | `response_id`、`output_index`、`item` |
| `response.completed` | 响应已完成。最终事件。 | `response_id`、`status`、`usage` |
| `response.incomplete` | 生成提前停止，例如达到 token 上限。最终事件。 | `response_id`、`status`、`incomplete_details`、`usage` |
| `response.failed` | 生成失败。最终事件。 | `response_id`、`status`、`error` |
| `response.cancelled` | 响应已取消。最终事件。 | `response_id`、`status` |
| `error` | 与某个具体响应无关的问题，出现后流无法继续。 | `error`，一个 problem 对象 |

服务在最终事件或 `error` 事件之后关闭流。

服务**可以**发送额外的事件，例如工具调用参数、图片、音频和结构化 JSON 增量。客户端**必须**忽略不认识的事件类型。

如果客户端关闭了流式请求的连接，服务**应**停止生成。

## 6.4 事件 id 与重连 {#reconnection}

事件的 `id` **必须**是整数序号，在该响应内严格递增，从 1 开始。

连接断开后，客户端通过发送自己收到的最后一个 id 来恢复。可以使用请求头：

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

或使用查询参数：

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

两者都发往任务的事件接口（[第 7.4 节](https://madeforagent.com/zh-cn/lmsp/1.0/tasks.md#events)）。服务只补发序号大于 2 的事件。两者同时出现时，以 `after` 为准。

如果请求的事件已超出保留期，服务返回 `410 Gone` 和错误码 `event_history_expired`，客户端改为通过 `GET /lmsp/v1/tasks/{task_id}` 获取最终结果。

直接从 `POST /lmsp/v1/responses` 流式返回的响应属于该 HTTP 连接，无法恢复。需要可恢复输出的客户端**应**创建[任务](https://madeforagent.com/zh-cn/lmsp/1.0/tasks.md)并跟随它的事件。

## 6.5 工具调用 {#tools}

LMSP 1.0 定义由客户端执行的函数工具，服务本身不运行工具。`tools:execute` 权限范围预留给会执行工具的扩展（[第 10.3 节](https://madeforagent.com/zh-cn/lmsp/1.0/security.md#scopes)）。

首先，客户端列出工具。每个条目的 `type` 为 `function`，并带有 `name`、`description` 和 `parameters`（一个 JSON Schema 对象）。`tool_choice` 可以是 `auto`（默认）、`none`、`required`，或 `{"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"
}
```

当模型决定调用工具时，响应中会包含一个 `function_call` 项，其 `arguments` 是 JSON 编码的字符串。在流中，该项会以完整形式出现在 `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
}
```

客户端运行工具，然后发送一个携带完整上下文的新请求：之前的输入项、收到的 `function_call` 项，以及一个 `call_id` 相同的 `function_call_output` 项。其 `output` 是字符串，通常为 JSON 编码。

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