Como desenhar o schema de saída de uma decisão do Jev?

O schema de saída do Jev é a própria decisão: você define antecipadamente as opções e a estrutura, e a correspondência de schema é garantida, então a resposta não inventa campo nem devolve tipo errado. Modelar bem significa quebrar a decisão em fatores independentes, escolher a primitiva certa em cada campo (Noul para sim/não, Choice para um entre N, Score para nível em escala), nomear opções pelo significado e escrever rubricas com fronteira clara. Depois o código combina os sinais, lê probabilities e confidence e decide o que faz sozinho e o que vai pra revisão humana.
No Jev, o schema não é enfeite em volta da resposta, ele é a decisão
Se você ainda não brincou com o bicho: o Jev é o primeiro System One Model da TypeSafe AI, apresentado por Diogo Almeida, ex-pesquisador da OpenAI. Ele recebe um estado (texto ou JSON) e responde perguntas tipadas devolvendo valores estruturados com probabilidades, em vez de gerar texto
E aqui está o pulo do gato: quem define as opções e a estrutura da saída é você, antes da chamada. A correspondência de schema é garantida por construção, ou seja, a resposta não pode inventar um campo nem retornar o tipo de dado errado
Traduzindo: a qualidade e a usabilidade da resposta são decididas no momento em que você desenha o schema, não depois
Bora modelar isso direito? 🙂
O que você precisa saber antes de modelar o schema
Antes de sair escrevendo JSON, tenha o mapa na cabeça. A API do Jev define três tipos de pergunta, chamados de primitivas, e cada uma devolve uma coisa diferente
| Primitiva | Pergunta que ela responde | O que volta na resposta | Limites |
|---|---|---|---|
| Noul | Sim ou não | Um único número, noul, que é a probabilidade da resposta ser sim |
Sem campo confidence separado |
| Choice | Um entre N | choice, probabilities (cada opção mapeada pra sua probabilidade, somando 1) e confidence |
Até 255 opções |
| Score | Nível em escala ordenada | score, uma probabilidade por nível e confidence |
De 2 a 10 níveis |
Repare no Noul: ele não tem confidence porque a própria probabilidade já descreve a incerteza. Faz sentido, né? Um 0,51 num sim/não já grita "eu não faço ideia"
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 45min
Como a requisição é montada: o corpo carrega state, model e um mapa de questions, onde cada chave é o ID da pergunta e o valor é a definição dela. Na volta, cada resposta preserva o ID da pergunta e corresponde ao tipo daquela pergunta
Modelo e orçamento: o modelo atual documentado é o jev-1.13.0, com contexto de requisição de 64k e orçamento de 32k para o state mais a pergunta mais longa, entrada somente texto. Os aliases jev-latest (release estável e padrão do SDK) e jev-preview apontam pro modelo atual
Preço: US$ 0,042 por milhão de tokens de entrada, com tokens de saída gratuitos. Como a saída não custa, empilhar muitas perguntas na mesma requisição é barato do ponto de vista de output, o peso fica no state e no texto das perguntas
Guarde esse número do 32k, ele volta lá embaixo na seção de erros 😛
Passo a passo para desenhar o schema de uma decisão
1. Escreva a decisão em UMA frase
Antes de qualquer campo, escreve em português o que o software precisa decidir
"Este ticket vai pro time de billing ou pro de suporte técnico?"
"Este texto viola a política de spam?"
Se a sua frase tem um "e" no meio, ou se ela precisa de um parágrafo pra ser explicada, ela não é uma pergunta só
O erro comum deste passo: achar que "avalie este pitch de startup" é uma pergunta. Não é. É uma pilha de perguntas disfarçada
2. Decomponha em fatores independentes
A documentação é bem direta nisso: se a decisão exigiria raciocínio extenso ou pesa vários fatores independentes, pergunte cada fator separadamente e combine os resultados com lógica no seu código
O exemplo que a própria doc usa é exatamente o do pitch: em vez de "avalie este pitch de startup", pergunte separadamente sobre tamanho de mercado, viabilidade técnica e diferenciação, e depois combine os scores com uma fórmula sua
Isso muda o papel de cada lado: o modelo vira o sensor, o seu código vira o juiz
O erro comum deste passo: delegar a fórmula pro modelo. A ponderação entre fatores é regra de negócio, e regra de negócio tu quer no repositório, versionada, não escondida dentro de uma rubrica
3. Escolha a primitiva campo por campo
Com os fatores na mão, cada um vira uma pergunta com um tipo
- É sim ou não? Noul
- É um entre N rótulos que não se sobrepõem? Choice
- É um nível numa escala que tem ordem real (baixo, médio, alto)? Score
Se você está em dúvida entre Choice e Score, pergunta: as opções têm uma ordem natural? Se "reembolso" não é maior nem menor que "cancelamento", é Choice
O erro comum deste passo: usar Score pra coisa que não é escala, só porque parece mais informativo
4. Nomeie as opções sem ambiguidade
A doc orienta usar os mesmos nomes de campo entre as opções, pro modelo comparar diretamente, e descrever o que pertence a cada opção, o que pertence à opção vizinha e alguns exemplos representativos
Traduzindo pra prática: nome de opção precisa dizer o que a opção significa, e as descrições precisam ter o mesmo formato entre si
Se a opção A fala de "tipo de cliente" e a opção B fala de "quando usar", o modelo está comparando maçã com bicicleta
O erro comum deste passo: nomes vazios tipo opcao_a, tipo_1, outro. O modelo só tem aquele rótulo e a rubrica pra trabalhar, nome genérico é informação jogada fora
5. Escreva os criteria no formato certo de cada primitiva
Aqui o formato muda conforme o tipo, e vale decorar:
- Choice:
criteriaé um mapa de opção para descrição (a rubrica), e aceitanullquando aquela opção não precisa de detalhe extra - Score:
criteriaé um array ordenado de descrições de nível, da ponta baixa para a ponta alta da escala - Noul: é definido pelas
instructions(a pergunta sim/não a avaliar) e pode opcionalmente recebercriteriacom descrições paratrueefalse, quando a fronteira entre sim e não é sutil
Um esqueleto ilustrativo de questions, só pra você sentir a forma (os nomes exatos dos campos estão na doc das primitivas):
{
"state": "Assunto: cobrança duplicada no cartão...",
"model": "jev-latest",
"questions": {
"categoria_ticket": {
"type": "choice",
"instructions": "Para qual fila este ticket deve ser roteado?",
"criteria": {
"cobranca": "Problemas de fatura, cobrança duplicada, estorno e reembolso. Não inclui falha de login no portal de faturas, isso é acesso_conta",
"acesso_conta": "Login, senha, 2FA e permissão de usuário. Não inclui valores cobrados, isso é cobranca",
"bug_produto": "Comportamento errado do produto reproduzível pelo usuário",
"duvida_uso": null
}
},
"precisa_resposta_hoje": {
"type": "noul",
"instructions": "O cliente precisa de resposta ainda hoje?",
"criteria": {
"true": "Serviço parado, cobrança em curso ou prazo legal citado no texto",
"false": "Pedido de informação sem impacto imediato no uso"
}
},
"severidade": {
"type": "score",
"instructions": "Qual a severidade do impacto relatado?",
"criteria": [
"Incômodo cosmético, cliente segue trabalhando",
"Funcionalidade secundária afetada, existe contorno",
"Funcionalidade principal afetada, sem contorno",
"Operação parada ou dinheiro saindo errado"
]
}
}
}
O erro comum deste passo: rubrica que só diz o que a opção É e nunca diz o que ela NÃO é. A fronteira é a parte que resolve os casos difíceis
6. Use objetos e arrays quando a orientação tem vários tipos
Quando as instruções ou os critérios precisam carregar vários tipos de orientação, a doc recomenda usar objetos ou arrays com campos nomeados, em vez de achatar tudo numa string densa de prosa
Ou seja: definição num campo, fronteira em outro, exemplos num array. Cada coisa no seu lugar, que é justamente o que evita o modelo misturar tudo
O erro comum deste passo: o parágrafão. Aquela rubrica de oito linhas onde definição, exceção e exemplo estão todos grudados
7. Defina IDs de pergunta estáveis
A resposta vem indexada pelo ID da pergunta, com o type correspondente. Então o ID não é decoração, é a chave que o seu código vai usar pra sempre
Escolhe nomes que descrevem o fator (severidade, categoria_ticket) e trata mudança de ID como mudança de contrato
O erro comum deste passo: ID descartável tipo q1, q2. No dia que alguém reordenar as perguntas, seu if vai ler o campo errado e ninguém vai perceber
8. Agrupe muitas perguntas estreitas na mesma requisição
A recomendação da doc é fazer muitas perguntas estreitas e independentes sobre o mesmo estado numa única requisição, porque elas rodam em paralelo e o seu código combina os sinais
Não existe limite fixo de quantidade de perguntas: o limite é o orçamento de tokens da requisição, compartilhado entre o state e as perguntas
O erro comum deste passo: mandar uma requisição por fator, repetindo o mesmo state gigante em todas. Você paga o state de novo a cada chamada, e o state é justamente a parte cara (entrada é o que é cobrado, US$ 0,042 por milhão de tokens)
Como fazer o schema devolver algo que o código consiga usar
Schema bom não é o que responde bonito, é o que o if do outro lado consegue consumir sem chutar
A resposta de um Choice traz choice (a opção de maior probabilidade), probabilities (cada opção mapeada pra sua probabilidade, somando 1) e confidence (número de 0 a 1 calculado a partir da dispersão das probabilidades). O Score traz score, probabilidade por nível e confidence
Forma ilustrativa do answers:
{
"answers": {
"categoria_ticket": {
"type": "choice",
"choice": "cobranca",
"probabilities": {
"cobranca": 0.71,
"acesso_conta": 0.18,
"bug_produto": 0.08,
"duvida_uso": 0.03
},
"confidence": 0.62
},
"precisa_resposta_hoje": {
"type": "noul",
"noul": 0.88
}
}
}
Agora o que fazer com isso:
- Leia
probabilitieseconfidence, não só o vencedor. Oconfidencecolapsa a distribuição num único número de 0 a 1 justamente pro seu código aplicar um limiar sem refazer a conta na mão - Aplique as três faixas de confiança. A doc sugere alta (segue sem humano), média (pede confirmação, marca pra revisão ou coleta mais informação) e baixa (não age, roteia pra humano ou cai em outro sistema). Isso é o padrão de confidence-gated routing
- Aceite que a aplicação não precisa agir sobre a opção vencedora. Um exemplo da própria doc retorna
uncertainquando a probabilidade do topo fica abaixo de 0,60 e manda o caso pra um humano - Lembre que o Noul não tem
confidence. Ali o limiar você aplica direto na probabilidade: 0,88 é uma coisa, 0,52 é outra bem diferente
O erro comum aqui é o schema que só expõe o vencedor pro resto do sistema. Você joga fora o sinal de incerteza e transforma um modelo calibrado (o Jev foi treinado com RLCD, Reinforcement Learning for Calibrated Decisions, método criado pra produzir probabilidades calibradas junto de cada decisão) num chute com cara de certeza
Se você vem do mundo de LLM generativa, é a mesma dor de exigir JSON com schema entre agentes, só que aqui a garantia é estrutural, e sobra energia pra pensar no conteúdo dos campos em vez de no parse
Três schemas de exemplo para decisões comuns
São modelagens ilustrativas, pra você ver a FORMA dos campos. Adapte às suas regras
Triagem de ticket
categoria_ticket: Choice, com as filas reais como opções e rubrica dizendo o que é de cada fila e o que é da fila vizinhaprecisa_resposta_hoje: Noul, comcriteriadetrue/falseporque a fronteira do "urgente" é sutil e cada time entende uma coisaseveridade: Score, com 3 a 5 níveis descritos em ordem crescente de impacto
Três perguntas estreitas, uma requisição, e o roteamento final sai de uma regra sua do tipo "cobrança + severidade alta + urgente = fila prioritária"
Moderação de conteúdo
Aqui a tentação é fazer um Choice gigante de "tipo de violação". Só que um conteúdo pode violar duas políticas ao mesmo tempo, e Choice devolve uma opção só
Então: um Noul independente por política (viola_spam, viola_discurso_odio, viola_dados_pessoais, por aí vai), cada um com instructions próprio e criteria de true/false quando a linha é fina
O código junta: qualquer Noul acima do limiar alto derruba, faixa média manda pra revisão
Avaliação de candidatura ou pitch
É o exemplo da doc levado ao pé da letra: em vez de uma nota geral, um Score por fator independente (tamanho de mercado, viabilidade técnica, diferenciação) e a combinação por uma fórmula sua
O ganho não é só precisão, é auditoria: quando alguém perguntar por que o caso X foi reprovado, tu mostra qual fator puxou pra baixo, em vez de dar de ombros pra uma nota única
Erros de modelagem que quebram o schema na prática
Sintoma: as probabilidades ficam sempre empatadas entre duas opções
Causa: opções ambíguas ou nomeadas genericamente, que se sobrepõem no significado
Correção: renomeie pelo significado e escreva na rubrica o que pertence a cada opção e o que pertence à vizinha
Como prevenir: leia só os nomes das opções, sem a rubrica. Se VOCÊ não consegue classificar três casos reais, o modelo também não vai
Sintoma: a resposta parece "média demais", nunca crava nada
Causa: uma pergunta gigante pesando vários fatores de uma vez
Correção: decompor em perguntas independentes e combinar no código
Como prevenir: toda vez que a instructions precisar da palavra "considere também", nasceu uma segunda pergunta ali
Sintoma: o Score se comporta de forma errática entre níveis
Causa: níveis que não formam uma ordem real, tipo misturar "técnico", "urgente" e "caro" na mesma escala
Correção: ou vira Choice, ou vira vários Scores separados, cada um com escala própria (lembrando: mínimo de 2 e máximo de 10 níveis)
Como prevenir: leia o array de criteria de cima pra baixo. Se não dá pra dizer "este é mais que o anterior", não é escala
Sintoma: o modelo ignora parte da instrução
Causa: rubrica escrita como um parágrafo denso, com definição, exceção e exemplo grudados
Correção: objetos ou arrays com campos nomeados, separando os tipos de orientação
Como prevenir: uma orientação por campo, sempre
Sintoma: o sistema erra feio em casos raros, com toda a confiança do mundo
Causa: o código ignora confidence e age sempre no topo
Correção: faixas de confiança, com a baixa indo pra humano ou pra outro sistema
Como prevenir: no code review, procure qualquer lugar que lê choice sem olhar confidence ou probabilities
Sintoma: a requisição não cabe
Causa: state gigante empilhado com pergunta longa, estourando o orçamento de 32k pro state mais a pergunta mais longa
Correção: enxugar o state pro que a decisão realmente precisa e encurtar as rubricas mantendo a fronteira
Como prevenir: trate o state como payload de API, não como "joga o banco inteiro e reza". Já vi gente se ferrar mandando log completo quando três campos resolviam 🙂
Quando o schema é um modelo Python: o caso do Pydantic AI
Se você prefere descrever o schema como tipo em vez de JSON na mão, o mesmo desenho aparece na integração do Pydantic AI com a TypeSafe
Ali, cada campo do output_type vira uma pergunta, e a anotação define o tipo:
EnumouLiteralvira ChoiceIntEnumvira Scorebooloufloatlimitado vira Noul
E tem um detalhe que reforça tudo que falamos sobre nomes: nessa integração, o Jev enxerga as opções de Literal e Enum apenas pelo nome. Então o nome precisa dizer o que a opção significa, sem depender de comentário no código
Quando a diferença entre duas opções precisa de explicação, usa-se um Enum com UseEnumDocstrings e uma docstring sob cada membro. É a mesma rubrica de antes, só que morando no tipo
Importante deixar claro: isso é detalhe do Pydantic AI, não da API REST do Jev. Na API você continua montando state, model e o mapa de questions na mão
Vídeo: IA lendo código e desenhando estrutura sozinha
Pra quem quer entrar no clima de IA que lê contexto e devolve estrutura em vez de textão, este vídeo do canal mostra uma skill que faz a IA ler seu código e desenhar a arquitetura sozinha
Conclusão
Schema bem desenhado no Jev é decisão decomposta: fatores independentes, cada um num campo tipado, com nomes que dizem o significado e rubricas que marcam a fronteira entre as opções
O modelo devolve o sinal com probabilidade, e a combinação, o peso de cada fator e o limiar ficam no seu código, que é onde regra de negócio deve morar
Próximo passo é bem chato e bem eficiente: escreve a decisão no papel, lista os fatores independentes e monta uma primeira requisição com várias perguntas estreitas sobre o mesmo state
Depois é só olhar as probabilidades e ver onde o modelo hesita, porque é exatamente ali que sua rubrica está frouxa 😀
até o próximo post!
Perguntas frequentes
Quantas opções uma pergunta Choice do Jev pode ter?
Uma pergunta Choice aceita até 255 opções. Cada opção entra no mapa de criteria, que pode ter uma descrição por opção ou null quando aquela opção não precisa de detalhe extra.
Qual a diferença entre confidence e probabilities na resposta do Jev?
probabilities mostra cada opção (ou nível) mapeado pra sua chance, somando 1 no total. confidence é um número único de 0 a 1 que colapsa essa distribuição, pensado pra você aplicar um limiar no código sem refazer a conta.
Por que a resposta de uma pergunta Noul não tem campo confidence?
Porque o Noul retorna só um número, noul, que já é a probabilidade da resposta ser sim. Como esse número sozinho já descreve a incerteza (um 0,51 é tão incerto quanto parece), não existe um confidence separado pra essa primitiva.
Existe limite de quantas perguntas posso colocar numa requisição do Jev?
Não tem um limite fixo de perguntas. O que limita é o orçamento de tokens compartilhado entre o state e as questions, e no modelo jev-1.13.0 esse orçamento é de 32k pra state mais a pergunta mais longa.
Quando usar null no criteria de uma pergunta Choice?
Você usa null quando a opção é autoexplicativa pelo nome e não precisa de uma descrição extra na rubrica. As demais opções do mesmo Choice podem ter descrição normal, o mapa aceita misturar.
Quando vale a pena decompor uma decisão em várias perguntas no Jev?
Sempre que a decisão exigiria raciocínio extenso ou pesaria vários fatores independentes. A documentação recomenda perguntar cada fator separadamente e combinar os resultados com lógica no seu código: em vez de "avalie este pitch de startup", pergunte sobre tamanho de mercado, viabilidade técnica e diferenciação, e junte os scores com uma fórmula sua. Como as perguntas rodam em paralelo na mesma requisição, dá pra empilhar várias perguntas estreitas sobre o mesmo state e ainda manter a regra de negócio versionada no seu repositório.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares

Como montar um workflow de automação combinando decisões do Jev em código
Aprenda a montar um workflow com Jev: decisões tipadas encadeadas em código, alta confiança agindo sozinha e casos incertos escalando para revisão.

Para quem o Jev serve (e para quem não serve)?
Jev serve pra roteamento, scoring e guardrails em IA, não pra texto ou código. Veja pra quem o Jev serve e quando evitar.

Jev decide, LLM escreve: como dividir os papéis dentro de um agente de IA
Jev é o modelo que decide, não escreve: entenda como dividir papéis entre Jev e LLM dentro de um agente de IA e quando usar cada um.
