공통 규칙

9.1 버전과 확장

각 LMSP 요청은 다음 헤더를 실을 수 있다.

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 객체에 넣고 역도메인 표기로 이름을 짓는다.
{
  "extensions": {
    "com.example.cache": {
      "enabled": true
    }
  }
}

9.2 멱등성

응답 생성, 작업 생성, 모델 로드처럼 무언가를 만드는 요청은 멱등성 키를 받는다.

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

서비스는 키를 요청 본문의 다이제스트 및 결과와 함께 저장한다.

  • 같은 키에 같은 본문이면 원래 결과를 반환한다.
  • 같은 키에 다른 본문이면 409 Conflict와 idempotency_conflict로 응답한다.

키의 범위는 클라이언트와 엔드포인트이다. 키는 ULID나 UUID처럼 최대 255자의 고유한 값인 것이 좋다. 서비스는 키를 최소 24시간 보관하는 것이 좋다.

서비스는 스트리밍 요청에서는 키를 무시할 수 있다. 안전한 재시도가 필요한 클라이언트는 작업을 사용한다.

9.3 오류

LMSP 인터페이스의 모든 오류는 application/problem+json(RFC 9457)을 사용한다.

{
  "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 상태 점검

GET /lmsp/v1/health
{
  "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이다.

상태 점검 엔드포인트는 운영 상태만 반환한다. 모델 경로, 프롬프트, 액세스 토큰 또는 그 밖의 민감한 정보를 반환해서는 안 된다.