Skip to content

Modelos de Decisão ​

Modelos de decisão respondem perguntas estruturadas sobre um estado. Em vez de gerar texto livre, eles retornam uma resposta por pergunta nomeada: um julgamento binário, um rótulo selecionado ou uma pontuação em uma rubrica. A plataforma os serve com a mesma autenticação por Chave API e a mesma cobrança em créditos dos demais tipos de modelo.

O primeiro modelo desse tipo é o Jev (jev-1.13.0), servido pela TypeSafe. Você pode fazer várias perguntas ao mesmo tempo sobre o mesmo estado, e a resposta preserva o tipo de cada pergunta: noul, choice ou score.

Modelos de decisão são um tipo separado da Geração de Texto. Eles não aceitam mensagens de chat, parâmetros de geração nem definições de ferramentas, e não aparecem nos seletores de agente, thread, fala ou embedding.

Para a lista atual de modelos de decisão e seus preços, consulte a página de Preços e o seletor de modelos na plataforma.

Playground Interativo ​

O Playground de Decisões permite escrever um estado, definir perguntas e inspecionar cada resposta com sua distribuição e confiança.

Estado ​

O estado é o texto ou JSON sobre o qual o modelo raciocina. Cole uma mensagem de suporte, um trecho de documento ou um objeto JSON. O estado pode ser uma string, um objeto JSON, um array JSON ou null.

Perguntas ​

Adicione uma ou mais perguntas nomeadas. Cada pergunta tem um editor conforme seu tipo:

TipoO que você forneceO que retorna
noulUma pergunta de instrução, mais descrições opcionais para os resultados sim e nãoA probabilidade de uma resposta sim
choiceUma pergunta de instrução e um mapa de rótulos para descriçõesO rótulo selecionado e a probabilidade de cada rótulo
scoreUma pergunta de instrução e uma rubrica ordenada com pelo menos dois níveisA pontuação esperada, a rubrica (legenda) e a probabilidade de cada nível

Os nomes das perguntas são seus. Use o mesmo nome no editor e na resposta para correlacioná-los.

Execução e Visualização ​

Execute a requisição para ver um cartão por pergunta:

  • A resposta selecionada, destacada na distribuição.
  • A distribuição completa em barras ou gráfico, não só a opção vencedora.
  • A confiança reportada para respostas choice e score.
  • O uso de tokens e o ID da requisição.

O Playground não simula uma conversa. É uma única requisição sobre um único estado.

TIP

Todas as perguntas rodam na mesma requisição. Perguntar ao mesmo tempo se é seguro, a categoria e a urgência mede uma entrada só, não três chamadas separadas.

Tipos de Pergunta ​

Uma requisição carrega um estado e um objeto não vazio de perguntas nomeadas. Cada pergunta declara seu type.

Perguntas binárias (noul) ​

Uma pergunta noul pede um julgamento sim/não e retorna a probabilidade de sim.

json
{
  "state": "I was charged twice for the same subscription. Please fix it.",
  "questions": {
    "billing_related": {
      "type": "noul",
      "instructions": "Is this request about billing?",
      "criteria": {
        "true": "A billing or payment issue",
        "false": "Anything else"
      }
    }
  }
}

Os critérios são opcionais e descrevem o que significam sim e não. Eles não são traduzidos nem reescritos pela plataforma: envie-os no idioma que você quer que o modelo use.

Perguntas de escolha (choice) ​

Uma pergunta choice seleciona um rótulo do mapa de critérios e retorna a probabilidade de cada rótulo.

json
{
  "state": "I was charged twice for the same subscription. Please fix it.",
  "questions": {
    "category": {
      "type": "choice",
      "instructions": "Pick the support category.",
      "criteria": {
        "billing": "Payment, invoices and charges",
        "technical": "Errors, bugs and outages",
        "account": "Login, profile and access"
      }
    }
  }
}

As chaves dos critérios são os rótulos. Elas são seus dados e retornam inalteradas em choice e em probabilities.

