Como usar o Jev para triar a mensagem do usuário antes de acionar o agente

A triagem com Jev é uma camada que roda antes do agente e decide o destino de cada mensagem: atender, pedir um dado que falta ou mandar direto para um humano. O Jev, modelo de decisão da TypeSafe AI, não gera texto, ele devolve respostas tipadas (Choice, Score ou Noul) com confiança calibrada. Você monta uma Choice para o destino e perguntas Noul em paralelo no mesmo state, e trata o caso ambíguo como caminho próprio: de 0.30 a 0.70 é incerto, acima de 0.70 é sim. Custa US$ 0,042 por milhão de tokens de entrada, e a saída não é cobrada
Fala aí, beleza? Nem toda mensagem que chega deveria acordar o seu agente 😛
Pensa no fluxo normal: o usuário manda qualquer coisa e o LLM já entra em campo, lê tudo, raciocina, gasta token e tempo
Só que muitas vezes o pedido é algo que o agente não consegue atender, ou depende de um dado que ele não tem (número do pedido, conta do usuário), ou é alguém pedindo pra falar com uma pessoa
Aí o modelo fica tentando responder o que não devia, e a conversa fica zoada
A ideia deste post é colocar uma camada de triagem na entrada, antes do agente, usando o Jev
O Jev é um modelo de decisão da TypeSafe AI, lançado em 15 de setembro de 2026 como o primeiro modelo público da linha que a empresa chama de System One Models
E o detalhe que muda tudo: ele não gera texto
Ele lê um estado (texto ou JSON) e devolve respostas tipadas com confiança calibrada
Ou seja: o LLM gera, o Jev decide 🙂
Bora ver na prática?
Por que triar antes de acionar o agente?
Se você já montou um agente, sabe que o LLM é ótimo pra raciocinar, planejar e escrever
Curso de Jev: Sistemas Mais Inteligentes, Rápidos e Robustos
Desenvolva sistemas mais inteligentes, rápidos e robustos com Jev
Porém usar ele pra decidir "essa mensagem vai pra onde?" é tipo chamar o dev sênior pra separar a correspondência do escritório haha
A divisão de papéis fica assim: o LLM raciocina, planeja e gera, enquanto o Jev cuida de classificação, roteamento, nota, triagem e decisões com respostas delimitadas
E o que seria "resposta delimitada"?
É uma resposta que cabe num formato fechado, sem texto livre, e o Jev tem três tipos disso:
| Tipo | O que devolve | Pra que serve na triagem |
|---|---|---|
| Choice | Uma opção dentre opções nomeadas, a probabilidade de cada opção e a confiança | Decidir o destino da mensagem (atender, pedir dado, humano) |
| Score | Uma nota numa rubrica ordenada (pode ser fracionária), a probabilidade de cada nível, uma legenda e a confiança | Medir grau, tipo urgência |
| Noul | A probabilidade de uma hipótese de sim/não | Perguntas binárias, tipo "o usuário pediu uma pessoa?" |
A própria documentação traz um exemplo de triagem que serve de molde: um ticket de loja de calçados ("My running shoes arrived in the wrong size…") com uma Choice que decide a equipe entre returns, shipping e billing
A nossa triagem segue exatamente esse padrão, só que as opções são o destino da mensagem e não a equipe
O que você precisa antes de começar?
Se liga na lista, é curtinha:
- Conta na TypeSafe AI: o cadastro está aberto pra qualquer pessoa, e conta nova ganha US$ 5 de crédito
- Chave de API: gerada em
console.typesafe.ai/settings/keyse exportada na variávelTYPESAFE_API_KEY - Python 3.10 ou superior com o
typesafe-sdk, ou Node.js 20 ou superior com o@typesafe-ai/sdk
Os dois SDKs usam o modelo jev-latest por padrão, então tu nem precisa informar o modelo no começo
E tem o argumento que faz a triagem valer em TODA mensagem: o Jev custa US$ 0,042 por milhão de tokens de entrada, e os tokens de saída não são cobrados
Como ele não escreve resposta, você paga basicamente pela leitura da mensagem 😀
Passo a passo: montando a camada de triagem com o Jev
Agora sim, mão na massa
Passo 1: instalar o SDK e autenticar
No Python, tu roda:
pip install typesafe-sdk
# ou
uv add typesafe-sdk
Se o seu projeto é JavaScript:
npm install @typesafe-ai/sdk
Depois exporta a chave:
export TYPESAFE_API_KEY="sk-..."
Erro comum deste passo: esquecer a variável de ambiente, ou exportar num terminal e rodar o script em outro
Os SDKs leem a chave de TYPESAFE_API_KEY, então se ela não estiver ali, não tem autenticação
Já perdi um tempinho bom com esse tipo de coisa, confere antes de sair debugando o código hehe
Passo 2: modelar a Choice de destino
Aqui mora o coração da triagem
Na Choice, o campo criteria é um mapa: cada chave é o nome de uma opção e cada valor é a descrição dela
Pra nossa entrada, três opções resolvem:
Curso RecomendadoDesenvolva sistemas mais inteligentes, rápidos e robustos com JevConhecer cursoatendivel: o pedido é algo que o agente consegue resolver com o que ele já temfalta_dado: o pedido é atendível, mas depende de uma informação que não veio na mensagemhumano: o caso precisa de uma pessoa
O segredo é escrever descrições mutuamente exclusivas
Cada mensagem deveria caber em uma opção só, sem ficar em cima do muro entre duas
Erro comum deste passo: opções sobrepostas
Se falta_dado e humano descrevem quase a mesma coisa, a probabilidade se divide entre as duas e a confiança despenca, mesmo numa mensagem clarinha
Antes de culpar o modelo, relê as descrições 😛
Passo 3: adicionar perguntas Noul em paralelo
A Choice diz pra onde vai, mas às vezes você quer um sinal binário separado
Tipo:
- A mensagem pede algo que o agente consegue fazer?
- O usuário pediu explicitamente para falar com uma pessoa?
Isso é Noul: a probabilidade de uma hipótese de sim/não
E aqui vem a parte massa: a requisição tem três campos no nível de cima, state (o conteúdo avaliado), model e questions, que é um mapa de ids de pergunta para objetos de pergunta
Ou seja, várias perguntas são avaliadas em paralelo sobre o mesmo state
Você coloca a Choice de destino e as Noul lado a lado, cada uma com seu id (destino, pode_atender, pediu_humano e por aí vai)
Erro comum deste passo: fazer uma chamada pra cada pergunta
Não precisa! Todas cabem na mesma requisição, em cima do mesmo state
Passo 4: chamar o Jev e ler a resposta inteira
Com o SDK Python, o uso básico é importar o TypeSafeClient e chamar client.system_one(state, questions) dentro de um with:
from typesafe_sdk import TypeSafeClient
state = "Quero cancelar meu pedido, mas não lembro o número dele"
questions = {
"destino": {
"criteria": {
"atendivel": "O agente resolve o pedido só com o que veio na mensagem",
"falta_dado": "O pedido é atendível, mas falta uma informação (ex: número do pedido)",
"humano": "O caso precisa ser tratado por uma pessoa",
},
},
}
with TypeSafeClient() as client:
result = client.system_one(state, questions)
print(result)
Na resposta da Choice você recebe a opção vencedora, a probabilidade de cada opção e a confiança, que vai de 0 a 1 e é derivada da distribuição de probabilidade da resposta
Erro comum deste passo: olhar só a opção vencedora
Uma vitória de atendivel com confiança alta e uma vitória apertada com confiança baixa são situações BEM diferentes
E é justamente isso que a próxima seção resolve
Como tratar o caso ambíguo sem travar a conversa?
Aqui é onde a maioria das triagens quebra
O jeito ingênuo é usar um limiar fixo de 0.5 no Noul: passou de 0.5 é sim, abaixo é não
Só que aí 0.49 e 0.51 disparam ações opostas, sendo que os dois valores são, na real, incertos
A própria documentação do Noul sugere outra abordagem: tratar de 0.30 a 0.70 (limites incluídos) como incerto e acima de 0.70 como sim
O que fica abaixo de 0.30 você trata como não
def classifica_noul(probabilidade: float) -> str:
if probabilidade > 0.70:
return "sim"
if probabilidade >= 0.30:
return "incerto"
return "nao"
Na Choice, a orientação é parecida, com três caminhos baseados na confiança:
- Confiança alta: automatiza (aciona o agente, ou pede o dado faltante se a opção for
falta_dado) - Faixa do meio: vai pra revisão
- Confiança baixa: vai pra um humano

