# レスポンスとストリーミング

> LMSP のコア会話インターフェース。Responses 形式のリクエストと出力アイテム、同期生成とストリーミング生成、サーバー送信イベントの種類、イベント ID、再接続、ツール呼び出しを定めます。

Source: https://madeforagent.com/ja/lmsp/1.0/responses/
Language: ja
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` の構造を使う。これにより、1 つのリクエスト形式で次のものを運べる。

- 複数ターンのメッセージ
- テキスト、画像、音声、ファイル
- ツール呼び出しとツール結果
- 構造化出力
- 推論の要約
- マルチモーダル出力

LMSP 1.0 が定義するのはテキストコンテンツだけである。画像、音声、ファイルのコンテンツタイプは、将来のバージョンのために予約されている。

| フィールド | 必須 | 意味 |
| --- | --- | --- |
| `model` | はい | 使用するモデルの ID。 |
| `input` | はい | 入力アイテムの配列。`message` アイテムは `role`（`system`、`user`、`assistant`）と、`input_text` などのパートからなる `content` 配列を持つ。ツールを使う場合は `function_call` アイテムと `function_call_output` アイテムが加わる（[6.5 節](https://madeforagent.com/ja/lmsp/1.0/responses.md#tools)）。 |
| `stream` | いいえ | `true` にするとサーバー送信イベントを受け取る。既定は `false`。 |
| `max_output_tokens` | いいえ | 生成するトークン数の上限。 |
| `temperature` | いいえ | サンプリング温度。 |
| `response_format` | いいえ | `{"type": "text"}`（既定）、または構造化出力のための `{"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}}`。`structured_output` 機能が必要。 |
| `tools`, `tool_choice` | いいえ | モデルが呼び出せる関数ツール（[6.5 節](https://madeforagent.com/ja/lmsp/1.0/responses.md#tools)）。`tools` 機能が必要。 |
| `store` | いいえ | サービスにレスポンスを保存するよう求める。これにより、後で取得したり、`previous_response_id` として使ったりできる。既定は `false`。`conversations` 機能を持たないサービスは無視する。 |
| `previous_response_id` | いいえ | 保存済みのレスポンスから続ける。`conversations` 機能が必要。 |
| `extensions` | いいえ | 非公開の拡張（[9.1 節](https://madeforagent.com/ja/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` | トークン数: `input_tokens`、`output_tokens`、`total_tokens`。 |
| `error` | `null`。`status` が `failed` の場合は problem オブジェクト（[9.3 節](https://madeforagent.com/ja/lmsp/1.0/common-rules.md#errors)）。 |
| `incomplete_details` | `null`。`status` が `incomplete` の場合は、`max_output_tokens` などの `reason` を持つオブジェクト。 |

出力アイテムの種類:

| アイテムの種類 | 形 |
| --- | --- |
| `message` | `id`、`role`（`assistant`）、`content`。`content` は、それぞれ `text` を持つ `output_text` パートの配列。 |
| `function_call` | `id`、`call_id`、`name`、`arguments`。`arguments` は JSON エンコードされた文字列。 |
| `reasoning` | `id` と `summary`。`summary` は、それぞれ `text` を持つ `summary_text` パートの配列。 |

生成に失敗した場合、同期リクエストへの応答は、レスポンスオブジェクトではなく、エラーステータスと problem ドキュメント（[9.3 節](https://madeforagent.com/ja/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
}
```

サービスは `Content-Type: text/event-stream` を付けて `200 OK` で応答し、意味を持つイベントを送る。各イベントは `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` | 生成が早めに止まった。たとえばトークン上限による。最終イベント。 | `response_id`、`status`、`incomplete_details`、`usage` |
| `response.failed` | 生成に失敗した。最終イベント。 | `response_id`、`status`、`error` |
| `response.cancelled` | レスポンスがキャンセルされた。最終イベント。 | `response_id`、`status` |
| `error` | 1 つのレスポンスに結び付かない問題。この後ストリームは継続できない。 | `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/ja/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/ja/lmsp/1.0/tasks.md)を作成してそのイベントを追う**べきである**。

## 6.5 ツール呼び出し {#tools}

LMSP 1.0 は、クライアントが実行する関数ツールを定義する。サービス自身はツールを実行しない。`tools:execute` スコープは、ツールを実行する拡張のために予約されている（[10.3 節](https://madeforagent.com/ja/lmsp/1.0/security.md#scopes)）。

まず、クライアントがツールを列挙する。各エントリーは、`function` に設定された `type`、`name`、`description`、そして JSON Schema オブジェクトである `parameters` を持つ。`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\"}"
}
```
