# Local Model Service Protocol (LMSP) 1.0, Rascunho > A Made for Agent publica protocolos abertos e legíveis por máquina que permitem que agentes de IA, modelos e ferramentas se descubram e conversem entre si. Começa com o LMSP, o Local Model Service Protocol. Source: https://madeforagent.com/pt-br/llms-full.txt Updated: 2026-11-08 --- # Protocolo de Serviço de Modelos Locais (LMSP) > O LMSP é um protocolo aberto para descobrir e chamar os modelos de linguagem do seu dispositivo. Define descoberta de serviços, catálogo de modelos, streaming, tarefas persistentes e compatibilidade com a OpenAI. Source: https://madeforagent.com/pt-br/lmsp/ Language: pt-BR Updated: 2026-11-08 ## O que o LMSP faz {#what} O LMSP (Local Model Service Protocol) é um protocolo aberto para softwares que executam modelos de linguagem no próprio dispositivo ou na rede local do usuário, e para os clientes que usam esse software. Um serviço local residente se descreve em um endereço well-known e lista seus modelos. Ele responde às requisições de geração com JSON ou com eventos enviados pelo servidor, e executa as gerações longas como tarefas persistidas, que podem ser canceladas e acompanhadas de novo após uma desconexão. O mesmo serviço também fala a API da OpenAI, de modo que os clientes que existem hoje continuam funcionando. O LMSP não substitui a API da OpenAI, o Ollama nem o MCP. Ele combina os pontos fortes de cada um em uma camada de protocolo pensada para serviços locais residentes. ## Visão rápida {#glance} | Tópico | Resumo | | --- | --- | | Endereço padrão | `http://127.0.0.1:17832` | | Descrição do serviço | `GET /.well-known/lmsp.json` | | Interface principal | `/lmsp/v1`, JSON sobre HTTP, streaming com eventos enviados pelo servidor | | Interfaces de compatibilidade | `/v1` para clientes OpenAI, `/api` opcional para clientes Ollama | | Descoberta | Endereço manual, sondagem de endereços locais, mDNS e DNS-SD opcionais (`_lmsp._tcp.local.`) | | Autenticação | Tokens de portador obtidos por pareamento local | | Persistência | SQLite embutido, com tarefas que sobrevivem a uma reinicialização | | Contrato | OpenAPI 3.2 | ## Experimente {#try} Se um serviço LMSP estiver em execução na sua máquina, este é o fluxo completo. Faça primeiro o pareamento para obter um token, como descrito na [seção 10.2](https://madeforagent.com/pt-br/lmsp/1.0/security.md#pairing), e guarde-o em `LMSP_TOKEN`. ```sh # 1. Descobrir o serviço curl http://127.0.0.1:17832/.well-known/lmsp.json # 2. Listar os modelos locais curl http://127.0.0.1:17832/lmsp/v1/models \ -H "Authorization: Bearer $LMSP_TOKEN" # 3. Gerar uma resposta curl http://127.0.0.1:17832/lmsp/v1/responses \ -H "Authorization: Bearer $LMSP_TOKEN" \ -H "Content-Type: application/json" \ -d '{"model":"qwen3:14b-q4_k_m","input":[{"type":"message","role":"user","content":[{"type":"input_text","text":"Hello"}]}]}' ``` ## Como o LMSP se relaciona com outros protocolos {#related} | Protocolo | O que cobre | Relação com o LMSP | | --- | --- | --- | | API da OpenAI | Modelos hospedados. A Responses API é a sua interface mais recente. | O LMSP segue a estrutura do Responses em sua interface principal, e um serviço oferece, ao lado dela, uma interface compatível com a OpenAI. | | Ollama | Um ambiente de execução local que já serve endpoints compatíveis com a OpenAI. | Pode ficar por trás de um serviço LMSP como adaptador, e o LMSP define endpoints opcionais compatíveis com o Ollama. | | MCP | Conecta agentes a ferramentas e contexto. | O LMSP conecta agentes a modelos. Ambos preferem a descoberta sem estado a sessões obrigatórias. | | A2A | Colaboração entre agentes. | O LMSP toma emprestados os cartões de serviço e os estados explícitos de tarefa para a descrição do serviço e para as suas tarefas. | ## Recursos {#resources} - A [especificação, versão 1.0 (rascunho)](https://madeforagent.com/pt-br/lmsp/1.0.md). - O contrato OpenAPI, em [JSON](https://madeforagent.com/lmsp/1.0/openapi.json) ou [YAML](https://madeforagent.com/lmsp/1.0/openapi.yaml). - [llms.txt](https://madeforagent.com/pt-br/llms.txt) e [llms-full.txt](https://madeforagent.com/pt-br/llms-full.txt), para modelos de linguagem. - Cada página está disponível em Markdown. Substitua a barra final do endereço por `.md`, por exemplo [`/pt-br/lmsp/1.0/tasks.md`](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md). ## Perguntas frequentes ### O que é o LMSP? O LMSP, o Local Model Service Protocol (Protocolo de Serviço de Modelos Locais), é um protocolo aberto para serviços de modelos de linguagem executados no próprio dispositivo do usuário ou na rede local. Ele define como os clientes descobrem um serviço, listam seus modelos, solicitam respostas, recebem a saída em streaming e executam tarefas longas. ### O LMSP substitui a API da OpenAI, o Ollama ou o MCP? Não. O LMSP se apoia neles. Sua interface principal segue a estrutura do OpenAI Responses, um serviço pode oferecer endpoints compatíveis com a OpenAI e com o Ollama, e o protocolo toma emprestados do MCP a descoberta sem estado e do A2A os estados das tarefas. ### Os clientes OpenAI existentes podem usar um serviço LMSP? Normalmente sim. Eles precisam de outra URL base e do token do LMSP como chave de API. Não encontram o serviço automaticamente, porque a descoberta exige um cliente compatível com o LMSP. ### Como um cliente encontra um serviço LMSP local? Ele tenta três coisas, nesta ordem. Primeiro um endereço digitado manualmente; depois o endereço local convencional, onde requisita /.well-known/lmsp.json; e por fim, opcionalmente, a busca por mDNS e DNS-SD de _lmsp._tcp.local. na rede local. ### Um serviço de modelos no localhost é seguro? Não automaticamente, porque páginas da web podem tentar acessar portas locais. Os serviços LMSP se vinculam ao loopback por padrão, exigem tokens de portador obtidos por pareamento local, verificam os cabeçalhos Origin e Host e exigem autenticação no modo LAN. ### Qual é o status da especificação? A versão 1.0 é um primeiro rascunho público e ainda pode mudar de forma incompatível. O texto em inglês é o normativo, e as traduções são oferecidas por conveniência. --- # Visão geral > Visão geral do rascunho do LMSP 1.0. O que é o Local Model Service Protocol, os projetos em que ele se baseia, sua arquitetura em camadas, como ler a especificação e os termos usados em todo o texto. Source: https://madeforagent.com/pt-br/lmsp/1.0/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 1.1 Resumo {#abstract} O Local Model Service Protocol (LMSP) define como os clientes encontram e usam serviços de modelos de linguagem executados no próprio dispositivo ou na rede local do usuário. Ele especifica a descoberta de serviços, um catálogo de modelos, a geração síncrona e em streaming, e tarefas assíncronas que sobrevivem a reinicializações. Também define como um mesmo serviço oferece uma interface compatível com a OpenAI ao lado da interface LMSP, para que os clientes existentes continuem funcionando. O LMSP não substitui a API da OpenAI, o Ollama nem o MCP. Ele combina os pontos fortes de cada um em uma camada de protocolo pensada para um serviço local residente. ## 1.2 Status deste documento {#status} Este é o primeiro rascunho público do LMSP 1.0, publicado em 2026-11-08. “LMSP” é um nome provisório. O texto está aberto a comentários e pode mudar de forma incompatível até que a 1.0 seja definitiva. O texto em inglês é normativo. As traduções são oferecidas por conveniência; se houver divergência, prevalece o texto em inglês. ## 1.3 Base do projeto {#design-basis} O LMSP reaproveita projetos comprovados em vez de inventar novos: - **API OpenAI Responses.** Itens de saída estruturados, eventos semânticos enviados pelo servidor e execução em segundo plano, com consulta e cancelamento, para trabalhos de longa duração. É a referência da interface de conversa principal do LMSP. Veja [respostas em streaming](https://developers.openai.com/api/docs/guides/streaming-responses) e [modo em segundo plano](https://developers.openai.com/api/docs/guides/background). - **Ollama.** Serve os endpoints compatíveis com a OpenAI `/v1/models`, `/v1/chat/completions` e `/v1/responses`, o que mostra que um serviço mais uma camada de adaptação à OpenAI reduz drasticamente o custo de adoção. Veja a [compatibilidade do Ollama com a OpenAI](https://docs.ollama.com/api/openai-compatibility). - **Model Context Protocol (MCP).** Seu projeto mais recente deixa a inicialização obrigatória de sessão e passa à descoberta sem estado: cada requisição carrega suas próprias informações de versão, e os clientes conhecem as capacidades por meio de uma interface de descoberta. Isso combina com serviços locais, em que reinicializações, falhas de clientes e conexões interrompidas não devem corromper o estado do protocolo. Veja o [MCP](https://modelcontextprotocol.io/). - **Agent2Agent (A2A).** Cartões de serviço, estados explícitos de tarefa, assinatura de tarefas e cancelamento inspiram a descrição do serviço e o modelo de tarefas assíncronas do LMSP. Veja o [A2A](https://a2a-protocol.org/). ## 1.4 Arquitetura {#architecture} O LMSP é organizado em três camadas, sobre os adaptadores que conversam com os ambientes de execução dos modelos: ```text +---------------------------------------------------------------+ | Discovery mDNS / DNS-SD + well-known service document | +---------------------------------------------------------------+ | Core model catalog, responses, SSE, async tasks | +---------------------------------------------------------------+ | Compatibility OpenAI API, optional Ollama API | +---------------------------------------------------------------+ | Adapters llama.cpp, Ollama, vLLM, custom runtimes | +---------------------------------------------------------------+ ``` - **Descoberta.** mDNS/DNS-SD e um documento well-known de descrição do serviço ([página 3](https://madeforagent.com/pt-br/lmsp/1.0/discovery.md)). - **Núcleo.** O catálogo de modelos, as respostas síncronas, os eventos enviados pelo servidor e as tarefas assíncronas ([páginas 5 a 7](https://madeforagent.com/pt-br/lmsp/1.0/models.md)). - **Compatibilidade.** Uma API compatível com a OpenAI e, opcionalmente, uma API compatível com o Ollama ([página 8](https://madeforagent.com/pt-br/lmsp/1.0/compatibility.md)). - **Adaptadores.** Pontes para o llama.cpp, o Ollama, o vLLM ou um ambiente de execução próprio. O princípio orientador é **um único núcleo de execução de modelos, duas famílias de interfaces**. Um serviço oferece a interface LMSP e a interface OpenAI sobre o mesmo núcleo, de modo que há um único lugar onde os modelos são carregados, as requisições são executadas e as tarefas são acompanhadas. ## 1.5 Linguagem de conformidade {#conformance} As palavras-chave **DEVE/DEVEM** (MUST), **NÃO DEVE/NÃO DEVEM** (MUST NOT), **OBRIGATÓRIO** (REQUIRED), **DEVERIA/DEVERIAM** (SHOULD), **NÃO DEVERIA/NÃO DEVERIAM** (SHOULD NOT), **RECOMENDADO** (RECOMMENDED), **PODE/PODEM** (MAY) e **OPCIONAL** (OPTIONAL) deste documento devem ser interpretadas conforme descrito na [BCP 14](https://www.rfc-editor.org/info/bcp14) ([RFC 2119](https://www.rfc-editor.org/rfc/rfc2119), [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174)) quando, e somente quando, aparecem em negrito e em letras maiúsculas. Fora desse caso, são palavras comuns. Cada página é marcada como normativa ou informativa. As páginas normativas definem requisitos; as informativas oferecem orientação. Os exemplos são informativos. O JSON usa UTF-8, e os nomes de campo usam `snake_case`. ## 1.6 Terminologia {#terminology} | Termo | Significado | | --- | --- | | Serviço | Um processo residente que implementa o LMSP e executa modelos por meio de adaptadores. | | Cliente | Software que descobre e chama um serviço: um agente, um aplicativo ou uma ferramenta. | | Adaptador | O componente que conecta o serviço a um único ambiente de execução de modelos, como llama.cpp, Ollama ou vLLM. | | Modelo | Um modelo disponível localmente, identificado por um `id` estável. | | Resposta | O resultado de uma requisição de geração: itens de saída, uso e um status. | | Tarefa | Uma execução assíncrona e persistida de uma requisição de resposta, com um estado explícito. | | Evento | Um evento enviado pelo servidor, com número de sequência, emitido enquanto uma resposta é gerada. | --- # Transporte e implantação > Endereços de escuta padrão, transporte, formato de streaming e layout de URLs de um serviço LMSP, e como ele roda como serviço do sistema operacional, separado dos processos dos modelos. Source: https://madeforagent.com/pt-br/lmsp/1.0/transport/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 2.1 Implantação padrão {#deployment} Um serviço **DEVE** escutar por padrão nos endereços de loopback `127.0.0.1` e `::1`. A porta convencional é `17832`, o que torna o endereço base padrão `http://127.0.0.1:17832`. | Item | Valor | | --- | --- | | Endereços de escuta | `127.0.0.1` e `::1` | | Transporte | HTTP/1.1 ou HTTP/2 transportando JSON | | Streaming | Eventos enviados pelo servidor, `Content-Type: text/event-stream` | | Prefixo da interface principal | `/lmsp/v1` | | Prefixo compatível com a OpenAI | `/v1` | | Descrição do serviço | `GET /.well-known/lmsp.json` | | Contrato legível por máquina | `GET /lmsp/v1/openapi.json` | | Canal local opcional | Socket de domínio Unix ou named pipe do Windows | As requisições e as respostas usam JSON em UTF-8 (`Content-Type: application/json`), exceto os fluxos (`text/event-stream`) e os erros (`application/problem+json`). Os carimbos de data e hora são inteiros: segundos desde a época Unix. Os identificadores são strings opacas; um prefixo de tipo, como `resp_` ou `task_`, é **RECOMENDADO**. O contrato da interface é um documento OpenAPI 3.2. O OpenAPI 3.2 consegue descrever eventos enviados pelo servidor, JSON Lines e JSON Sequences, de modo que os endpoints de streaming são especificados no mesmo documento que o restante. O contrato desta versão é publicado em [`/lmsp/1.0/openapi.json`](https://madeforagent.com/lmsp/1.0/openapi.json). Um serviço **PODE** também aceitar conexões em um socket de domínio Unix ou em um named pipe do Windows, com a mesma semântica HTTP. Na 1.0, a forma de anunciar esses endpoints fica a cargo de extensões. ## 2.2 Operação contínua {#operation} Um serviço **DEVERIA** ser hospedado pelo sistema operacional: launchd no macOS, systemd no Linux e o Gerenciador de Serviços no Windows. O processo do serviço e os processos dos modelos **DEVERIAM** ser separados. A falha de um modelo **DEVERIA** afetar apenas as tarefas que usam esse modelo. Ela **NÃO DEVERIA** tornar indisponíveis a descoberta de serviços, o catálogo de modelos nem as consultas sobre tarefas anteriores. --- # Descoberta de serviços > Como os clientes LMSP encontram um serviço local por configuração manual, sondagem de loopback e mDNS/DNS-SD opcional, e como ler o documento well-known de descrição do serviço. Source: https://madeforagent.com/pt-br/lmsp/1.0/discovery/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 3.1 Métodos de descoberta {#methods} Um cliente descobre um serviço tentando estes métodos em ordem: 1. **Configuração manual.** O usuário informa diretamente o endereço do serviço. 2. **Sondagem de endereços locais convencionais.** O cliente requisita `/.well-known/lmsp.json` em endereços candidatos. Os candidatos convencionais são `http://127.0.0.1:17832` e `http://[::1]:17832`. 3. **Descoberta na LAN.** O cliente busca `_lmsp._tcp.local.` com mDNS e DNS-SD. Um método tem sucesso quando produz uma descrição de serviço válida ([seção 3.3](https://madeforagent.com/pt-br/lmsp/1.0/discovery.md#service-description)). Um endereço informado manualmente pelo usuário sempre tem precedência sobre os descobertos. ## 3.2 Anúncio na LAN {#mdns} O DNS-SD usa registros PTR para encontrar instâncias de serviço, registros SRV para obter o host e a porta, e registros TXT para transportar uma pequena quantidade de informações extras. Combinado com o mDNS, oferece descoberta sem configuração em uma rede local ([RFC 6763](https://www.rfc-editor.org/rfc/rfc6763), [RFC 6762](https://www.rfc-editor.org/rfc/rfc6762)). Um exemplo de anúncio: ```text Service type: _lmsp._tcp.local. Instance name: Workstation LMSP._lmsp._tcp.local. TXT record: v=1 id=svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2 path=/ auth=pairing ``` | Chave TXT | Significado | | --- | --- | | `v` | Versão do formato do anúncio. `1` para o LMSP 1.0. | | `id` | O ID do serviço, igual a `service.id` na descrição do serviço. | | `path` | Caminho de URL da raiz do serviço. Os clientes requisitam `{path}.well-known/lmsp.json`. | | `auth` | Dica de autenticação. `pairing` significa que o cliente deve fazer o pareamento antes de usar o serviço. | Regras: - Um serviço **NÃO DEVE** colocar tokens de acesso, listas de modelos, caminhos de arquivos nem qualquer outra informação sensível no registro TXT. O registro apenas localiza o serviço. As capacidades reais **DEVEM** ser lidas da descrição do serviço. - Um serviço **DEVE** manter o anúncio mDNS desativado por padrão. Ele só é ativado quando o usuário liga explicitamente a descoberta na LAN. Um serviço usado apenas na máquina local não faz anúncio. - Um serviço que anuncia na LAN precisa escutar além do loopback, o que só é permitido no modo LAN ([seção 10.5](https://madeforagent.com/pt-br/lmsp/1.0/security.md#lan)). - Um cliente **DEVE** tratar o registro TXT como uma dica não verificada e confirmar o serviço lendo a sua descrição. ## 3.3 Descrição do serviço {#service-description} ```http GET /.well-known/lmsp.json ``` Um serviço **DEVE** servir este documento como `application/json`, sem exigir autenticação. ```json { "protocol": "lmsp", "versions": ["1.0"], "service": { "id": "svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2", "name": "Workstation Local Models", "version": "1.0.0" }, "interfaces": [ { "kind": "lmsp", "version": "1.0", "url": "http://127.0.0.1:17832/lmsp/v1", "transport": "http+json" }, { "kind": "openai", "version": "responses+chat", "url": "http://127.0.0.1:17832/v1", "transport": "http+json" } ], "capabilities": { "streaming": true, "tasks": true, "event_resume": true, "conversations": true, "model_management": true }, "authentication": { "type": "bearer", "pairing_url": "http://127.0.0.1:17832/lmsp/v1/pair" }, "openapi": "http://127.0.0.1:17832/lmsp/v1/openapi.json" } ``` | Campo | Significado | | --- | --- | | `protocol` | Sempre `"lmsp"`. | | `versions` | As versões do LMSP que o serviço suporta, como strings `major.minor`. | | `service` | `id` é um identificador estável do serviço, `name` um nome de exibição e `version` a versão do software do serviço. | | `interfaces` | As interfaces oferecidas. Cada uma tem um `kind` (`lmsp`, `openai` ou `ollama`), uma `version`, uma `url` base e um `transport`. Para `openai`, `version` nomeia as famílias de API atendidas, como `responses+chat`. | | `capabilities` | Flags booleanas de recursos, listadas abaixo. | | `authentication` | `type` é `bearer`. `pairing_url` é onde os clientes trocam um código de pareamento por um token ([seção 10.2](https://madeforagent.com/pt-br/lmsp/1.0/security.md#pairing)). | | `openapi` | URL do documento OpenAPI que descreve a interface LMSP. | Flags de capacidade: | Flag | Significado | | --- | --- | | `streaming` | As respostas podem ser enviadas em streaming como eventos enviados pelo servidor. **DEVE** ser `true` na 1.0. | | `tasks` | Tarefas assíncronas estão disponíveis. **DEVE** ser `true` na 1.0. | | `event_resume` | Os fluxos de eventos das tarefas podem ser assinados e retomados (`GET /lmsp/v1/tasks/{task_id}/events`). | | `conversations` | O serviço armazena respostas, de modo que `store` e `previous_response_id` funcionam e `GET /lmsp/v1/responses/{response_id}` está disponível. | | `model_management` | Os modelos podem ser carregados e descarregados explicitamente. | ## 3.4 Comportamento do cliente {#client-behavior} Um cliente: - **DEVERIA** selecionar a versão mais alta em `versions` que ele também suporte. - **DEVERIA** selecionar a interface LMSP ou a interface OpenAI em `interfaces`, conforme o que ele consiga falar. - **DEVE** usar apenas as capacidades que a descrição declara. Uma flag ausente significa `false`. - **DEVE** ignorar os campos de extensão que não reconhece. - **DEVERIA** reler a descrição do serviço periodicamente, e também quando uma requisição falhar, em vez de mantê-la em cache para sempre. - **DEVERIA** lembrar um serviço escolhido pelo `service.id`, e não pelo endereço, porque os endereços podem mudar. --- # Endpoints > A tabela completa dos endpoints do LMSP 1.0 com método, caminho, nível de exigência e finalidade, além das convenções para caminhos, autenticação e endpoints opcionais. Source: https://madeforagent.com/pt-br/lmsp/1.0/endpoints/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 4.1 Tabela de endpoints {#table} Um serviço em conformidade **DEVE** implementar todos os endpoints marcados como obrigatórios. Ele **PODE** implementar os opcionais e os sinaliza por meio das flags de capacidade de sua [descrição do serviço](https://madeforagent.com/pt-br/lmsp/1.0/discovery.md#service-description). | Método | Caminho | Exigência | Finalidade | | --- | --- | --- | --- | | GET | `/.well-known/lmsp.json` | Obrigatório | [Descoberta do serviço e das capacidades](https://madeforagent.com/pt-br/lmsp/1.0/discovery.md#service-description) | | GET | `/lmsp/v1/openapi.json` | Obrigatório | Especificação da interface legível por máquina | | GET | `/lmsp/v1/health` | Obrigatório | [Verificação de atividade e de prontidão](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#health) | | POST | `/lmsp/v1/pair` | Obrigatório | [Trocar um código de pareamento por um token de portador](https://madeforagent.com/pt-br/lmsp/1.0/security.md#pairing) | | GET | `/lmsp/v1/models` | Obrigatório | [Listar os modelos locais](https://madeforagent.com/pt-br/lmsp/1.0/models.md#list) | | GET | `/lmsp/v1/models/{model_id}` | Obrigatório | [Obter um modelo](https://madeforagent.com/pt-br/lmsp/1.0/models.md#operations) | | POST | `/lmsp/v1/responses` | Obrigatório | [Geração síncrona ou em streaming](https://madeforagent.com/pt-br/lmsp/1.0/responses.md#request) | | GET | `/lmsp/v1/responses/{response_id}` | Opcional | [Recuperar uma resposta armazenada](https://madeforagent.com/pt-br/lmsp/1.0/responses.md#sync) | | POST | `/lmsp/v1/tasks` | Obrigatório | [Criar uma tarefa de geração assíncrona](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#create) | | GET | `/lmsp/v1/tasks/{task_id}` | Obrigatório | [Obter uma tarefa assíncrona](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#create) | | POST | `/lmsp/v1/tasks/{task_id}/cancel` | Obrigatório | [Cancelar uma tarefa assíncrona](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#cancel) | | GET | `/lmsp/v1/tasks/{task_id}/events` | Opcional | [Assinar ou retomar o fluxo de eventos](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#events) | | POST | `/lmsp/v1/models/{model_id}/load` | Opcional | [Pré-carregar um modelo](https://madeforagent.com/pt-br/lmsp/1.0/models.md#operations) | | POST | `/lmsp/v1/models/{model_id}/unload` | Opcional | [Descarregar um modelo](https://madeforagent.com/pt-br/lmsp/1.0/models.md#operations) | Os endpoints compatíveis com a OpenAI em `/v1` e os endpoints opcionais compatíveis com o Ollama estão listados na [página 8](https://madeforagent.com/pt-br/lmsp/1.0/compatibility.md). ## 4.2 Convenções {#conventions} - **Corpos.** Os corpos de requisição e de resposta são JSON (`application/json`), exceto os fluxos de eventos (`text/event-stream`) e os erros (`application/problem+json`). - **Parâmetros de caminho.** Um nome entre chaves, como `{model_id}`, é um marcador. Os valores **DEVEM** ser codificados em percent-encoding. Um ID de modelo como `qwen3:14b-q4_k_m` é enviado como `qwen3%3A14b-q4_k_m`. - **Autenticação.** Todo endpoint exige `Authorization: Bearer `, exceto `/.well-known/lmsp.json`, `/lmsp/v1/openapi.json`, `/lmsp/v1/health` e `/lmsp/v1/pair`. - **Endpoints opcionais.** Um endpoint opcional que o serviço não implementa **DEVE** responder `501 Not Implemented` com o código de erro `unsupported_capability`. - **Versões e erros.** As requisições podem trazer cabeçalhos de versão, e todo erro usa um único formato. Ambos são definidos na [página 9](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md). - **Contrato.** O documento OpenAPI publicado em [`/lmsp/1.0/openapi.json`](https://madeforagent.com/lmsp/1.0/openapi.json) é a forma legível por máquina desta página. Onde os dois divergem, o texto é normativo. --- # Catálogo de modelos > Como um serviço LMSP lista seus modelos locais, o objeto de modelo e suas flags de capacidade, os estados do ciclo de vida do modelo, IDs de modelo estáveis e revisões do catálogo. Source: https://madeforagent.com/pt-br/lmsp/1.0/models/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 5.1 Listar modelos {#list} ```http GET /lmsp/v1/models?capability=chat&ready_only=false Authorization: Bearer ``` | Parâmetro de consulta | Significado | | --- | --- | | `capability` | Retorna apenas os modelos que têm a capacidade informada, por exemplo `chat`, `embeddings` ou `tools`. | | `ready_only` | Quando `true`, retorna apenas os modelos cujo `status` é `ready`. O padrão é `false`. | ```json { "object": "list", "catalog_revision": "42", "data": [ { "id": "qwen3:14b-q4_k_m", "object": "model", "display_name": "Qwen3 14B Q4_K_M", "owned_by": "local", "family": "qwen3", "revision": "sha256:8f27c1a4e9b05d36f2a7c8e1b4d90a63c5e2f7b8a1d4c9e60b3f5a7d2c8e1b04", "status": "ready", "capabilities": { "chat": true, "completion": true, "embeddings": false, "tools": true, "vision": false, "structured_output": true, "streaming": true }, "input_modalities": ["text"], "output_modalities": ["text"], "context_window": 32768, "max_output_tokens": 8192, "runtime": { "backend": "llama.cpp", "device": "metal", "load_on_demand": true } } ] } ``` Para poupar os clientes de buscar o catálogo completo repetidamente, um serviço **DEVERIA** retornar um cabeçalho `ETag`, um campo `catalog_revision`, ou ambos: - `catalog_revision` é uma string opaca que muda sempre que o catálogo muda. - Um serviço que envia `ETag` **DEVERIA** responder a um `If-None-Match` correspondente com `304 Not Modified`. ## 5.2 Objeto de modelo {#object} | Campo | Significado | | --- | --- | | `id` | Identificador estável do modelo, usado em toda requisição que nomeia um modelo. | | `object` | Sempre `"model"`. | | `display_name` | Nome legível. O usuário pode alterá-lo. | | `aliases` | Lista opcional de nomes alternativos. São apenas informativos. | | `owned_by` | De onde vem o modelo. `local` para modelos instalados neste dispositivo. | | `family` | Família do modelo, como `qwen3`. | | `revision` | Digest do conteúdo do modelo, como `sha256:8f27...`. | | `status` | Estado do ciclo de vida ([seção 5.3](https://madeforagent.com/pt-br/lmsp/1.0/models.md#lifecycle)). | | `capabilities` | Flags booleanas: `chat`, `completion`, `embeddings`, `tools`, `vision`, `structured_output` e `streaming`. | | `input_modalities`, `output_modalities` | Os tipos de conteúdo que o modelo lê e escreve. `text` é a única modalidade definida na 1.0. | | `context_window` | Número máximo de tokens de contexto. | | `max_output_tokens` | Número máximo de tokens em uma resposta. | | `runtime` | `backend` (por exemplo `llama.cpp`), `device` (por exemplo `metal`) e `load_on_demand`. | | `error` | Presente quando `status` é `error`. Um objeto de problema ([seção 9.3](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#errors)). | O `id` de um modelo **DEVE** ser estável. O nome de exibição e os aliases podem ser alterados pelo usuário, portanto **NÃO DEVEM** ser usados como chave primária. ## 5.3 Ciclo de vida do modelo {#lifecycle} ```text installed --> loading --> ready --> unloading --> installed | +-----> error ``` | Status | Significado | | --- | --- | | `installed` | O modelo existe, mas não está carregado. | | `loading` | A memória está sendo alocada ou o ambiente de execução está sendo inicializado. | | `ready` | O modelo pode processar requisições imediatamente. | | `unloading` | Os recursos estão sendo liberados. | | `error` | O carregamento falhou. O objeto de modelo **DEVERIA** carregar um erro estruturado. | Uma nova requisição de carregamento move um modelo no estado `error` de volta para `loading`. Quando uma requisição nomeia um modelo que está `installed` e cujo `runtime.load_on_demand` é `true`, o serviço o carrega como parte da requisição. Se o modelo não puder ser usado imediatamente e não for carregado sob demanda, o serviço responde `409` com `model_not_ready`. Se o carregamento falhar, o erro é `model_load_failed`. ## 5.4 Operações com modelos {#operations} `GET /lmsp/v1/models/{model_id}` retorna um objeto de modelo. Um ID desconhecido resulta em `404` com `model_not_found`. Dois endpoints opcionais controlam o carregamento explicitamente. Eles estão disponíveis quando a capacidade `model_management` é `true` e exigem o escopo `models:manage` ([seção 10.3](https://madeforagent.com/pt-br/lmsp/1.0/security.md#scopes)): | Endpoint | Comportamento | | --- | --- | | `POST /lmsp/v1/models/{model_id}/load` | Pré-carrega o modelo. Retorna o objeto de modelo com `202 Accepted` quando o carregamento começou, ou `200` quando ele já está `ready`. | | `POST /lmsp/v1/models/{model_id}/unload` | Descarrega o modelo. Retorna o objeto de modelo. Repetir a requisição é inofensivo. | Ambos aceitam um `Idempotency-Key` ([seção 9.2](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#idempotency)). --- # Respostas e streaming > A interface de conversa principal do LMSP, com requisições e itens de saída no estilo Responses, geração síncrona e em streaming, tipos de eventos enviados pelo servidor, IDs de evento, reconexão e ferramentas. Source: https://madeforagent.com/pt-br/lmsp/1.0/responses/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 6.1 Requisição {#request} ```http POST /lmsp/v1/responses Authorization: Bearer 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 } ``` O protocolo principal usa uma estrutura `input` e `output` no estilo Responses, em vez de uma lista simples de strings de mensagem, para que um único formato de requisição possa carregar: - mensagens de vários turnos; - texto, imagens, áudio e arquivos; - chamadas de ferramentas e resultados de ferramentas; - saída estruturada; - resumos de raciocínio; - saída multimodal. O LMSP 1.0 define apenas conteúdo de texto. Os tipos de conteúdo de imagem, áudio e arquivo ficam reservados para versões futuras. | Campo | Obrigatório | Significado | | --- | --- | --- | | `model` | Sim | ID do modelo a usar. | | `input` | Sim | Array de itens de entrada. Um item `message` tem um `role` (`system`, `user` ou `assistant`) e um array `content` de partes, como `input_text`. O uso de ferramentas acrescenta itens `function_call` e `function_call_output` ([seção 6.5](https://madeforagent.com/pt-br/lmsp/1.0/responses.md#tools)). | | `stream` | Não | `true` para receber eventos enviados pelo servidor. O padrão é `false`. | | `max_output_tokens` | Não | Limite superior do número de tokens gerados. | | `temperature` | Não | Temperatura de amostragem. | | `response_format` | Não | `{"type": "text"}` (o padrão) ou `{"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}}` para saída estruturada. Exige a capacidade `structured_output`. | | `tools`, `tool_choice` | Não | Ferramentas de função que o modelo pode chamar ([seção 6.5](https://madeforagent.com/pt-br/lmsp/1.0/responses.md#tools)). Exige a capacidade `tools`. | | `store` | Não | Pede ao serviço que guarde a resposta, para que ela possa ser recuperada depois e usada como `previous_response_id`. O padrão é `false`. Ignorado por serviços sem a capacidade `conversations`. | | `previous_response_id` | Não | Continua a partir de uma resposta armazenada. Exige a capacidade `conversations`. | | `extensions` | Não | Extensões privadas ([seção 9.1](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#versioning)). | Uma requisição que exige uma capacidade que o modelo não tem é rejeitada com `400` e `unsupported_capability`. Uma requisição que não cabe na janela de contexto é rejeitada com `400` e `context_length_exceeded`. Um serviço que consegue armazenar conversas **PODE** também suportar `previous_response_id`. Caso contrário, toda requisição **DEVE** carregar o contexto completo. Um serviço **NÃO DEVE** depender da conexão HTTP para manter o estado da conversa. ## 6.2 Resposta síncrona {#sync} Quando `stream` é `false`, o serviço retorna `200 OK` com um objeto de resposta depois que a geração termina. ```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 } ``` | Campo | Significado | | --- | --- | | `id` | Identificador da resposta, como `resp_...`. | | `object` | Sempre `"response"`. | | `created_at` | Momento da criação, em segundos desde a época Unix. | | `status` | `in_progress`, `completed`, `incomplete`, `failed` ou `cancelled`. Uma resposta síncrona é retornada em um status final. | | `model` | ID do modelo que produziu a resposta. | | `output` | Array de itens de saída. | | `usage` | Contagens de tokens: `input_tokens`, `output_tokens` e `total_tokens`. | | `error` | `null` ou um objeto de problema ([seção 9.3](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#errors)) quando `status` é `failed`. | | `incomplete_details` | `null` ou um objeto com um `reason`, como `max_output_tokens`, quando `status` é `incomplete`. | Tipos de itens de saída: | Tipo de item | Formato | | --- | --- | | `message` | `id`, `role` (`assistant`) e `content`, um array de partes `output_text` que têm, cada uma, um `text`. | | `function_call` | `id`, `call_id`, `name` e `arguments`, uma string codificada em JSON. | | `reasoning` | `id` e `summary`, um array de partes `summary_text` que têm, cada uma, um `text`. | Se a geração falhar, uma requisição síncrona é respondida com um status de erro e um documento de problema ([seção 9.3](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#errors)), e não com um objeto de resposta. O status `failed` aparece em streams, tarefas e respostas armazenadas. `GET /lmsp/v1/responses/{response_id}` retorna uma resposta que foi armazenada com `store: true`. É opcional e exige a capacidade `conversations`. Um ID desconhecido resulta em `404` com `response_not_found`. ## 6.3 Streaming {#streaming} Para fazer streaming, defina `stream` na requisição: ```json { "stream": true } ``` O serviço responde `200 OK` com `Content-Type: text/event-stream` e envia eventos semânticos. Cada evento tem um `id`, um nome `event` e um objeto 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}} ``` Pelo menos estes eventos são definidos: | Evento | Significado | Campos de dados | | --- | --- | --- | | `response.created` | A resposta foi criada. | `response_id`, `status` (`in_progress`) | | `response.output_item.added` | Um novo item de saída começou. | `response_id`, `output_index`, `item` | | `response.output_text.delta` | Texto foi acrescentado a um item de mensagem. | `response_id`, `item_id`, `delta` | | `response.output_item.done` | Um item de saída está completo. | `response_id`, `output_index`, `item` | | `response.completed` | A resposta terminou. Evento final. | `response_id`, `status`, `usage` | | `response.incomplete` | A geração parou antes do fim, por exemplo no limite de tokens. Evento final. | `response_id`, `status`, `incomplete_details`, `usage` | | `response.failed` | A geração falhou. Evento final. | `response_id`, `status`, `error` | | `response.cancelled` | A resposta foi cancelada. Evento final. | `response_id`, `status` | | `error` | Um problema que não está ligado a uma única resposta, após o qual o fluxo não pode continuar. | `error`, um objeto de problema | Um serviço fecha o fluxo após um evento final ou um evento `error`. Os serviços **PODEM** enviar eventos adicionais, por exemplo para argumentos de chamadas de ferramentas, imagens, áudio e deltas de JSON estruturado. Os clientes **DEVEM** ignorar os tipos de evento que não conhecem. Se o cliente fechar a conexão de uma requisição em streaming, o serviço **DEVERIA** parar de gerar. ## 6.4 IDs de evento e reconexão {#reconnection} O `id` de um evento **DEVE** ser um número de sequência inteiro, estritamente crescente dentro da resposta, começando em 1. Após uma conexão interrompida, um cliente retoma enviando o último ID que recebeu. Ele faz isso com um cabeçalho: ```http Last-Event-ID: 2 ``` ou com um parâmetro de consulta: ```http GET /lmsp/v1/tasks/{task_id}/events?after=2 ``` Ambos vão para o endpoint de eventos de uma tarefa ([seção 7.4](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#events)). O serviço reenvia apenas os eventos cujo número de sequência é maior que 2. Se ambos estiverem presentes, `after` prevalece. Se os eventos solicitados forem mais antigos que o período de retenção, o serviço responde `410 Gone` com o erro `event_history_expired`. O cliente então busca o resultado final, com `GET /lmsp/v1/tasks/{task_id}`. Uma resposta enviada em streaming diretamente por `POST /lmsp/v1/responses` pertence àquela conexão HTTP e não pode ser retomada. Um cliente que precisa de saída retomável **DEVERIA** criar uma [tarefa](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md) e acompanhar os seus eventos. ## 6.5 Chamadas de ferramentas {#tools} O LMSP 1.0 define ferramentas de função que o cliente executa. O serviço não executa ferramentas por conta própria. O escopo `tools:execute` é reservado para extensões que o fazem ([seção 10.3](https://madeforagent.com/pt-br/lmsp/1.0/security.md#scopes)). Primeiro, o cliente lista as ferramentas. Cada entrada tem `type` definido como `function`, um `name`, uma `description` e `parameters`, um objeto JSON Schema. `tool_choice` é `auto` (o padrão), `none`, `required` ou `{"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" } ``` Quando o modelo decide chamar uma ferramenta, a resposta contém um item `function_call`. Seus `arguments` são uma string codificada em JSON. Em um stream, o item chega completo em `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 } ``` O cliente executa a ferramenta e então envia uma nova requisição que carrega o contexto completo: os itens de entrada anteriores, o item `function_call` como foi recebido e um item `function_call_output` com o mesmo `call_id`. Seu `output` é uma string, geralmente codificada em JSON. ```json { "type": "function_call_output", "call_id": "call_01J8M7B3N9T2V5X8Z1C4D7F0HM", "output": "{\"temperature_c\":17,\"condition\":\"light rain\"}" } ``` --- # Tarefas assíncronas > Como o LMSP executa gerações longas como tarefas persistidas, com criação de tarefas, a máquina de estados, cancelamento idempotente, fluxos de eventos e políticas de reinicialização para tarefas inacabadas. Source: https://madeforagent.com/pt-br/lmsp/1.0/tasks/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 7.1 Criar uma tarefa {#create} Um cliente cria uma tarefa enviando por POST a requisição de resposta que deseja executar, envolvida em um envelope de tarefa. Um cabeçalho `Idempotency-Key` é recomendado ([seção 9.2](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#idempotency)). ```http POST /lmsp/v1/tasks Authorization: Bearer Idempotency-Key: 01J8M7C4Y3N5P8R2T6V9X1Z4BH ``` ```json { "type": "response", "input": { "model": "qwen3:14b-q4_k_m", "input": [ { "type": "message", "role": "user", "content": [ { "type": "input_text", "text": "Write a long report." } ] } ] }, "on_restart": "fail" } ``` | Campo | Obrigatório | Significado | | --- | --- | --- | | `type` | Sim | `response`, o único tipo de tarefa na 1.0. | | `input` | Sim | Uma requisição de resposta, exatamente como em `POST /lmsp/v1/responses`. Seu campo `stream` é ignorado. | | `on_restart` | Não | `fail` (o padrão), `retry` ou `resume`. Veja a [seção 7.5](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#restart). | O serviço **DEVE** persistir a tarefa antes de responder. Em seguida, ele retorna: ```http HTTP/1.1 202 Accepted ``` ```json { "id": "task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC", "object": "task", "type": "response", "status": "queued", "created_at": 1794200100, "updated_at": 1794200100, "response_id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW", "events_url": "/lmsp/v1/tasks/task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC/events", "on_restart": "fail", "response": null, "error": null } ``` | Campo da tarefa | Significado | | --- | --- | | `id` | Identificador da tarefa, como `task_...`. | | `object` | Sempre `"task"`. | | `type` | `response`. | | `status` | O estado atual ([seção 7.2](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#states)). | | `created_at`, `updated_at` | Momentos em segundos desde a época Unix. | | `response_id` | ID da resposta que a tarefa produz. É atribuído quando a tarefa é criada. | | `events_url` | Caminho do fluxo de eventos. Presente quando a capacidade `event_resume` é `true`. | | `on_restart` | A política de reinicialização da tarefa. | | `response` | O objeto de resposta quando `status` é `succeeded`; caso contrário, `null`. | | `error` | Um objeto de problema ([seção 9.3](https://madeforagent.com/pt-br/lmsp/1.0/common-rules.md#errors)) quando `status` é `failed`; caso contrário, `null`. | `GET /lmsp/v1/tasks/{task_id}` retorna o objeto da tarefa. Os clientes que não usam fluxos de eventos consultam este endpoint periodicamente. Um ID desconhecido resulta em `404` com `task_not_found`. Uma tarefa concluída tem esta aparência: ```json { "id": "task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC", "object": "task", "type": "response", "status": "succeeded", "created_at": 1794200100, "updated_at": 1794200162, "response_id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW", "events_url": "/lmsp/v1/tasks/task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC/events", "on_restart": "fail", "response": { "id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW", "object": "response", "created_at": 1794200100, "status": "completed", "model": "qwen3:14b-q4_k_m", "output": [ { "id": "msg_01J8M8R6A2C5E8G1J4M7P0S3VY", "type": "message", "role": "assistant", "content": [ { "type": "output_text", "text": "Local model services make on-device inference a shared, discoverable utility..." } ] } ], "usage": { "input_tokens": 12, "output_tokens": 1480, "total_tokens": 1492 }, "error": null, "incomplete_details": null }, "error": null } ``` ## 7.2 Máquina de estados {#states} ```text queued --> loading --> running --> succeeded | | | | | +--> failed | | +--> cancelling --> cancelled | +--------------> failed +--------------------------> cancelled ``` | Estado | Significado | Próximos estados | | --- | --- | --- | | `queued` | Aceita e persistida, aguardando para começar. | `loading`, `cancelled`, `failed` | | `loading` | O modelo está sendo carregado. | `running`, `cancelling`, `failed` | | `running` | O modelo está gerando. | `succeeded`, `failed`, `cancelling` | | `cancelling` | O cancelamento foi solicitado, e o backend ainda não parou. | `cancelled` | | `succeeded` | Final. A resposta está completa. | nenhum | | `failed` | Final. | nenhum | | `cancelled` | Final. | nenhum | Os estados terminais são `succeeded`, `failed` e `cancelled`. Uma tarefa em estado terminal **NÃO DEVE** mudar novamente. Uma tarefa cuja resposta termina como `incomplete`, por exemplo no limite de tokens, é `succeeded`. Toda transição é atômica, de modo que uma tarefa nunca fica cancelada e concluída ao mesmo tempo. Vale a transição que for confirmada primeiro. ## 7.3 Cancelamento {#cancel} ```http POST /lmsp/v1/tasks/{task_id}/cancel ``` O serviço retorna `200 OK` e o objeto da tarefa atual. Uma tarefa `queued` passa a `cancelled` imediatamente. Uma tarefa `loading` ou `running` passa a `cancelling` até que o backend tenha parado e, depois, a `cancelled`. O cancelamento **DEVE** ser idempotente. Cancelar uma tarefa que já está `cancelling` ou `cancelled` retorna a tarefa atual e não produz novo erro. Cancelar uma tarefa que já está `succeeded` ou `failed` é respondido com `409` e `task_not_cancelable`. Um ID desconhecido resulta em `404` com `task_not_found`. ## 7.4 Fluxos de eventos {#events} ```http GET /lmsp/v1/tasks/{task_id}/events Accept: text/event-stream ``` Este endpoint é opcional. Ele está disponível quando a capacidade `event_resume` é `true`. - Os eventos são os eventos de resposta da [seção 6.3](https://madeforagent.com/pt-br/lmsp/1.0/responses.md#streaming), para a resposta que a tarefa produz. A numeração e a retomada seguem a [seção 6.4](https://madeforagent.com/pt-br/lmsp/1.0/responses.md#reconnection). - O fluxo começa com `response.created`, que é registrado quando a tarefa é aceita. Ele termina com um único evento final que corresponde ao resultado: `response.completed`, `response.incomplete`, `response.failed` ou `response.cancelled`. - Um cliente que se conecta tarde recebe primeiro os eventos que perdeu e depois os eventos ao vivo. O serviço fecha o fluxo após o evento final. - Os eventos são mantidos por um período de retenção ([seção 11.2](https://madeforagent.com/pt-br/lmsp/1.0/persistence.md#rules)). Eventos mais antigos resultam em `410 Gone` com `event_history_expired`. ## 7.5 Semântica de reinicialização {#restart} `on_restart` define o que acontece com uma tarefa inacabada quando o serviço é reiniciado: | Valor | Comportamento | | --- | --- | | `fail` | O padrão. O serviço marca a tarefa inacabada como `failed`, com o código de erro `server_restarted`. | | `retry` | O serviço executa a tarefa novamente desde o início. | | `resume` | O serviço continua a partir de um snapshot. Isso só é permitido quando o backend suporta explicitamente snapshots retomáveis. Caso contrário, a requisição de criação é rejeitada com `400` e `unsupported_capability`. | Uma tarefa que está `cancelling` quando o serviço reinicia conclui o seu cancelamento e passa a `cancelled`, qualquer que seja a sua política. `retry` não é recomendado como padrão, porque a tarefa pode já ter executado ferramentas ou produzido efeitos colaterais externos. Um cliente que escolhe `retry` **DEVE** combiná-lo com um `Idempotency-Key` e tornar suas chamadas de ferramentas idempotentes. --- # Compatibilidade com OpenAI e Ollama > Como um serviço LMSP continua compatível com clientes OpenAI e Ollama existentes por meio de uma fina camada de conversão de dados sobre um único núcleo de execução, e onde essa compatibilidade termina. Source: https://madeforagent.com/pt-br/lmsp/1.0/compatibility/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 8.1 Endpoints compatíveis com a OpenAI {#openai} Um serviço **DEVERIA** oferecer uma interface compatível com a OpenAI ao lado da interface LMSP e declará-la em `interfaces` com `kind` definido como `openai`. Para atender aos clientes existentes, um serviço que faz isso **DEVE** implementar pelo menos estes endpoints sob o prefixo `/v1`: | Endpoint | Observações | | --- | --- | | `GET /v1/models` | Lista os modelos do catálogo LMSP. Cada `id` é o ID de modelo do LMSP. | | `POST /v1/chat/completions` | Chat Completions, com e sem streaming. | | `POST /v1/responses` | O formato OpenAI Responses. | | `POST /v1/embeddings` | A interface principal do LMSP 1.0 não tem endpoint de embeddings. O adaptador serve este endpoint diretamente, para modelos cujo `capabilities.embeddings` é `true`. | Esses endpoints aceitam os mesmos tokens de portador que a interface LMSP. Um cliente que fala o protocolo OpenAI define o token do LMSP como sua chave de API. Uma primeira implementação pode começar com `/v1/models` e `/v1/chat/completions` ([página 12](https://madeforagent.com/pt-br/lmsp/1.0/mvp.md)). ## 8.2 Endpoints compatíveis com o Ollama {#ollama} Um serviço **DEVERIA** fornecer também estes endpoints, para que os clientes escritos para o Ollama funcionem igualmente: | Endpoint | Observações | | --- | --- | | `GET /api/tags` | Lista os modelos do catálogo LMSP. | | `POST /api/chat` | Chat. | | `POST /api/generate` | Geração de texto simples. | Um serviço que os fornece declara uma interface com `kind` definido como `ollama`. ## 8.3 Um único núcleo de execução {#core} A camada de compatibilidade **DEVE** apenas converter dados. Ela **NÃO DEVE** criar um segundo conjunto de lógica de gerenciamento de modelos. Uma requisição em uma interface de compatibilidade é mapeada para uma resposta LMSP, roda no mesmo núcleo e no mesmo adaptador que uma requisição nativa e usa o mesmo catálogo de modelos e a mesma autenticação. ```text OpenAI Chat Completions | mapeamento da requisição v LMSP Response | adaptação ao backend v llama.cpp / Ollama / vLLM / outros ambientes de execução ``` Nos endpoints `/v1` e `/api`, um serviço **DEVERIA** relatar os erros no formato que a API correspondente define, para que clientes não modificados consigam interpretá-los. A interface LMSP sempre usa `application/problem+json`. ## 8.4 Limites {#boundaries} A compatibilidade tem limites, e vale a pena enunciá-los com clareza: - Um cliente existente compatível com a OpenAI geralmente só precisa de um `base_url` alterado. Ele não ganha automaticamente a descoberta do LMSP. - Somente os clientes que suportam o LMSP conseguem descobrir um serviço automaticamente, ler suas capacidades detalhadas, retomar fluxos de eventos e gerenciar tarefas assíncronas. - Nenhum protocolo do lado do servidor consegue fazer funcionar um cliente que não pode ser configurado e aceita apenas endereços oficiais de nuvem. --- # 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: ``` 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. --- # Segurança local > Requisitos de segurança para serviços LMSP, com vínculo ao loopback, pareamento e tokens de portador, escopos, verificações de Origin e Host contra páginas web maliciosas, modo LAN e regras de logs. Source: https://madeforagent.com/pt-br/lmsp/1.0/security/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 10.1 Linha de base {#baseline} Escutar apenas em localhost não é segurança absoluta: uma página web maliciosa ainda pode tentar alcançar portas locais. Por isso o LMSP combina várias medidas. - Um serviço **DEVE** se vincular por padrão aos endereços de loopback. Ele **NÃO DEVE** escutar em `0.0.0.0`, nem em qualquer outro endereço que não seja de loopback, a menos que o modo LAN esteja ativado ([seção 10.5](https://madeforagent.com/pt-br/lmsp/1.0/security.md#lan)). - Na primeira execução, um serviço **DEVERIA** gerar um segredo de serviço aleatório de alta entropia e usá-lo, em vez de qualquer valor padrão embutido, para emitir e verificar tokens. - Toda requisição à interface principal **DEVE** carregar um token de portador válido, exceto nos endpoints de bootstrap listados na [seção 4.2](https://madeforagent.com/pt-br/lmsp/1.0/endpoints.md#conventions). Vir do loopback nunca basta por si só. ## 10.2 Pareamento e tokens {#pairing} Um cliente obtém seu próprio token de portador com um código de pareamento local. O usuário pede ao serviço que mostre um código de pareamento, da maneira que o serviço oferecer, e o cliente o envia: ```http POST /lmsp/v1/pair Content-Type: application/json ``` ```json { "client_name": "example-client", "pairing_code": "K7QD-4M2X", "scopes": ["inference"] } ``` | Campo da requisição | Significado | | --- | --- | | `client_name` | Nome de exibição do cliente, mostrado ao usuário. | | `pairing_code` | O código que o usuário obteve do serviço. | | `scopes` | Lista opcional de escopos solicitados. O padrão é `["inference"]`. | O serviço responde com um token. O `token_type` é sempre `Bearer`: ```json { "client_id": "cli_01J8MAT3W6X9B2D5F8H1K4N7QZ", "access_token": "lmsp_example_3f9a1c52e7d84b60", "token_type": "Bearer", "scopes": ["inference"] } ``` O cliente então envia `Authorization: Bearer ` em todas as requisições. - Um código de pareamento **DEVE** ser de uso único e **DEVERIA** expirar em até 5 minutos. Ele **DEVERIA** ter pelo menos 40 bits de entropia. Um serviço **DEVE** limitar a taxa de tentativas malsucedidas. Um código errado ou expirado é respondido com `401` e `unauthorized`. - Os tokens são independentes por cliente, de modo que o usuário pode revogar um cliente sem afetar os demais. Um serviço **DEVERIA** permitir que o usuário liste e revogue os clientes pareados. - Um cliente **DEVERIA** guardar seu token no chaveiro ou no gerenciador de credenciais do sistema operacional. Um serviço **DEVERIA** armazenar apenas um hash de cada token. - Um token ausente, inválido ou revogado é respondido com `401`, `unauthorized` e um cabeçalho `WWW-Authenticate: Bearer`. Um token válido que não tem o escopo exigido por um endpoint é respondido com `403` e `forbidden`. ## 10.3 Escopos {#scopes} As permissões são divididas em escopos separados. Baixar modelos, excluir modelos e executar ferramentas nunca pegam carona no escopo de inferência. | Escopo | Permite | | --- | --- | | `inference` | Ler o catálogo de modelos, criar respostas e tarefas, e ler e cancelar as tarefas do próprio cliente. | | `models:manage` | Carregar e descarregar modelos. | | `models:install` | Reservado. Baixar e excluir modelos. | | `tools:execute` | Reservado. Executar ferramentas no lado do serviço. | As tarefas e as respostas armazenadas pertencem ao cliente que as criou. Um serviço **DEVERIA** responder a uma requisição de outro cliente como se elas não existissem (`task_not_found` ou `response_not_found`). ## 10.4 Proteções de navegador e de rede {#browser} - Um serviço **DEVE** rejeitar por padrão as requisições de navegador entre origens diferentes e permitir apenas os valores de `Origin` configurados explicitamente. Uma requisição com qualquer outro `Origin` é respondida com `403` e `forbidden`. - Quando uma origem é permitida, o serviço responde às suas requisições preflight de CORS e envia `Access-Control-Allow-Origin` com exatamente essa origem, nunca com `*`. - Um serviço **DEVE** validar o cabeçalho `Host`, para impedir o DNS rebinding. Ele aceita apenas os nomes de host que atende: os nomes e endereços de loopback, mais quaisquer nomes configurados para o modo LAN. Qualquer outro valor é respondido com `403` e `forbidden`. ## 10.5 Modo LAN {#lan} O modo LAN significa escutar além dos endereços de loopback. - Um serviço **NÃO DEVE** ativar o modo LAN a menos que o usuário o ative explicitamente. - No modo LAN, um serviço **DEVE** exigir autenticação e **DEVERIA** também ativar o TLS. Um cliente **NÃO DEVERIA** enviar um token por HTTP simples para um endereço que não seja de loopback, a menos que o usuário permita explicitamente. - O anúncio mDNS só é permitido no modo LAN, quando o usuário também ativou a descoberta na LAN ([seção 3.2](https://madeforagent.com/pt-br/lmsp/1.0/discovery.md#mdns)). ## 10.6 Logs e privacidade {#logging} - Caminhos de modelos, logs, prompts e conteúdo gerado **NÃO DEVEM** aparecer nos anúncios mDNS. - Por padrão, um serviço **DEVERIA** registrar apenas metadados (horários, endpoints, códigos de status, IDs, contagens de tokens e durações). Ele **NÃO DEVERIA** registrar prompts completos nem conteúdo gerado. - As respostas de integridade e os detalhes de erro **NÃO DEVEM** conter caminhos de modelos, prompts, tokens de acesso nem outras informações sensíveis. --- # Persistência > Como um serviço LMSP armazena seu estado, com um banco SQLite embutido, as tabelas a manter, as regras transacionais para tarefas e eventos, a retenção e a recuperação na inicialização. Source: https://madeforagent.com/pt-br/lmsp/1.0/persistence/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 11.1 Armazenamento {#storage} Um serviço **DEVERIA** manter seu estado em um banco de dados [SQLite](https://www.sqlite.org/) embutido. Um conjunto sugerido de tabelas: | Tabela | Conteúdo | | --- | --- | | `service_config` | Identidade e configuração do serviço. | | `clients` | Clientes pareados, hashes de tokens e escopos. | | `models` | Metadados de modelos e digests de conteúdo. | | `responses` | Respostas armazenadas. | | `tasks` | Tarefas assíncronas. | | `task_events` | O log de eventos de cada tarefa, com números de sequência. | | `idempotency_keys` | Chaves de idempotência, digests de requisições e resultados. | Os arquivos de modelo **DEVEM** ficar fora do banco de dados. O banco guarda apenas metadados e digests de conteúdo. Os nomes e a organização das tabelas são uma escolha de implementação. O que os clientes podem observar, e o que precisa ser interoperável, é o comportamento descrito nas próximas duas seções. ## 11.2 Regras {#rules} Seja qual for o armazenamento que um serviço use, ele: - **DEVE** persistir uma tarefa antes de retornar `202 Accepted`. - **DEVE** atualizar os números de sequência dos eventos e o status da tarefa na mesma transação. - **DEVE** tornar atômica a transição de cancelamento, para evitar a condição de corrida de uma tarefa que é cancelada e depois concluída. - **DEVERIA** manter as tarefas e os eventos concluídos por um período de retenção configurável. - **NÃO DEVE** excluir tarefas inacabadas durante a limpeza de logs. - **DEVE**, na inicialização, varrer as tarefas `queued`, `loading`, `running` e `cancelling` que restaram e aplicar a política de reinicialização de cada uma ([seção 7.5](https://madeforagent.com/pt-br/lmsp/1.0/tasks.md#restart)). ## 11.3 Recuperação na inicialização {#recovery} A tabela mostra o estado para o qual uma tarefa remanescente é movida, de acordo com a sua política `on_restart`: | Estado encontrado na inicialização | `fail` | `retry` | `resume` | | --- | --- | --- | --- | | `queued` | `failed` | `queued` | `queued` | | `loading` | `failed` | `queued` | `queued` | | `running` | `failed` | `queued` | `running`, continuando a partir do snapshot | | `cancelling` | `cancelled` | `cancelled` | `cancelled` | Uma tarefa movida para `failed` recebe o código de erro `server_restarted` e um evento `response.failed`. Uma tarefa movida para `cancelled` recebe um evento `response.cancelled`. O novo estado e o seu evento são gravados em uma única transação ([seção 11.2](https://madeforagent.com/pt-br/lmsp/1.0/persistence.md#rules)). --- # Escopo mínimo viável > Um escopo sugerido para uma primeira implementação do LMSP, com as dez peças que formam um ciclo fechado utilizável e as partes da especificação que podem esperar por versões futuras. Source: https://madeforagent.com/pt-br/lmsp/1.0/mvp/ Language: pt-BR Specification: LMSP 1.0 (draft) Updated: 2026-11-08 ## 12.1 Primeira versão {#scope} A primeira versão não precisa implementar todos os recursos multimodais, o download de modelos nem a voz em tempo real. Ela forma um ciclo fechado utilizável quando oferece: 1. Descoberta de serviços por meio de `/.well-known/lmsp.json`. 2. Anúncio opcional na LAN de `_lmsp._tcp.local.`. 3. `GET /lmsp/v1/models`. 4. `POST /lmsp/v1/responses`, tanto síncrono quanto como fluxo SSE. 5. Tarefas assíncronas: criar, consultar e cancelar, com persistência em SQLite. 6. Retomada de fluxos interrompidos com `Last-Event-ID` ou `after`. 7. Tokens de portador, pareamento local e proteção de `Origin` e `Host`. 8. Os endpoints `/v1/models` e `/v1/chat/completions` compatíveis com a OpenAI. 9. Um arquivo de contrato OpenAPI 3.2 e testes de conformidade entre linguagens. 10. Pelo menos um backend real e uma verificação de que as tarefas se recuperam corretamente após uma reinicialização do serviço. O ponto central deste projeto: o LMSP fornece o conjunto completo de capacidades, a interface OpenAI fornece compatibilidade pronta, o mDNS e a descrição do serviço fornecem descoberta automática, e o modelo de tarefas em SQLite fornece persistência local. ## 12.2 O que pode esperar {#later} Tudo o que a lista acima não menciona pode vir em versões posteriores. Isso inclui os endpoints opcionais (respostas armazenadas e carregamento e descarregamento de modelos), os endpoints `/v1/responses` e `/v1/embeddings` da OpenAI, a API compatível com o Ollama e todo tipo de conteúdo além de texto. Este escopo é um caminho para uma primeira versão utilizável, não um perfil de conformidade. Um serviço que declara conformidade com o LMSP 1.0 ainda implementa todos os endpoints obrigatórios da [página 4](https://madeforagent.com/pt-br/lmsp/1.0/endpoints.md) e o comportamento obrigatório descrito nas outras páginas.