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 gestão de modelos; - a API compatível com o TypeSafe em
/v1/*, idêntica ao nível do protocolo à do TypeSafe, para que os SDKs TypeSafe existentes funcionem sem alterações. Vê 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 a 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 em memória |
POST |
/api/pull |
Descarrega um modelo (transmite o progresso) |
DELETE |
/api/delete |
Elimina 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 pedido e resposta são objetos JSON. O corpo é analisado como JSON independentemente do
Content-Type, por issocurl -dfunciona tal como está. Os pedidos têm no máximo 8 MiB. - Os nomes dos campos usam
snake_case. Campos de pedido desconhecidos são ignorados;nullsignifica ausente. - Os nomes dos modelos são
[host/][namespace/]model[:tag], sem distinção de maiúsculas e minúsculas. Uma tag em falta significalatest. As respostas usam sempre a forma canónica, comolaya:latest. - Números. Probabilidades, confianças,
scoreenoulsão arredondados a 4 casas decimais. As durações são inteiros em nanossegundos; as marcas temporais são RFC 3339 em UTC. - Streaming.
/api/pulle/api/createtransmitem JSON delimitado por novas linhas, um objeto por linha, terminando com exatamente um{"status":"success"}ou uma linha de erro. Envia"stream": falsepara obteres uma única resposta. - IDs de pedido. Todas as respostas transportam
X-Request-Id, e as respostas de/v1/*tambémx-typesafe-request-id. UmX-Request-Idválido enviado pelo cliente é ecoado. - Concorrência. Um modelo carregado executa um pedido de cada vez, e cada pedido responde a todas as suas perguntas numa única passagem. Os pedidos para o mesmo modelo ficam em fila, por isso enviar mais de um de cada vez não termina mais cedo; o tempo de ida e volta de cada um passa então a incluir a espera. Faz todas as perguntas sobre um estado num único pedido. Modelos carregados diferentes são executados em paralelo.
- Nenhum download implícito. Nenhum endpoint descarrega um modelo como efeito secundário. O
ollaya rundescarrega 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 analises; a única mensagem congelada é model "<name>" not found, try pulling it first, como no Ollama. |
code |
Código legível por máquina. Ramifica 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 o pedido 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 router) não está nesta máquina; num download, não está no registo | 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á a escrever o mesmo nome de modelo | depois de terminar |
REQUEST_TOO_LARGE |
413 | Corpo acima de 8 MiB | não |
QUEUE_FULL |
503 | Já há OLLAYA_MAX_QUEUE pedidos à espera; enviado com Retry-After: 1 |
sim |
MODEL_LOAD_FAILED |
500 | O modelo não pôde ser carregado (ficheiros 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 do pedido | 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 | Registo 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: trata um código desconhecido pelo seu estado 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 de um stream começar, uma falha chega como última linha com o mesmo formato, por exemplo {"error": "…", "code": "DIGEST_MISMATCH"}. Verifica em cada linha se há error antes de a leres como progresso.
Perguntas
/api/decide, /v1/systemone e /api/create partilham um único esquema de perguntas, o do TypeSafe. Um pedido tem 1–256 perguntas, indexadas por qualquer id; as respostas voltam pela mesma ordem.
type |
instructions |
criteria |
Resposta |
|---|---|---|---|
choice |
opcional | obrigatório: objeto etiqueta → descrição, ou um array de etiquetas; 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, por isso um id descritivo comois_spamfunciona por si só.stateé uma string, um objeto ou um array, até 65.536 tokens. Se exceder o contexto disponível do modelo,/api/decidetrunca-o e reportastate_truncated: true./v1/systemonee/v1/decisionsdevolvem422 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 router, aplicam-se os limites do destino.
As respostas têm os formatos do TypeSafe, nesta ordem de campos:
type |
Campos |
|---|---|
choice |
choice: a etiqueta mais provável. confidence. probabilities: etiqueta → probabilidade, pela 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 se verificar. 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 tem toda a probabilidade. A fórmula é a mesma para todos os modelos, mas o que uma dada confiança significa não é: os modelos são calibrados de forma diferente, por isso ajusta um limiar por modelo nos teus próprios dados. As probabilidades são calibradas com as temperaturas de cada modelo. Numa GPU CUDA corre o grafo fp16, cujas respostas podem diferir do fp32 em empates apertados.
keep_alive
Durante quanto tempo um modelo permanece carregado depois de um pedido terminar, com a semântica do Ollama:
| Valor | Significado |
|---|---|
"5m", "1h30m", "300ms", 300, "300" |
Permanece carregado esse tempo após o pedido |
0, "0", "0s" |
Descarrega assim que o pedido termina |
-1, "-5m", qualquer valor negativo |
Permanece carregado até o servidor parar ou um descarregamento explícito |
em falta ou null |
OLLAYA_KEEP_ALIVE, predefinição 5m |
O cronómetro começa quando um pedido termina, e o valor do pedido mais recente prevalece. Para um router, aplica-se ao destino que respondeu. O /v1/* ignora keep_alive.
Decidir
POST /api/decide
Responde a perguntas tipadas sobre um estado numa única passagem direta. O corpo é o corpo de /v1/systemone mais opções nativas; a resposta é a resposta do TypeSafe mais campos nativos, por isso um cliente TypeSafe também a consegue analisar.
| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
model |
string | sim | Nome do modelo |
state |
string, objeto ou array | sim para decidir | Sem ele, o pedido carrega ou descarrega o modelo (abaixo) |
questions |
objeto | sim, a menos que o modelo tenha perguntas incorporadas | Substitui por completo as perguntas do próprio modelo |
preset |
string | não | O nome de uma predefinição, incorporada 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. Vê Imagens |
keep_alive |
string ou number | não | Vê 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 router, o seu destino (laya:en para um pedido de laya) |
answers |
Id de pergunta → resposta, pela ordem das perguntas |
usage |
input_tokens lidos; output_tokens é sempre 0 |
routing |
Para um router: 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 a receção do pedido até à resposta, incluindo a fila |
load_duration |
Nanossegundos gastos à espera que o modelo carregue; 0 quando já estava quente |
eval_duration |
Nanossegundos no runner: tokenização, passagem direta, calibração |
Com "extras": ["laya"], cada resposta tem também 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 a perguntas sobre uma imagem, além do estado. Envia a imagem em images, codificada em base64, tal como 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 pedido, apenas PNG. O pré-processamento do modelo é reproduzido valor a valor, por isso os píxeis têm de corresponder ao que os autores do modelo descodificam. Os descodificadores de JPEG do Rust diferem do libjpeg-turbo até 4 níveis em alguns píxeis, por isso o JPEG ainda não é aceite: converte-o primeiro para PNG.
- Decider: A imagem é redimensionada para múltiplos de 32 píxeis, como o modelo espera, e pode ter no máximo 4.096 patches de 16x16 píxeis depois disso, cerca de um megapíxel (1024x1024). Uma imagem maior recebe um 422 que o indica; reduz-a primeiro.
- Decider: As perguntas aceitam no máximo 10 opções. O mesmo modelo também responde a pedidos só de texto.
- Winnow E4B vision: até 16 PNG 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 etiquetas de texto existentes do Winnow não o carregam.
- Um modelo que não lê imagens responde a um pedido 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. Um pedido sem state e questions nunca decide. Sem keep_alive, ou com um valor positivo ou negativo, carrega o modelo (todos os destinos, no caso de um router) e devolve done_reason: "load". Com keep_alive: 0 descarrega-o ("unload"). O ollaya run pré-carrega deste 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 secundário sobre dados armazenados, por isso é seguro tentar de novo.
Predefinições
Uma predefinição é um conjunto nomeado de perguntas. Seis são incorporadas (triage, email, guard, moderation, router, agent), e podes guardar as tuas próprias. Envia "preset": "NAME" para /api/decide em vez 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 incorporadas, depois as personalizadas: name, builtin, description, ids de pergunta, modified_at |
POST /api/presets/create |
name, questions, description (opcional) |
Guarda 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 |
Elimina uma predefinição personalizada |
Os nomes têm de 1 a 64 caracteres de letras minúsculas, dígitos, - e _. Um nome incorporado não pode ser reutilizado (422) nem eliminado (403), e um nome desconhecido é um 404. As predefinições personalizadas são guardadas junto dos modelos, por isso todos os clientes do servidor veem as mesmas.
Routers
Um router como laya (laya:latest) não tem pesos: para cada pedido escolhe um dos seus destinos, que depois 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 (a predefinição) |
laya:en |
Textos curtos em maiúsculas e sem letras acentuadas, como nomes de comerciantes num extrato de cartão (MIGROS KADIKOY ISTANBUL TR), SKUs ou nomes de utilizador, normalmente não podem ser identificados e vão para laya:en. Se sabes o idioma, pede laya:multilingual ou laya:en diretamente; o model da resposta diz qual checkpoint respondeu.
O encaminhamento custa microssegundos. Ramifica com base em route, nunca em reason, cujo texto pode mudar. O laya:typed-decisions nunca é escolhido pelo router; pede-o diretamente.
Listar modelos locais
GET /api/tags
Os modelos nesta máquina, do mais recente para o mais antigo. Cada entrada tem name, model (o mesmo), modified_at, size em bytes, digest (sha256 do manifesto, em hex simples) e details: parent_model, format (onnx, gguf ou router), family, families, parameter_size e quantization_level (as precisões que transporta, 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 incorporadas, ou null |
router |
Para um router: 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 multilingue ainda pode ler outros idiomas, por isso mede nos teus dados. |
capabilities |
Tipos de pergunta a que responde (choice, score, noul), mais act se tiver uma cabeça de ato |
modified_at |
Como em /api/tags |
Um router é 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 routers nunca aparecem; os 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 será descarregado, ou null quando mantido carregado), size_vram, context_length e device (cpu, cuda:0, metal, …).
Descarregar um modelo
POST /api/pull
{"model": "laya:en"}
Descarrega o modelo para o armazenamento local e verifica cada blob em relação ao seu sha256. Descarregar um router descarrega também todos os modelos para os quais ele encaminha. Só são descarregadas as camadas de que esta máquina precisa, os blobs partilhados entre modelos são descarregados uma vez, e os downloads interrompidos são retomados.
A resposta transmite o progresso, com as cadeias de estado 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 router há um único success, mesmo no fim. Um nome que não é analisado, um modelo que não está no registo e um registo inacessível são erros HTTP comuns (422, 404, 502) antes de o stream começar, por isso curl --fail funciona. Com "stream": false a resposta é {"status": "success"} quando termina. Um segundo download do mesmo nome junta-se ao que está em curso. Seguro tentar de novo.
Eliminar um modelo
DELETE /api/delete
{"model": "triage"}
Elimina o nome, e os blobs que nenhum outro modelo usa. Um modelo carregado é descarregado assim que os seus pedidos terminam; eliminar um router mantém os seus destinos. A resposta é 200 com corpo vazio, e 404 MODEL_NOT_FOUND quando o nome não existe; após um timeout, trata isso como sucesso.
Copiar um modelo
POST /api/copy
{"source": "laya:en", "destination": "my-guardrail"}
Copia um modelo para um novo nome, substituindo 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 ficheiros que nomeia e envia os seus conteúdos como JSON.
| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
model |
string | sim | Nome a criar |
from |
string | sim | Um modelo local, possivelmente um router. Nunca é descarregado. |
questions |
objeto | não | Perguntas incorporadas, validadas como um pedido 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 | Predefiniçã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, por isso 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 |
Pedido: 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. Vê Compatibilidade com o TypeSafe.
Segurança
O servidor liga-se a 127.0.0.1:11435 e, tal como o Ollama, confia nos chamadores locais. Ligá-lo a outro endereço (OLLAYA_HOST=0.0.0.0) deixa que todos os que conseguem alcançar a porta executem decisões e descarreguem, eliminem e criem modelos, por isso:
OLLAYA_API_KEYfaz com que todos os pedidos, excetoGET /,HEAD /e o preflight de CORS, exijamAuthorization: Bearer <key>; caso contrário, a resposta é401 UNAUTHORIZED. O SDK TypeSafe envia a sua chave deste modo, e a CLIollayaenvia$OLLAYA_API_KEY. O servidor regista um aviso quando escuta para além do loopback sem uma chave.- O TLS não é terminado pelo servidor; coloca um proxy reverso à frente para acesso remoto.
- Navegadores. Pedidos com um cabeçalho
Originsão permitidos apenas delocalhost,127.0.0.1,0.0.0.0e[::1](qualquer porta), de webviews de aplicações e editores, e das origens emOLLAYA_ORIGINS(separadas por vírgulas, wildcards*). Um servidor em loopback também rejeita cabeçalhosHostinesperados, o que bloqueia DNS rebinding. - Os teus dados. Os estados e as perguntas nunca são registados nem ecoados 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], por isso 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 extra |
OLLAYA_KEEP_ALIVE |
5m |
keep_alive predefinido |
OLLAYA_MAX_LOADED_MODELS |
3 |
Limite de modelos carregados |
OLLAYA_MAX_QUEUE |
512 |
Pedidos em curso 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 registo predefinido nos nomes |