Perguntas de pontuação (score) ​

Uma pergunta score atribui uma pontuação em uma rubrica ordenada. A rubrica é um array com pelo menos duas descrições, indexadas a partir de zero. O score retornado é o valor esperado e pode cair entre níveis inteiros.

json
{
  "state": "I need this resolved before tomorrow morning or my account is suspended.",
  "questions": {
    "urgency": {
      "type": "score",
      "instructions": "How urgent is this request?",
      "criteria": ["Low", "Medium", "High"]
    }
  }
}

A resposta repete a rubrica como legend, com chaves de pontuação como strings numéricas. Use a legenda para rotular a distribuição na sua interface.

Resposta ​

As respostas são indexadas pelo nome da pergunta enviada. Cada resposta mantém seu tipo.

json
{
  "model": "jev-1.13.0",
  "answers": {
    "billing_related": {
      "type": "noul",
      "noul": 0.98
    },
    "category": {
      "type": "choice",
      "choice": "billing",
      "confidence": 0.91,
      "probabilities": {
        "billing": 0.91,
        "technical": 0.05,
        "account": 0.04
      }
    },
    "urgency": {
      "type": "score",
      "score": 0.78,
      "confidence": 0.58,
      "legend": { "0": "Low", "1": "Medium", "2": "High" },
      "probabilities": { "0": 0.25, "1": 0.72, "2": 0.03 }
    }
  },
  "usage": {
    "input_tokens": 367,
    "output_tokens": 62
  }
}
CampoDescrição
modelO modelo que respondeu à requisição
answersUma entrada para cada nome de pergunta enviado
answers[].typenoul, choice ou score, conforme a pergunta
answers[].noulProbabilidade de sim para uma pergunta noul, de 0 a 1
answers[].choiceRótulo selecionado para uma pergunta choice
answers[].scorePontuação esperada para uma pergunta score
answers[].confidenceConfiança reportada para respostas choice e score
answers[].probabilitiesProbabilidade por rótulo ou por nível de pontuação
answers[].legendDescrições da rubrica com chaves de pontuação, para respostas score
usage.input_tokensTokens de entrada medidos pelo provedor
usage.output_tokensTokens de saída reportados pelo provedor (não cobrados, veja abaixo)

Confiança e Probabilidades ​

Leia a distribuição, não apenas a resposta vencedora.

  • noul retorna uma única probabilidade. noul: 0.5 significa que os dois resultados são igualmente plausíveis, não um sim fraco.
  • Em choice, probabilities soma 1 entre os rótulos. Uma confidence de 0,55 com o segundo rótulo em 0,30 é uma decisão bem mais fraca que uma 0,95 com o segundo em 0,02.
  • Em score, score é o valor esperado e probabilities descreve a distribuição dos níveis. Uma média alta com probabilidade espalhada por dois níveis distantes não é o mesmo que uma resposta concentrada.
  • Confiança alta não é prova de acerto. Calibre um limiar com os seus próprios dados antes de agir automaticamente sobre uma resposta.

A plataforma nunca inventa uma distribuição nem um valor de confiança. Se um provedor não consegue reportá-los para um tipo de pergunta, esse tipo não é oferecido.

API REST ​

As requisições de decisão vão para a rota canônica POST /v1/decisions. O mesmo serviço de execução atende os aliases de compatibilidade usados pelos clientes existentes.

BaseRota de execuçãoListagem de modelos
https://api.sippulse.ai/v1POST /decisionsGET /models
https://api.sippulse.aiPOST /v1/systemoneGET /v1/models
https://api.sippulse.ai/apiPOST /api/v1/systemone, POST /api/alpha/decisionsGET /api/v1/models

Todas as rotas de execução aceitam o mesmo corpo e retornam o mesmo formato de resposta. Use a rota canônica em integrações novas.

Autenticação ​

Envie sua Chave API da SipPulse no cabeçalho api-key, ou como Authorization: Bearer <chave> quando seu cliente espera um token bearer.

