# Regras comuns

> Regras compartilhadas por todos os endpoints LMSP, com cabeçalhos de versão e extensões, chaves de idempotência, o formato de erro problem+json com seus códigos de erro e a verificação de integridade.

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

## 9.1 Versões e extensões {#versioning}

Cada requisição LMSP **PODE** carregar estes cabeçalhos:

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

`LMSP-Version` é a versão do protocolo que o cliente tem como alvo. `LMSP-Client` identifica o software cliente para fins de diagnóstico, como `name/version`. Um serviço **NÃO DEVE** alterar o comportamento do protocolo com base nele.

Regras:

- O `v1` no caminho denota a versão principal.
- Uma requisição que nomeia uma versão principal desconhecida é respondida com `426 Upgrade Required` e o código de erro `unsupported_protocol_version`.
- Novos campos opcionais **NÃO DEVEM** quebrar a compatibilidade da 1.x.
- Serviços e clientes **DEVEM** ignorar os campos que não conhecem.
- As extensões privadas ficam em um objeto `extensions` e são nomeadas em notação de domínio reverso:

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

## 9.2 Idempotência {#idempotency}

As requisições que criam algo, como criar uma resposta, criar uma tarefa ou carregar um modelo, aceitam uma chave de idempotência:

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

O serviço armazena a chave junto com um digest do corpo da requisição e o resultado:

- A mesma chave com o mesmo corpo retorna o resultado original.
- A mesma chave com um corpo diferente é respondida com `409 Conflict` e `idempotency_conflict`.

Uma chave tem como escopo o cliente e o endpoint. Ela **DEVERIA** ser um valor único de no máximo 255 caracteres, como um ULID ou um UUID. Um serviço **DEVERIA** guardar as chaves por pelo menos 24 horas.

Um serviço **PODE** ignorar a chave em requisições em streaming. Um cliente que precisa de novas tentativas seguras usa uma [tarefa](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md).

## 9.3 Erros {#errors}

Todo erro na interface LMSP usa `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
}
```

| Campo | Obrigatório | Significado |
| --- | --- | --- |
| `type` | Sim | URI que identifica o tipo de erro. O LMSP usa `urn:lmsp:error:` seguido do código com hifens no lugar de sublinhados. |
| `title` | Sim | Resumo curto e legível por pessoas. |
| `status` | Sim | O código de status HTTP. |
| `code` | Sim | Código de erro legível por máquina, da lista abaixo. |
| `detail` | Não | Explicação legível por pessoas desta ocorrência. Ela **NÃO DEVE** conter segredos, prompts nem conteúdo gerado. |
| `request_id` | Não | Identificador da requisição, para correlação com os logs do serviço. |
| `retryable` | Sim | Se repetir a requisição mais tarde pode dar certo. |

Códigos de erro comuns:

| Código | Status HTTP | Repetível | Significado |
| --- | --- | --- | --- |
| `invalid_request` | 400 | Não | A requisição está malformada ou tem parâmetros inválidos. |
| `unauthorized` | 401 | Não | O token está ausente, é inválido, expirou ou foi revogado, ou um código de pareamento está errado. |
| `forbidden` | 403 | Não | O token não tem o escopo exigido, ou a verificação de `Origin` ou `Host` falhou. |
| `model_not_found` | 404 | Não | Nenhum modelo local tem este ID. |
| `model_not_ready` | 409 | Sim | O modelo não está carregado e não é carregado sob demanda. |
| `model_load_failed` | 500 | Sim | O carregamento do modelo falhou. |
| `context_length_exceeded` | 400 | Não | A entrada não cabe na janela de contexto do modelo. |
| `unsupported_capability` | 400 ou 501 | Não | O modelo ou o serviço não suporta o que a requisição exige. Um endpoint opcional não implementado responde 501. |
| `unsupported_protocol_version` | 426 | Não | O serviço não suporta a versão principal solicitada. |
| `response_not_found` | 404 | Não | Nenhuma resposta armazenada tem este ID. |
| `task_not_found` | 404 | Não | Nenhuma tarefa tem este ID. |
| `task_not_cancelable` | 409 | Não | A tarefa já foi concluída com sucesso ou falhou. |
| `idempotency_conflict` | 409 | Não | A chave de idempotência já foi usada com outro corpo de requisição. |
| `event_history_expired` | 410 | Não | Os eventos solicitados são mais antigos que o período de retenção. |
| `rate_limited` | 429 | Sim | Requisições demais. |
| `resource_exhausted` | 503 | Sim | O dispositivo ficou sem memória ou sem outro recurso. |
| `backend_unavailable` | 503 | Sim | Não é possível alcançar o ambiente de execução do modelo. |
| `server_restarted` | 503 | Sim | O serviço foi reiniciado enquanto a tarefa estava inacabada. |
| `internal_error` | 500 | Varia | Uma falha inesperada dentro do serviço. |

O campo `retryable` é a referência definitiva. A coluna acima mostra o valor usual. Um serviço **PODE** definir outros códigos. Um cliente **DEVE** tratar um código que não conhece pelo seu status HTTP e pelo seu campo `retryable`.

## 9.4 Verificação de integridade {#health}

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

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

| Campo | Significado |
| --- | --- |
| `status` | `starting`, `ready`, `degraded` ou `stopping`. |
| `service_id` | O ID do serviço da descrição do serviço. |
| `uptime_seconds` | Segundos desde que o serviço foi iniciado. |
| `loaded_models` | Número de modelos no estado `ready`. |
| `active_tasks` | Número de tarefas que estão `queued`, `loading`, `running` ou `cancelling`. |
| `storage` | `ok` ou `error`. |

O status HTTP é `200 OK` quando `status` é `ready` ou `degraded`, e `503 Service Unavailable` nos demais casos.

O endpoint de integridade retorna apenas o status operacional. Ele **NÃO DEVE** retornar caminhos de modelos, prompts, tokens de acesso nem outras informações sensíveis.