Crie sistemas com IA para vender
Prompts, modelos e checklists para criar e publicar seu sistema com IA e preparar a oferta para o primeiro cliente.
Quero o e-book gratuito Receba o livro e os bônus no seu e-mail.E quais números usar?
A documentação não crava um valor universal, e faz sentido: os limiares devem acompanhar o custo de uma ação errada
Se errar o destino só gera uma pergunta a mais, tu pode ser mais permissivo
Se errar significa o agente mexer em pedido de cliente sem o dado certo, aperta o limiar
Na prática, deixa os dois cortes da Choice como configuração, e não cravados no código:
def rota_choice(opcao: str, confianca: float, limiar_alto: float, limiar_baixo: float) -> str:
if confianca >= limiar_alto:
return opcao # automatiza: atendivel, falta_dado ou humano
if confianca >= limiar_baixo:
return "revisao"
return "humano"
E como achar esses valores?
Roda a triagem em mensagens reais do seu histórico e olha em que faixa de confiança o Jev começa a errar o destino: o corte alto fica acima dessa faixa, e quanto mais caro for o erro, mais alto ele sobe
O que ficar entre os dois cortes vai pra revisão, e o que ficar abaixo do corte baixo vai direto pra uma pessoa
Já nos Noul tu tem o ponto de partida da própria documentação: a faixa incerta de 0.30 a 0.70, que a função classifica_noul ali de cima já aplica
Agora, uma decisão de design que é do SEU sistema (não do Jev): o incerto não precisa travar o usuário
Enquanto a revisão acontece, o agente pode mandar uma resposta de espera ou uma pergunta de esclarecimento, tipo "você consegue me passar o número do pedido?"
Assim o caso ambíguo vira um caminho próprio, e não um buraco na conversa
Erro comum desta etapa: tratar incerto como não
Isso joga fora justamente as mensagens que mais precisavam de atenção
Onde essa triagem faz diferença?
Tem alguns use cases em que essa camada se paga rapidinho
Suporte com roteamento por equipe: é o molde do exemplo oficial, com returns, shipping e billing
Você pode até encadear: primeiro decide se é atendivel, falta_dado ou humano, e depois roteia por equipe
Chatbot que depende de dado: quando o pedido precisa de número do pedido ou da conta, a triagem pega isso antes de chamar o LLM
O agente já entra sabendo que precisa pedir a informação, em vez de alucinar uma resposta
Pedido explícito de humano: se o Noul de pediu_humano vem alto, a mensagem pula o agente direto
Nada mais irritante que pedir uma pessoa e receber três parágrafos gerados por IA haha
Decisão de grau, não de categoria: quando a pergunta é "quão urgente é isso?", o tipo certo é o Score
Você monta uma rubrica ordenada de urgência e recebe uma nota ponderada, a probabilidade de cada nível e a confiança
E a mesma lógica de camada na entrada vale pra outras checagens, como moderar conteúdo enviado por usuários ou detectar jailbreak antes do LLM
Tudo roda no mesmo state, como perguntas em paralelo
Próximo passo
Recapitulando o que vimos:
- O Jev decide, o agente gera
- A Choice define o destino (
atendivel,falta_dado,humano) com descrições que não se sobrepõem - As perguntas Noul rodam em paralelo no mesmo
state, na mesma requisição - A confiança importa tanto quanto a opção vencedora
- O caso ambíguo vira caminho próprio, com revisão e uma resposta que não trava o usuário
O próximo passo é simples: cria a conta, usa os US$ 5 de crédito inicial e roda a Choice e os Noul em mensagens reais do seu histórico
Olha onde o Jev acerta, onde ele fica na faixa incerta, e calibra os limiares pelo custo de errar no seu caso
Se tu montar essa triagem com Jev aí no seu projeto, me conta como ficou, bora trocar uma ideia 😀
Até o próximo post!
Perguntas frequentes
Quanto custa usar o Jev para fazer a triagem de cada mensagem?
O Jev cobra US$ 0,042 por milhão de tokens de entrada, e os tokens de saída não são cobrados. Como ele não gera texto, o custo da triagem fica basicamente restrito à leitura do state enviado na requisição.
Preciso entrar numa lista de espera para criar conta na TypeSafe AI?
Não, o cadastro está aberto para qualquer pessoa. Toda conta nova ganha US$ 5 de crédito, o suficiente pra testar a camada de triagem antes de decidir se vale colocar em produção.
O Jev consegue decidir quando uma mensagem precisa ir para um humano?
Sim, esse é justamente o tipo de resposta que a Choice resolve na triagem: você cria uma opção como humano dentro do campo criteria e descreve quando ela se aplica. A confiança devolvida ajuda a decidir se encaminha direto ou se pede confirmação antes.
Qual a diferença entre usar Choice, Score e Noul na triagem com Jev?
Choice escolhe uma opção entre opções nomeadas e devolve a probabilidade de cada uma com a confiança, ótimo pra decidir o destino da mensagem. Score dá uma nota numa rubrica ordenada, útil pra medir grau como urgência. Noul responde só a probabilidade de uma hipótese de sim/não, ideal pra perguntas binárias como se o usuário pediu um humano.
O Jev substitui o LLM que está dentro do agente?
Não, a ideia é dividir papéis: o LLM continua raciocinando, planejando e gerando a resposta final. O Jev entra antes disso, cuidando de classificação, roteamento e triagem com respostas tipadas e confiança calibrada.
Dá para montar essa triagem com Jev em projetos Node.js?
Dá sim, a TypeSafe AI mantém o SDK @typesafe-ai/sdk para JavaScript, que exige Node.js 20 ou superior. Ele lê a chave da mesma variável TYPESAFE_API_KEY e usa o jev-latest como modelo padrão, igual ao SDK Python.
Formações
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 48min
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.

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.

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.