Exemplo de requisição ​

bash
curl -X POST 'https://api.sippulse.ai/v1/decisions' \
  -H 'Content-Type: application/json' \
  -H 'api-key: $SIPPULSE_API_KEY' \
  -d '{
    "model": "jev-1.13.0",
    "state": "I was charged twice for the same subscription. Please fix it.",
    "questions": {
      "billing_related": {
        "type": "noul",
        "instructions": "Is this request about billing?",
        "criteria": { "true": "A billing or payment issue", "false": "Anything else" }
      },
      "urgency": {
        "type": "score",
        "instructions": "How urgent is this request?",
        "criteria": ["Low", "Medium", "High"]
      }
    }
  }'
python
import os
import requests

response = requests.post(
    "https://api.sippulse.ai/v1/decisions",
    headers={
        "Content-Type": "application/json",
        "api-key": os.environ["SIPPULSE_API_KEY"],
    },
    json={
        "model": "jev-1.13.0",
        "state": "I was charged twice for the same subscription. Please fix it.",
        "questions": {
            "billing_related": {
                "type": "noul",
                "instructions": "Is this request about billing?",
                "criteria": {"true": "A billing or payment issue", "false": "Anything else"},
            },
            "urgency": {
                "type": "score",
                "instructions": "How urgent is this request?",
                "criteria": ["Low", "Medium", "High"],
            },
        },
    },
)
response.raise_for_status()
print(response.json()["answers"])
javascript
const response = await fetch("https://api.sippulse.ai/v1/decisions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "api-key": process.env.SIPPULSE_API_KEY,
  },
  body: JSON.stringify({
    model: "jev-1.13.0",
    state: "I was charged twice for the same subscription. Please fix it.",
    questions: {
      billing_related: {
        type: "noul",
        instructions: "Is this request about billing?",
        criteria: { true: "A billing or payment issue", false: "Anything else" },
      },
      urgency: {
        type: "score",
        instructions: "How urgent is this request?",
        criteria: ["Low", "Medium", "High"],
      },
    },
  }),
});

if (!response.ok) {
  throw new Error(`Erro na API de Decisões: ${response.status}`);
}

const { answers, usage } = await response.json();
console.log(answers.billing_related.noul, usage.input_tokens);

Listagem de modelos ​

A rota de listagem segue o seu SDK. O SDK TypeSafe espera um array models; o cliente no estilo OpenRouter espera um array data. Os dois são servidos pelo mesmo modelo, no formato que cada cliente consegue interpretar.

bash
curl 'https://api.sippulse.ai/v1/models' \
  -H 'api-key: $SIPPULSE_API_KEY'
json
{
  "models": [
    {
      "name": "jev-1.13.0",
      "description": "Decision model",
      "release_date": "2026-09-20"
    }
  ]
}
bash
curl 'https://api.sippulse.ai/api/v1/models' \
  -H 'api-key: $SIPPULSE_API_KEY'
json
{
  "data": [
    {
      "id": "jev-1.13.0",
      "name": "jev-1.13.0"
    }
  ]
}

SDKs Compatíveis ​

O protocolo de decisão é compatível com as convenções dos clientes TypeSafe e OpenRouter. O que muda entre eles é apenas como a URL base e as credenciais são configuradas.

SDK TypeSafe ​

Aponte o cliente para o host da SipPulse e use sua Chave API da SipPulse. O SDK envia Authorization: Bearer, que a plataforma aceita. client.systemOne(...) e client.models.list() funcionam sem alteração.

javascript
import { TypeSafeClient, noul, score } from "@typesafe-ai/sdk";

const client = new TypeSafeClient({
  apiKey: process.env.SIPPULSE_API_KEY,
  baseURL: "https://api.sippulse.ai",
});

