Referência da API
O ollaya serve expõe duas APIs em http://localhost:11435:
- a API nativa em
/api/*, modelada na do Ollama, para decisões e gerenciamento de modelos; - a API compatível com o TypeSafe em
/v1/*, idêntica em nível de protocolo à do TypeSafe, para que os SDKs TypeSafe existentes funcionem sem alterações. Consulte Compatibilidade com o TypeSafe.
| Método | Caminho | Finalidade |
|---|---|---|
GET, HEAD |
/ |
Verificação de atividade (liveness): Ollaya is running |
GET |
/api/version |
Versão do servidor |
POST |
/api/decide |
Responde perguntas tipadas sobre um estado; também carrega e descarrega um modelo |
GET |
/api/tags |
Modelos nesta máquina |
POST |
/api/show |
Detalhes de um modelo |
GET |
/api/ps |
Modelos carregados na memória |
POST |
/api/pull |
Baixa um modelo (transmite o progresso) |
DELETE |
/api/delete |
Exclui um modelo |
POST |
/api/copy |
Copia um modelo para um novo nome |
POST |
/api/create |
Cria um modelo a partir de outro (transmite o progresso) |
POST |
/v1/systemone |
System One do TypeSafe |
POST |
/v1/decisions |
Alias de /v1/systemone |
GET |
/v1/models |
Lista de modelos do TypeSafe |
/api/push e /api/blobs/:digest estão reservados e respondem 501 NOT_IMPLEMENTED. Os endpoints de texto do Ollama (/api/generate, /api/chat, /api/embed) respondem 404: os modelos de decisão nunca geram texto.
Convenções
- JSON. Os corpos de requisição e resposta são objetos JSON. O corpo é analisado como JSON qualquer que seja o
Content-Type, entãocurl -dfunciona como está. As requisições têm no máximo 8 MiB. - Os nomes de campos usam
snake_case. Campos de requisição desconhecidos são ignorados;nullsignifica ausente. - Os nomes de modelos são
[host/][namespace/]model[:tag], sem diferenciar maiúsculas de minúsculas. Uma tag ausente significalatest. As respostas sempre usam a forma canônica, comolaya:latest. - Números. Probabilidades, confianças,
scoreenoulsão arredondados para 4 casas decimais. As durações são inteiros em nanossegundos; os carimbos de data e hora são RFC 3339 em UTC. - Streaming.
/api/pulle/api/createtransmitem JSON delimitado por quebras de linha, um objeto por linha, terminando com exatamente um{"status":"success"}ou uma linha de erro. Envie"stream": falsepara obter uma única resposta. - IDs de requisição. Toda resposta carrega
X-Request-Id, e as respostas de/v1/*tambémx-typesafe-request-id. UmX-Request-Idválido enviado pelo cliente é repetido na resposta. - Concorrência. Um modelo carregado executa uma requisição por vez, e cada requisição responde a todas as suas perguntas em uma única passada. As requisições para o mesmo modelo entram na fila, então enviar mais de uma de cada vez não termina mais cedo; o tempo de ida e volta de cada uma passa a incluir a espera. Faça todas as perguntas sobre um estado em uma única requisição. Modelos carregados diferentes são executados em paralelo.
- Nenhum download implícito. Nenhum endpoint baixa um modelo como efeito colateral. O
ollaya runbaixa primeiro; as aplicações chamam/api/pull.
Erros
Todo erro, em qualquer endpoint, tem este corpo:
{
"error": "model \"laya:xl\" not found, try pulling it first",
"code": "MODEL_NOT_FOUND"
}
| Campo | Significado |
|---|---|
error |
Mensagem legível por humanos. Não a analise; a única mensagem congelada é model "<name>" not found, try pulling it first, como no Ollama. |
code |
Código legível por máquina. Ramifique com base nele. |
detail |
Apenas para INVALID_REQUEST, TOO_MANY_OPTIONS, INPUT_TOO_LONG e STATE_TRUNCATED: cada problema de validação, no formato ValidationError do TypeSafe (do FastAPI): loc, msg, type e às vezes ctx. |
| Código | HTTP | Quando | Nova tentativa |
|---|---|---|---|
INVALID_JSON |
400 | Corpo ausente, não é JSON ou não é um objeto | não |
INVALID_REQUEST |
422 | O corpo não passa na validação; detail lista cada problema |
não |
TOO_MANY_OPTIONS |
422 | As opções de uma pergunta não cabem no orçamento de opções do modelo | não |
INPUT_TOO_LONG |
422 | O state tem mais de 65.536 tokens |
não |
STATE_TRUNCATED |
422 | /v1/systemone ou /v1/decisions descartaria parte do state para caber no contexto do modelo |
não |
UNAUTHORIZED |
401 | OLLAYA_API_KEY está definida e a requisição não traz a chave |
não |
FORBIDDEN |
403 | Cabeçalho Origin ou Host do navegador não permitido |
não |
MODEL_NOT_FOUND |
404 | Modelo (ou o destino de um roteador) não está nesta máquina; em um download, não está no registro | não |
NOT_FOUND |
404 | Não existe esse endpoint | não |
METHOD_NOT_ALLOWED |
405 | O endpoint existe, o método não | não |
OPERATION_IN_PROGRESS |
409 | Um download ou uma criação está gravando o mesmo nome de modelo | depois que terminar |
REQUEST_TOO_LARGE |
413 | Corpo acima de 8 MiB | não |
QUEUE_FULL |
503 | Já há OLLAYA_MAX_QUEUE requisições esperando; enviado com Retry-After: 1 |
sim |
MODEL_LOAD_FAILED |
500 | O modelo não pôde ser carregado (arquivos corrompidos, memória, OLLAYA_LOAD_TIMEOUT) |
raramente |
INFERENCE_FAILED |
500 | O runner falhou durante uma decisão | sim |
STORAGE_ERROR |
500 | Disco cheio, permissões ou I/O | não |
INTERNAL |
500 | Um bug; o log do servidor tem detalhes sob o ID da requisição | sim |
UNSUPPORTED_MODEL |
501 | Esta compilação não consegue executar o formato do modelo | não |
NOT_IMPLEMENTED |
501 | Endpoint reservado | não |
REGISTRY_ERROR |
502 | Registro inacessível ou inválido | sim |
DIGEST_MISMATCH |
502 | Um download não correspondeu ao seu sha256 e foi descartado | sim |
O conjunto de códigos é aberto: trate um código desconhecido pelo seu status HTTP. Um erro de validação lista todos os problemas de uma vez:
{
"error": "state: Field required; questions.urgency.score.criteria: List should have at least 2 items after validation, not 1",
"code": "INVALID_REQUEST",
"detail": [
{"loc": ["body", "state"], "msg": "Field required", "type": "missing"},
{
"loc": ["body", "questions", "urgency", "score", "criteria"],
"msg": "List should have at least 2 items after validation, not 1",
"type": "too_short",
"ctx": {"field_type": "List", "min_length": 2, "actual_length": 1}
}
]
}
Depois que um stream começa, uma falha chega como última linha no mesmo formato, por exemplo {"error": "…", "code": "DIGEST_MISMATCH"}. Verifique em cada linha se há error antes de lê-la como progresso.
Perguntas
/api/decide, /v1/systemone e /api/create compartilham um único esquema de perguntas, o do TypeSafe. Uma requisição tem 1–256 perguntas, indexadas por qualquer id; as respostas voltam na mesma ordem.
type |
instructions |
criteria |
Resposta |
|---|---|---|---|
choice |
opcional | obrigatório: objeto rótulo → descrição, ou um array de rótulos; 2–255 opções | choice, confidence, probabilities |
score |
opcional | obrigatório: array de descrições de níveis, o nível 0 primeiro; 2–10 níveis | score, confidence, legend, probabilities |
noul |
opcional | opcional: {"true": "…", "false": "…"} |
noul |
instructionspode ser uma string, um objeto, um array ounull. Quando está ausente ou énull, o modelo lê o id da pergunta, então um id descritivo comois_spamfunciona sozinho.stateé uma string, um objeto ou um array, de até 65.536 tokens. Se exceder o contexto disponível do modelo,/api/decideo trunca e reportastate_truncated: true./v1/systemonee/v1/decisionsretornam422 STATE_TRUNCATEDcom o modelo que respondeu emdetail[0].ctx.model.- Limites do modelo. Cada opção precisa de espaço no contexto do modelo: cerca de 125 opções para
laya:en(512 tokens) e 250 paralaya:multilingual(1.024). Mais do que isso é422 TOO_MANY_OPTIONS. Para um roteador, valem os limites do destino.
As respostas têm os formatos do TypeSafe, nesta ordem de campos:
type |
Campos |
|---|---|
choice |
choice: o rótulo mais provável. confidence. probabilities: rótulo → probabilidade, na ordem de criteria. |
score |
score: o nível esperado Σ i·pᵢ, que pode cair entre níveis. confidence. legend: "0"… → a descrição do nível. probabilities: "0"… → probabilidade. |
noul |
noul: a probabilidade de a afirmação ser verdadeira. Sem confidence, como no TypeSafe. |
confidence é a probabilidade máxima normalizada do TypeSafe, (K · pmax − 1) / (K − 1) para K opções: 0 quando todas as opções são igualmente prováveis, 1 quando uma opção concentra toda a probabilidade. A fórmula é a mesma para todo modelo, mas o que uma dada confiança significa não é: os modelos são calibrados de forma diferente, então ajuste um limiar por modelo nos seus próprios dados. As probabilidades são calibradas com as temperaturas de cada modelo. Em uma GPU CUDA roda o grafo fp16, cujas respostas podem diferir do fp32 em empates apertados.
keep_alive
Por quanto tempo um modelo permanece carregado depois que uma requisição termina, com a semântica do Ollama:
| Valor | Significado |
|---|---|
"5m", "1h30m", "300ms", 300, "300" |
Permanece carregado esse tempo após a requisição |
0, "0", "0s" |
Descarrega assim que a requisição termina |
-1, "-5m", qualquer valor negativo |
Permanece carregado até o servidor parar ou um descarregamento explícito |
ausente ou null |
OLLAYA_KEEP_ALIVE, padrão 5m |
O cronômetro começa quando uma requisição termina, e o valor da requisição mais recente prevalece. Para um roteador, ele se aplica ao destino que respondeu. O /v1/* ignora keep_alive.
Decidir
POST /api/decide
Responde perguntas tipadas sobre um estado em uma única passada direta. O corpo é o corpo de /v1/systemone mais opções nativas; a resposta é a resposta do TypeSafe mais campos nativos, então um cliente TypeSafe também consegue analisá-la.
| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
model |
string | sim | Nome do modelo |
state |
string, objeto ou array | sim para decidir | Sem ele, a requisição carrega ou descarrega o modelo (abaixo) |
questions |
objeto | sim, a menos que o modelo tenha perguntas integradas | Substitui por completo as perguntas do próprio modelo |
preset |
string | não | O nome de uma predefinição, integrada ou personalizada, em vez de questions |
images |
array de strings | não | Para um modelo de visão: imagens PNG, em base64 ou URLs data: em base64. Decider aceita uma; winnow:e4b-vision aceita até 16. Consulte Imagens |
keep_alive |
string ou number | não | Consulte keep_alive |
extras |
array de strings | não | ["laya"] adiciona a confiança própria e a probabilidade de ato do laya a cada resposta |
stream |
boolean | não | Reservado; true é rejeitado |
curl http://localhost:11435/api/decide -d '{
"model": "laya",
"state": "I was charged twice for my subscription this month. Please refund the second charge.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {
"billing": "Payments, invoices and refunds",
"technical": "Bugs, errors and outages",
"account": "Login, profile and settings"
}
},
"urgency": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": ["Can wait", "Needs attention this week", "Needs attention today"]
},
"refund": {
"type": "noul",
"instructions": "The customer asks for money back.",
"criteria": {"true": "Asks for a refund", "false": "Does not ask for a refund"}
}
},
"keep_alive": "10m"
}'
{
"model": "laya:en",
"answers": {
"department": {
"type": "choice",
"choice": "billing",
"confidence": 0.7781,
"probabilities": {"billing": 0.8521, "technical": 0.0611, "account": 0.0868}
},
"urgency": {
"type": "score",
"score": 1.1982,
"confidence": 0.3418,
"legend": {"0": "Can wait", "1": "Needs attention this week", "2": "Needs attention today"},
"probabilities": {"0": 0.1203, "1": 0.5612, "2": 0.3185}
},
"refund": {"type": "noul", "noul": 0.9127}
},
"usage": {"input_tokens": 118, "output_tokens": 0},
"routing": {
"router": "laya:latest",
"model": "laya:en",
"route": "english",
"reason": "English Latin text"
},
"state_truncated": false,
"done_reason": "decide",
"created_at": "2026-09-24T09:30:12.418Z",
"total_duration": 18734512,
"load_duration": 0,
"eval_duration": 16302117
}
| Campo | Significado |
|---|---|
model |
O modelo que respondeu: para um roteador, seu destino (laya:en para uma requisição de laya) |
answers |
Id de pergunta → resposta, na ordem das perguntas |
usage |
input_tokens lidos; output_tokens é sempre 0 |
routing |
Para um roteador: router, o model escolhido, uma chave route estável e um reason informativo. null caso contrário. |
state_truncated |
true se parte do estado foi descartada para caber no contexto do modelo |
done_reason |
"decide", "load" ou "unload" |
created_at |
Quando a resposta foi produzida |
total_duration |
Nanossegundos desde o recebimento da requisição até a resposta, incluindo a fila |
load_duration |
Nanossegundos gastos esperando o modelo carregar; 0 quando ele já estava quente |
eval_duration |
Nanossegundos no runner: tokenização, passada direta, calibração |
Com "extras": ["laya"], cada resposta também tem um objeto laya: confidence (a confiança do laya baseada em entropia) e act_probability (da cabeça de ato do modelo, ou null).
Imagens
Um modelo de visão (decider:2b-vision ou winnow:e4b-vision) responde perguntas sobre uma imagem além do estado. Envie a imagem em images, codificada em base64, do mesmo modo que o images do Ollama funciona:
curl http://localhost:11435/api/decide -d '{
"model": "decider:2b-vision",
"state": "A photo from the warehouse camera.",
"images": ["'"$(base64 -w0 shelf.png)"'"],
"questions": {
"blocked": {"type": "noul", "instructions": "Is the aisle blocked?"},
"fill": {"type": "score", "instructions": "How full is the shelf?", "criteria": ["empty", "half full", "full"]}
}
}'
- Decider: Uma imagem por requisição, apenas PNG. O pré-processamento do modelo é reproduzido valor a valor, então os pixels precisam corresponder ao que os autores do modelo decodificam. Os decodificadores de JPEG do Rust diferem do libjpeg-turbo em até 4 níveis em alguns pixels, então o JPEG ainda não é aceito: converta-o para PNG primeiro.
- Decider: A imagem é redimensionada para múltiplos de 32 pixels, como o modelo espera, e pode ter no máximo 4.096 patches de 16x16 pixels depois disso, cerca de um megapixel (1024x1024). Uma imagem maior recebe um 422 que diz isso; reduza-a antes.
- Decider: As perguntas aceitam no máximo 10 opções. O mesmo modelo também responde a requisições apenas de texto.
- Winnow E4B vision: até 16 PNGs ordenados, 2–64 opções por pergunta, dentro do contexto combinado de imagem/estado/pergunta. O projetor correspondente é descarregado separadamente da mesma revisão do autor. As tags de texto existentes da Winnow não o carregam.
- Um modelo que não lê imagens responde a uma requisição com
imagescom um 422.
/v1/systemone e /v1/decisions permanecem idênticos à API do TypeSafe, que não tem campo de imagem.
Carregar e descarregar. Uma requisição sem state e questions nunca decide. Sem keep_alive, ou com um valor positivo ou negativo, ela carrega o modelo (todos os destinos, no caso de um roteador) e retorna done_reason: "load". Com keep_alive: 0 ela o descarrega ("unload"). O ollaya run pré-carrega desse modo, e o ollaya stop descarrega.
curl http://localhost:11435/api/decide -d '{"model": "laya:en", "keep_alive": -1}'
curl http://localhost:11435/api/decide -d '{"model": "laya:en", "keep_alive": 0}'
Uma decisão não tem efeito colateral sobre dados armazenados, então é seguro tentar de novo.
Predefinições
Uma predefinição é um conjunto nomeado de perguntas. Seis são integradas (triage, email, guard, moderation, router, agent), e você pode salvar as suas próprias. Envie "preset": "NAME" para /api/decide no lugar de questions.
curl http://localhost:11435/api/presets/create -d '{
"name": "billing-check",
"description": "Billing, and how upset the customer is",
"questions": {
"billing": {"type": "noul", "instructions": "The message is about a charge, an invoice or a refund."},
"tone": {"type": "choice", "instructions": "How does the customer sound?", "criteria": {"calm": null, "annoyed": null, "angry": null}}
}
}'
curl http://localhost:11435/api/decide -d '{"model": "winnow:e4b", "state": "I was charged twice this month.", "preset": "billing-check"}'
| Endpoint | Corpo | Efeito |
|---|---|---|
GET /api/presets |
– | Predefinições integradas, depois as personalizadas: name, builtin, description, ids de pergunta, modified_at |
POST /api/presets/create |
name, questions, description (opcional) |
Salva uma predefinição personalizada, substituindo uma com o mesmo nome |
POST /api/presets/show |
name |
Uma predefinição com as suas perguntas |
DELETE /api/presets/delete |
name |
Exclui uma predefinição personalizada |
Os nomes têm de 1 a 64 caracteres de letras minúsculas, dígitos, - e _. Um nome integrado não pode ser reutilizado (422) nem excluído (403), e um nome desconhecido é um 404. As predefinições personalizadas são armazenadas junto dos modelos, então todo cliente do servidor vê as mesmas.
Roteadores
Um roteador como laya (laya:latest) não tem pesos: para cada requisição ele escolhe um de seus destinos, que então responde. O laya lê apenas o state:
| Estado | route |
Respondido por |
|---|---|---|
| Inglês | english |
laya:en |
| Predominantemente escrita não latina (árabe, cirílico, CJK, …) | multilingual |
laya:multilingual |
| Escrita latina, mas não inglês (turco, alemão, …) | multilingual |
laya:multilingual |
| Nenhuma letra | english (o padrão) |
laya:en |
Textos curtos em maiúsculas e sem letras acentuadas, como nomes de comerciantes em uma fatura de cartão (MIGROS KADIKOY ISTANBUL TR), SKUs ou nomes de usuário, geralmente não podem ser identificados e vão para laya:en. Se você sabe o idioma, peça laya:multilingual ou laya:en diretamente; o model da resposta diz qual checkpoint respondeu.
O roteamento custa microssegundos. Ramifique com base em route, nunca em reason, cujo texto pode mudar. O laya:typed-decisions nunca é escolhido pelo roteador; peça-o diretamente.
Listar modelos locais
GET /api/tags
Os modelos nesta máquina, do mais novo para o mais antigo. Cada entrada tem name, model (o mesmo), modified_at, size em bytes, digest (sha256 do manifesto, em hex puro) e details: parent_model, format (onnx, gguf ou router), family, families, parameter_size e quantization_level (as precisões que ele carrega, como F16/F32, ou a quantização de um modelo GGUF, como Q8_0).
{
"models": [
{
"name": "laya:en",
"model": "laya:en",
"modified_at": "2026-09-24T08:11:02.117Z",
"size": 853634822,
"digest": "bf30e4654e9483ff1e6a4fe6fb21b8a71baff6c8a01013046e7d13339020efd7",
"details": {
"parent_model": "",
"format": "onnx",
"family": "laya",
"families": ["laya"],
"parameter_size": "421M",
"quantization_level": "F16/F32"
}
}
]
}
Mostrar detalhes de um modelo
POST /api/show
curl http://localhost:11435/api/show -d '{"model": "laya:en"}'
| Campo | Significado |
|---|---|
license |
Texto da licença |
modelfile |
Um Modelfile que recria o modelo |
parameters |
Parâmetros definidos no modelo, um name value por linha, como precision fp32 |
questions |
Perguntas integradas, ou null |
router |
Para um roteador: strategy, default e routes (rota → modelo). null caso contrário. |
details |
Como em /api/tags |
model_info |
general.architecture, general.languages, general.source (o repositório fixado do Hugging Face), mais chaves específicas da família, como laya.context_length. general.languages lista os idiomas para os quais o modelo foi treinado e avaliado (multilingual para muitos); um modelo construído sobre uma base multilíngue ainda pode ler outros idiomas, então meça nos seus dados. |
capabilities |
Tipos de pergunta que ele responde (choice, score, noul), mais act se tiver uma cabeça de ato |
modified_at |
Como em /api/tags |
Um roteador é mostrado como ele mesmo, não resolvido para um destino.
Listar modelos em execução
GET /api/ps
Os modelos carregados, ordenados por nome. Os roteadores nunca aparecem; seus destinos carregados, sim. Cada entrada tem name, model, size (memória, RAM mais VRAM), digest, details (com a precisão realmente carregada: F16 ou F32, ou a quantização de um modelo GGUF), expires_at (quando ele será descarregado, ou null quando mantido carregado), size_vram, context_length e device (cpu, cuda:0, metal, …).
Baixar um modelo
POST /api/pull
{"model": "laya:en"}
Baixa o modelo para o armazenamento local e verifica cada blob em relação ao seu sha256. Baixar um roteador também baixa todos os modelos para os quais ele roteia. Só as camadas de que esta máquina precisa são baixadas, blobs compartilhados entre modelos são baixados uma vez, e downloads interrompidos são retomados.
A resposta transmite o progresso, com as strings de status do Ollama:
{"status":"pulling manifest"}
{"status":"pulling 891102d37268","digest":"sha256:891102d372688fc2a094dac56a384bc537b87c63f21f9f3dac0be2b7cbc8d86c","total":842609210,"completed":420557117}
{"status":"pulling 891102d37268","digest":"sha256:891102d372688fc2a094dac56a384bc537b87c63f21f9f3dac0be2b7cbc8d86c","total":842609210,"completed":842609210}
{"status":"verifying sha256 digest"}
{"status":"writing manifest"}
{"status":"success"}
Um modelo só aparece em /api/tags depois de writing manifest. Para um roteador há um único success, no final. Um nome que não é analisado, um modelo que não está no registro e um registro inacessível são erros HTTP comuns (422, 404, 502) antes de o stream começar, então curl --fail funciona. Com "stream": false a resposta é {"status": "success"} quando termina. Um segundo download do mesmo nome se junta ao que está em andamento. Seguro tentar de novo.
Excluir um modelo
DELETE /api/delete
{"model": "triage"}
Remove o nome, e os blobs que nenhum outro modelo usa. Um modelo carregado é descarregado assim que suas requisições terminam; excluir um roteador mantém seus destinos. A resposta é 200 com corpo vazio, e 404 MODEL_NOT_FOUND quando o nome não existe; após um timeout, trate isso como sucesso.
Copiar um modelo
POST /api/copy
{"source": "laya:en", "destination": "my-guardrail"}
Copia um modelo para um novo nome, sobrescrevendo um destino existente. A resposta é 200 com corpo vazio.
Criar um modelo
POST /api/create
A API por trás de ollaya create -f Modelfile: a CLI lê o Modelfile e os arquivos que ele nomeia e envia seus conteúdos como JSON.
| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
model |
string | sim | Nome a criar |
from |
string | sim | Um modelo local, possivelmente um roteador. Ele nunca é baixado. |
questions |
objeto | não | Perguntas integradas, validadas como uma requisição de decisão |
calibration |
objeto | não | temperature: até 3 números (choice, score, noul). temperature_by_options: "<type>:<2|3-5|6-10|11+>" → number. |
parameters |
objeto | não | precision: "fp16" ou "fp32", para fixar um grafo |
license |
string ou array | não | Texto(s) da licença |
description |
string | não | Uma linha, mostrada por /v1/models e ollaya show |
stream |
boolean | não | Padrão true |
curl http://localhost:11435/api/create -d '{
"model": "triage",
"from": "laya:en",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": ["billing", "technical", "account"]
}
},
"parameters": {"precision": "fp32"},
"description": "Support ticket triage"
}'
O stream reporta using existing layer sha256:… para cada camada herdada, creating new layer sha256:… para cada nova, depois writing manifest e success. As camadas são endereçadas por conteúdo, então repetir uma criação produz o mesmo modelo.
Versão
GET /api/version
{"version": "0.1.0"}
Endpoints compatíveis com o TypeSafe
| Endpoint | Descrição |
|---|---|
POST /v1/systemone |
Requisição: model, state (obrigatório) e questions. Resposta: exatamente model, answers e usage. |
POST /v1/decisions |
Alias de /v1/systemone |
GET /v1/models |
Os modelos locais, como {"models": [{"name", "description", "release_date"}]} |
O /v1/* ignora campos nativos como keep_alive e extras, e nunca adiciona campos nativos às suas respostas. Os erros usam o mesmo corpo que /api/*, que o SDK TypeSafe lê corretamente. Consulte Compatibilidade com o TypeSafe.
Segurança
O servidor se liga a 127.0.0.1:11435 e, como o Ollama, confia nos chamadores locais. Vinculá-lo a outro endereço (OLLAYA_HOST=0.0.0.0) permite que todos que conseguem alcançar a porta executem decisões e baixem, excluam e criem modelos, então:
OLLAYA_API_KEYfaz toda requisição, excetoGET /,HEAD /e o preflight de CORS, exigirAuthorization: Bearer <key>; caso contrário, a resposta é401 UNAUTHORIZED. O SDK TypeSafe envia sua chave desse modo, e a CLIollayaenvia$OLLAYA_API_KEY. O servidor registra um aviso quando escuta além do loopback sem uma chave.- O TLS não é terminado pelo servidor; coloque um proxy reverso na frente para acesso remoto.
- Navegadores. Requisições com um cabeçalho
Originsão permitidas apenas delocalhost,127.0.0.1,0.0.0.0e[::1](qualquer porta), de webviews de aplicativos e editores, e das origens emOLLAYA_ORIGINS(separadas por vírgulas, curingas*). Um servidor em loopback também rejeita cabeçalhosHostinesperados, o que bloqueia DNS rebinding. - Seus dados. Os estados e as perguntas nunca são registrados nem repetidos nos erros.
| Variável | Padrão | Efeito |
|---|---|---|
OLLAYA_HOST |
127.0.0.1:11435 |
Endereço de bind; o destino do cliente. Um endereço de loopback também escuta em [::1], então programas do Windows alcançam um servidor no WSL em localhost sem atraso |
OLLAYA_API_KEY |
não definida | Exige Authorization: Bearer <key> |
OLLAYA_ORIGINS |
não definida | Origens de navegador permitidas adicionais |
OLLAYA_KEEP_ALIVE |
5m |
keep_alive padrão |
OLLAYA_MAX_LOADED_MODELS |
3 |
Limite de modelos carregados |
OLLAYA_MAX_QUEUE |
512 |
Requisições em andamento antes de 503 QUEUE_FULL |
OLLAYA_LOAD_TIMEOUT |
5m |
Prazo de carregamento antes de 500 MODEL_LOAD_FAILED |
OLLAYA_DEVICE |
auto |
auto, cpu, cuda ou cuda:<n> |
OLLAYA_MODELS |
~/.ollaya/models |
Armazenamento de modelos |
OLLAYA_REGISTRY |
ollaya.dev |
Host de registro padrão nos nomes |