# 共通ルール

> すべての LMSP エンドポイントに共通するルール。バージョンヘッダーと拡張、冪等キー、エラーコードを伴う problem+json のエラー形式、ヘルスチェックを定めます。

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

## 9.1 バージョンと拡張 {#versioning}

LMSP のリクエストは、次のヘッダーを携え**てもよい**。

```http
LMSP-Version: 1.0
LMSP-Client: example-client/1.2.0
```

`LMSP-Version` は、クライアントが対象とするプロトコルのバージョンである。`LMSP-Client` は、診断用にクライアントソフトウェアを `name/version` の形式で識別する。サービスは、これに基づいてプロトコルの動作を変更し**てはならない**。

規則:

- パス中の `v1` はメジャーバージョンを表す。
- 未知のメジャーバージョンを指定するリクエストには、`426 Upgrade Required` とエラーコード `unsupported_protocol_version` で応答する。
- 新しい任意フィールドは、1.x の互換性を壊し**てはならない**。
- サービスとクライアントは、知らないフィールドを無視し**なければならない**。
- 非公開の拡張は `extensions` オブジェクトに入れ、逆ドメイン表記で名前を付ける。

```json
{
  "extensions": {
    "com.example.cache": {
      "enabled": true
    }
  }
}
```

## 9.2 冪等性 {#idempotency}

レスポンスの作成、タスクの作成、モデルのロードのように、何かを作成するリクエストは、冪等キーを受け付ける。

```http
Idempotency-Key: <client-generated-unique-value>
```

サービスは、キーを、リクエスト本文のダイジェストと結果と併せて保存する。

- 同じキーで同じ本文なら、元の結果を返す。
- 同じキーで異なる本文なら、`409 Conflict` と `idempotency_conflict` で応答する。

キーのスコープは、クライアントとエンドポイントである。キーは、ULID や UUID のような、最大 255 文字の一意な値である**べきである**。サービスは、キーを少なくとも 24 時間保持する**べきである**。

サービスは、ストリーミングリクエストではキーを無視し**てもよい**。安全な再試行が必要なクライアントは、[タスク](https://madeforagent.com/ja/lmsp/1.0/tasks.md)を使う。

## 9.3 エラー {#errors}

LMSP インターフェース上のすべてのエラーは `application/problem+json`（[RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)）を使う。

```json
{
  "type": "urn:lmsp:error:model-not-found",
  "title": "Model not found",
  "status": 404,
  "code": "model_not_found",
  "detail": "No local model with id 'qwen3:14b-q4_k_m'",
  "request_id": "req_01J8M9S6Y4W8C3P5R1V7Z2A0DH",
  "retryable": false
}
```

| フィールド | 必須 | 意味 |
| --- | --- | --- |
| `type` | はい | エラーの種類を識別する URI。LMSP は `urn:lmsp:error:` に、アンダースコアをハイフンに置き換えたコードを続けたものを使う。 |
| `title` | はい | 人間が読める短い要約。 |
| `status` | はい | HTTP ステータスコード。 |
| `code` | はい | 下の一覧にある、機械可読なエラーコード。 |
| `detail` | いいえ | このエラーの発生についての、人間が読める説明。シークレット、プロンプト、生成内容を含ん**ではならない**。 |
| `request_id` | いいえ | リクエストの識別子。サービスのログとの突き合わせに使う。 |
| `retryable` | はい | 後でリクエストを繰り返せば成功し得るかどうか。 |

一般的なエラーコード:

| コード | HTTP ステータス | 再試行可 | 意味 |
| --- | --- | --- | --- |
| `invalid_request` | 400 | いいえ | リクエストの形式が正しくないか、パラメーターが無効である。 |
| `unauthorized` | 401 | いいえ | トークンがない、無効、期限切れ、または失効している。あるいはペアリングコードが誤っている。 |
| `forbidden` | 403 | いいえ | トークンに必要なスコープがない、または `Origin` か `Host` の検査に失敗した。 |
| `model_not_found` | 404 | いいえ | この ID のローカルモデルがない。 |
| `model_not_ready` | 409 | はい | モデルがロードされておらず、オンデマンドでもロードされない。 |
| `model_load_failed` | 500 | はい | モデルのロードに失敗した。 |
| `context_length_exceeded` | 400 | いいえ | 入力がモデルのコンテキストウィンドウに収まらない。 |
| `unsupported_capability` | 400 または 501 | いいえ | モデルまたはサービスが、リクエストに必要なものに対応していない。未実装の任意エンドポイントは 501 で応答する。 |
| `unsupported_protocol_version` | 426 | いいえ | サービスが、要求されたメジャーバージョンに対応していない。 |
| `response_not_found` | 404 | いいえ | この ID の保存済みレスポンスがない。 |
| `task_not_found` | 404 | いいえ | この ID のタスクがない。 |
| `task_not_cancelable` | 409 | いいえ | タスクはすでに成功または失敗している。 |
| `idempotency_conflict` | 409 | いいえ | その冪等キーは、すでに別のリクエスト本文で使われている。 |
| `event_history_expired` | 410 | いいえ | 要求されたイベントが保持期間より古い。 |
| `rate_limited` | 429 | はい | リクエストが多すぎる。 |
| `resource_exhausted` | 503 | はい | デバイスのメモリまたはその他のリソースが不足している。 |
| `backend_unavailable` | 503 | はい | モデルランタイムに到達できない。 |
| `server_restarted` | 503 | はい | タスクが未完了の間にサービスが再起動した。 |
| `internal_error` | 500 | 場合による | サービス内部での予期しない障害。 |

`retryable` フィールドが正である。上の列は通常の値を示している。サービスは、さらにコードを定義し**てもよい**。クライアントは、知らないコードを、その HTTP ステータスと `retryable` フィールドによって処理し**なければならない**。

## 9.4 ヘルスチェック {#health}

```http
GET /lmsp/v1/health
```

```json
{
  "status": "ready",
  "service_id": "svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2",
  "uptime_seconds": 86420,
  "loaded_models": 1,
  "active_tasks": 2,
  "storage": "ok"
}
```

| フィールド | 意味 |
| --- | --- |
| `status` | `starting`、`ready`、`degraded`、`stopping`。 |
| `service_id` | サービス記述にあるサービス ID。 |
| `uptime_seconds` | サービスの起動からの秒数。 |
| `loaded_models` | `ready` 状態のモデルの数。 |
| `active_tasks` | `queued`、`loading`、`running`、`cancelling` のタスクの数。 |
| `storage` | `ok` または `error`。 |

`status` が `ready` または `degraded` のときは `200 OK`、それ以外は `503 Service Unavailable` を返す。

ヘルスエンドポイントが返すのは、運用上のステータスだけである。モデルのパス、プロンプト、アクセストークン、その他の機微な情報を返し**てはならない**。