const { answers, usage } = await client.systemOne({
  state: "I was charged twice for the same subscription. Please fix it.",
  questions: {
    billing_related: noul("Is this request about billing?", {
      true: "A billing or payment issue",
      false: "Anything else",
    }),
    urgency: score("How urgent is this request?", ["Low", "Medium", "High"]),
  },
});

console.log(answers.billing_related.noul, usage.input_tokens);
python
import os
from typesafe_sdk import Noul, Score, TypeSafeClient

with TypeSafeClient(
    api_key=os.environ["SIPPULSE_API_KEY"],
    base_url="https://api.sippulse.ai",
) as client:
    result = client.system_one(
        state="I was charged twice for the same subscription. Please fix it.",
        questions={
            "billing_related": Noul(instructions="Is this request about billing?"),
            "urgency": Score(
                instructions="How urgent is this request?",
                criteria=["Low", "Medium", "High"],
            ),
        },
    )
    print(result.nouls["billing_related"].noul, result.usage.input_tokens)

Cliente OpenRouter ​

O cliente OpenRouter não aceita serverURL no construtor para a operação de decisões. A chamada alphaDecisionsCreate calcula a URL base a partir de uma opção por chamada serverURL e, sem ela, usa o padrão do OpenRouter. Passe o host da SipPulse por chamada; não existe alias de gateway que contorne essa limitação.

javascript
import { OpenRouter } from "@openrouter/sdk";

const openrouter = new OpenRouter({
  apiKey: process.env.SIPPULSE_API_KEY,
});

const result = await openrouter.alpha.decisions.create(
  {
    model: "jev-1.13.0",
    state: "I was charged twice for the same subscription. Please fix it.",
    questions: {
      billing_related: {
        type: "noul",
        instructions: "Is this request about billing?",
      },
    },
  },
  { serverURL: "https://api.sippulse.ai" },
);

Opções de roteamento do provedor não são suportadas

A plataforma responde às perguntas e preserva o contrato de resposta, mas não implementa o roteamento comercial do OpenRouter: políticas de privacidade, retenção de dados, ordem de provedores, fallbacks e seleção de provedor não são honrados. Uma requisição que peça essas preferências é rejeitada em vez de ignorá-las em silêncio, então uma opção que aparece no schema do OpenRouter não é necessariamente suportada aqui.

Vercel AI SDK ​

O provider do AI SDK deriva o caminho /api/alpha de uma URL base que termina em /api/v1. Configure a URL base do provider de acordo; nenhum override por chamada é necessário.

Uso e Faturamento ​

Requisições de decisão são cobradas por tokens de entrada apenas, a custo, conforme a política de preço do modelo. A tarifa atual do Jev é US$ 0,042 por milhão de tokens de entrada, e a mesma tarifa vale para todo plano que oferece o modelo. Os tokens de saída reportados pelo provedor são mantidos como metadados de uso e não são cobrados.

É por isso que a resposta sempre traz os dois contadores:

  • usage.input_tokens é o que é cobrado.
  • usage.output_tokens é reportado para observabilidade e conciliação, e seu custo já está embutido na tarifa de entrada.

Os preços são definidos em USD. A moeda da sua organização aplica o câmbio atual e os impostos aplicáveis quando a plataforma converte o valor, então o valor em moeda local não é um múltiplo fixo do número em USD.

Onde o uso aparece ​

No Dashboard, uma chamada de decisão gera um item de uso do tipo Decisões com a regra de cobrança Input Token, o identificador canônico do modelo, a quantidade de entrada cobrada e o custo daquela chamada. A tabela de requisições e os detalhes da requisição mostram o mesmo ID da requisição, projeto, solicitante e total.

A contagem de tokens de saída não é uma linha faturável separada. Ao conciliar totais, some os itens de decisão pela quantidade de entrada; não espere um item de saída correspondente.

Valores zero e muito pequenos

Uma chamada de decisão pode ser barata o suficiente para que o valor cobrado seja arredondado para um valor muito pequeno. O relatório de uso mantém a precisão decimal de cada chamada, enquanto o crédito liquida o valor efetivamente debitado. Como a liquidação é por chamada, um número muito grande de chamadas quase zero não tem garantia de somar exatamente ao custo bruto em tokens.

Limites ​

O modelo declara seus limites de decisão. Os limites cobrem o contexto composto, não só o estado:

LimiteDescrição
Contexto totalMáximo de tokens para o estado mais todas as perguntas, incluindo instruções e critérios
Maior perguntaMáximo de tokens para o estado mais a maior pergunta
Opções de escolhaNúmero máximo de rótulos no mapa de critérios de uma pergunta choice
Faixa de pontuaçãoNúmero mínimo e máximo de níveis de rubrica em um array de critérios score

O gateway valida a forma da requisição e a cardinalidade de opções e rubrica antes de rodar a inferência. Uma requisição inválida falha com 400 e não é cobrada. Uma requisição maior que 2 MiB (UTF-8 serializado) é rejeitada antes da inferência com 413; aninhamento acima de 64 níveis é rejeitado com 400. Não há um teto separado para a quantidade de perguntas. Os dois tetos de tokens são enforçados pelo próprio modelo, então uma requisição grande demais é rejeitada lá, e não recontada pela plataforma.

Limites de taxa são aplicados por organização e compartilhados entre todos os aliases do mesmo modelo. latest e nomes de versão fixa não têm contadores nem preços separados.

Erros ​

CódigoSignificado
400Requisição malformada ou parâmetros inválidos, incluindo forma de pergunta inválida e preferências de provedor não suportadas
401Chave API da SipPulse inválida ou ausente
402Créditos insuficientes
404Modelo inexistente ou indisponível para a sua organização
413Corpo da requisição grande demais
429Limite de taxa excedido; respeite o cabeçalho Retry-After
500Erro interno do servidor
502 / 503Erro do provedor upstream ou indisponibilidade temporária
504Tempo esgotado

As rotas de decisão retornam erros no formato que o SDK OpenRouter consegue validar: code é o status HTTP numérico e platform_code é a string estável do erro da plataforma. Ramifique por platform_code no código; o code numérico espelha o status da resposta.

json
{
  "error": {
    "statusCode": 404,
    "name": "NotFoundError",
    "message": "The model 'jev-does-not-exist' does not exist or is not available for your organization.",
    "code": 404,
    "platform_code": "model_not_found"
  }
}

Uma chave SipPulse inválida retorna 401. Um problema com a credencial do provedor upstream não retorna 401: ele é reportado como erro de provedor (5xx), para que um cliente não encerre uma sessão válida por causa de um problema a montante.

javascript
const response = await fetch("https://api.sippulse.ai/v1/decisions", {
  method: "POST",
  headers: { "Content-Type": "application/json", "api-key": key },
  body: JSON.stringify(payload),
});

if (!response.ok) {
  const { error } = await response.json();
  if (error.platform_code === "model_not_found") {
    // Trate o erro estável da plataforma.
  }
  throw new Error(`${error.code}: ${error.platform_code ?? error.message}`);
}
python
resp = requests.post(url, headers=headers, json=payload)
if resp.status_code >= 400:
    error = resp.json()["error"]
    if error.get("platform_code") == "model_not_found":
        pass  # Trate o erro estável da plataforma.
    raise RuntimeError(f"{error['code']}: {error.get('platform_code', error['message'])}")

Identidade do Modelo e Aliases ​

O identificador canônico do modelo é jev-1.13.0. A plataforma também aceita uma lista curta de aliases documentados, incluindo jev-latest (o padrão do SDK TypeSafe), jev-1.13 e typesafe/jev-1.13. Os aliases são explícitos; prefixos arbitrários e nomes aproximados não são resolvidos.

Um nome de versão fixa nunca redireciona em silêncio para outro modelo. latest só muda quando o catálogo é publicado, com invalidação de cache. A resposta sempre informa a versão que de fato respondeu, então registre as answers junto com o campo model.

Próximos Passos ​