Como usar o Jev para triagem e roteamento de tickets de suporte

fluxo de Jev triagem de tickets classificando categoria, fila e urgência de um chamado de suporte
Resposta rápida

O Jev é o primeiro modelo da classe System One da TypeSafe AI: ele recebe um bloco de estado mais perguntas tipadas e devolve decisões com probabilidades, sem string pra dar parse. Pra montar uma triagem de tickets com o Jev, você modela o ticket como estado e manda na mesma chamada um Choice de categoria, um Choice de fila, um Score de urgência e Nouls binários (reembolso, risco de churn). Todas as perguntas rodam em paralelo contra o mesmo estado, e o código roteia lendo campos tipados. A pontuação de confiança define o que vai pra revisão humana.

Triagem de ticket é o trabalho mais chato do suporte e, ao mesmo tempo, o que mais estraga a fila quando sai errado

E quando a gente tenta resolver com LLM, aparece o segundo problema: a resposta vem em texto. Aí é JSON.parse dentro de try/catch, regex pra limpar crase de bloco de código, retry porque o modelo resolveu explicar o raciocínio antes de responder… um festival

O Jev ataca exatamente esse ponto. Ele é o primeiro modelo da classe System One da TypeSafe AI e não gera texto: recebe um bloco de estado mais perguntas tipadas e devolve decisões estruturadas com probabilidades

Neste post a gente monta um fluxo de ponta a ponta: classificar o pedido, escolher a fila, medir urgência, marcar sinais binários e deixar o código rotear, sem parsing. E, principalmente, onde entra a pontuação de confiança pra mandar caso duvidoso pra revisão humana

Bora? 🙂

O que você precisa antes de começar

O Jev está em early access liberado por lista de espera desde 15 de setembro de 2026, e até 20/09/2026 não foi anunciada disponibilidade geral (GA). Se você ainda não tem acesso direto, ele também está listado no OpenRouter (incluindo a versão Jev 1.13), na documentação de modelos do Cloudflare AI e no AI Gateway da Netlify

Do lado da máquina, o checklist é curtinho:

  • Chave da API na variável de ambiente TYPESAFE_API_KEY
  • SDK Python: pip install typesafe-sdk, com Python 3.10 ou superior. O cliente lê a TYPESAFE_API_KEY do ambiente e chama jev-latest por padrão
  • SDK JavaScript/TypeScript: npm install @typesafe-ai/sdk, com Node.js 20 ou superior. Entrega ESM, CommonJS e tipos, e expõe a classe TypeSafeClient mais os helpers choice, score e noul, com os tipos de resposta inferidos das perguntas
pip install typesafe-sdk
export TYPESAFE_API_KEY="sua-chave-aqui"

Se preferir Node:

npm install @typesafe-ai/sdk

A chamada crua, se você quiser bater direto no HTTP, é um POST https://api.typesafe.ai/v1/systemone com o campo model apontando pra rota jev-latest

E qual versão é essa jev-latest? Hoje o alias resolve pra jev-1.13.0, e ele muda quando sai versão nova. IDs versionados tipo jev-1.13.0 também são aceitos no campo model, e um GET /v1/models lista os nomes disponíveis pra sua conta. Roda esse GET antes de escrever qualquer coisa, é o jeito mais rápido de descobrir o que a tua chave enxerga

Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 45min

Passo a passo: montando a triagem e o roteamento de tickets

A lógica aqui é diferente da que você usa com modelo de texto. Você não pede "me devolve um JSON com categoria e urgência"

Você monta um estado (o ticket) e várias perguntas tipadas sobre esse estado. O modelo responde cada uma de forma independente, com probabilidades

  1. Modelar o bloco de estado com os dados do ticket

Estado é tudo que o Jev precisa enxergar pra decidir: assunto, corpo da mensagem, plano do cliente, histórico recente, canal de entrada

const state = {
  ticket: {
    assunto: "Cobrança duplicada no cartão em setembro",
    corpo: "Fui cobrado duas vezes esse mês e quero o dinheiro de volta ou cancelo",
    canal: "email"
  },
  cliente: {
    plano: "business",
    meses_ativo: 14,
    tickets_ultimos_30d: 3
  }
}

O erro comum deste passo é jogar o histórico inteiro do cliente no estado "por garantia". O orçamento de contexto do Jev, contado em tokens, é de 64K pro estado somado a todas as perguntas, com limite de 32K pro estado somado à maior pergunta individual. Estado gordo é a forma mais fácil de estourar os dois

Guarda esses dois na cabeça como "limite de contexto". No passo 6 aparecem outros dois limites, de quantidade de perguntas e de tamanho do JSON, que são bicho diferente e valem por requisição

  1. Escrever o Choice da categoria do pedido

Choice escolhe uma opção de um conjunto definido por você antes da chamada. É a primitiva da classificação

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

const client = new TypeSafeClient({ apiKey: process.env.TYPESAFE_API_KEY })

const categoria = choice({
  question: "Qual é a natureza principal do pedido do cliente neste ticket?",
  options: ["bug", "duvida_de_uso", "financeiro", "cancelamento", "seguranca"]
})

O erro comum aqui é criar opções que se sobrepõem, tipo financeiro e reembolso no mesmo conjunto. Se duas opções descrevem o mesmo ticket, a probabilidade racha entre elas e a confiança despenca, mesmo o modelo tendo "entendido" certo

  1. Choice da fila de destino

Categoria e fila não são a mesma coisa, e é por isso que valem duas perguntas separadas. Um bug de cobrança pode ser categoria bug e fila billing

const fila = choice({
  question: "Para qual fila este ticket deve ser roteado?",
  options: ["n1_geral", "billing", "engenharia", "retencao", "seguranca"]
})

O erro comum: amarrar fila a categoria no prompt ("se for financeiro, mande pra billing"). Isso é regra de negócio, e regra de negócio é código. Deixa o modelo responder as duas perguntas e decide o encaminhamento depois, no seu if

  1. Score da urgência contra níveis ordenados

Score avalia contra níveis ordenados, e o retorno não é um rótulo seco: é uma posição contínua ao longo dos níveis, que pode cair entre dois deles, acompanhada da probabilidade de cada nível e da confiança

const urgencia = score({
  question: "Qual a urgência de atendimento deste ticket?",
  levels: ["baixa", "normal", "alta", "critica"]
})

O erro comum é tratar Score como Choice e só olhar o nível vencedor. Você joga fora justamente a informação mais útil pra fila de SLA, que é o ticket parado entre alta e critica

  1. Noul pras perguntas de sim ou não

Noul é a pergunta binária. Perfeita pros sinais que disparam ação independente da categoria

const pedeReembolso = noul({
  question: "O cliente está pedindo reembolso?"
})

const riscoChurn = noul({
  question: "Há sinal explícito de intenção de cancelar o serviço?"
})

Tome cuidado aqui! O Noul retorna apenas a probabilidade da proposição ser verdadeira e NÃO tem campo de confiança separado, porque a própria probabilidade já descreve a incerteza do sim/não. Ou seja: código que lê answer.confidence em toda resposta quebra nas binárias. Esse é o erro comum do passo, e é do tipo que só aparece em produção, num ticket qualquer, às três da manhã

  1. Mandar tudo na mesma requisição

Todas as perguntas de uma requisição rodam em paralelo contra o mesmo estado, e cada pergunta extra custa apenas os próprios tokens. A TypeSafe chama esse padrão de speculative fan-out: dá pra perguntar tudo que talvez seja necessário numa chamada só e deixar o código escolher o que vai usar

const res = await client.evaluateAll({
  model: "jev-latest",
  state,
  questions: { categoria, fila, urgencia, pedeReembolso, riscoChurn }
})

E aqui entram os tais outros limites, que não são os de contexto do passo 1: por requisição, o Jev aceita 32 perguntas e 64 KiB de JSON. Um é contagem de perguntas, o outro é tamanho do payload em disco, nada a ver com os 64K e 32K de contexto em tokens

O evaluateAll aceita qualquer número de perguntas sobre um mesmo estado e divide em lotes acima de 32

O erro comum: montar 40 perguntas na mão com a chamada simples e tomar erro de limite. Se o teu catálogo de perguntas cresceu, usa o evaluateAll e deixa o chunking com o SDK

  1. Ler os campos tipados e executar o roteamento

Agora a parte que justifica tudo: não tem parsing. A resposta já vem restrita ao schema que você definiu antes da chamada

const probs = res.categoria.probabilities
const topo = Object.entries(probs).sort((a, b) => b[1] - a[1])[0]
const [rotulo, p] = topo

if (rotulo === "seguranca" && p >= 0.6) {
  encaminhar("seguranca", { prioridade: "p1" })
}

Os nomes exatos dos campos você confere na documentação de primitivas. O contrato que não muda é esse: Choice e Score trazem probabilities mais confiança, Noul traz só a probabilidade

Primitiva Pergunta que responde O que volta
Choice uma opção de um conjunto definido opção escolhida, probabilities por opção e confiança
Score avaliação contra níveis ordenados posição contínua entre níveis, probabilidade por nível e confiança
Noul sim ou não apenas a probabilidade da proposição ser verdadeira, sem campo de confiança

Se a tua triagem hoje já roda em cima de um fluxo de automação, tipo categorizar tickets no Chatwoot com n8n, o Jev não substitui o fluxo: ele vira o nó de decisão que devolve campo tipado pro resto do pipeline consumir

Onde a pontuação de confiança entra no roteamento

Essa é a parte que separa demo bonita de triagem que aguenta produção

A confiança do Jev é uma estatística calculada a partir da distribuição de probabilidades da própria resposta, expressa como um número de 0 a 1. Distribuição concentrada significa resposta confiante, distribuição espalhada significa resposta incerta

Ou seja: não é o modelo "achando" que acertou. É o formato da distribuição, e isso é auditável

O padrão prático é decidir pela probabilidade do topo. No cookbook de consistência de Choice da TypeSafe, a aplicação não é obrigada a agir sobre a opção vencedora: quando a probabilidade do topo fica abaixo de 0,60 o resultado vira uncertain e vai pra revisão humana (em exatamente 0,60 o rótulo do topo é aceito). Com essa regra, naquele exemplo, a concordância sobe pra 99,2% e 74,2% das respostas são rotuladas automaticamente

function decidir(answer, corte = 0.6) {
  const [rotulo, p] = Object.entries(answer.probabilities)
    .sort((a, b) => b[1] - a[1])[0]

  if (p < corte) return { status: "uncertain", sugestao: rotulo, p }
  return { status: "ok", rotulo, p }
}

const destino = decidir(res.fila)
if (destino.status === "uncertain") {
  enviarParaRevisaoHumana(ticket, destino.sugestao)
} else {
  encaminhar(destino.rotulo)
}

Só que atenção, e isso a própria documentação avisa: os thresholds dos cookbooks e os resultados das demos são exemplos pra você avaliar com dados próprios, não regras universais nem limite permanente do modelo. A orientação é definir os cortes a partir dos seus dados e das consequências de errar, prevendo saída de no-match e escalonamento dos casos incertos

O 0,60 ali vem de um cenário de Choice/moderação. Suporte é outro domínio

O erro comum desta seção é aplicar o mesmo corte pra toda fila sem pesar consequência. Errar entre n1_geral e duvida_de_uso custa um reencaminhamento chato. Errar um ticket de seguranca custa outra coisa bem diferente. Fila crítica pede corte mais alto e revisão humana mais generosa, fila barata pode automatizar mais

Variações do fluxo: do roteamento simples ao SLA e detecção de risco

O bonito do speculative fan-out é que essas variações não são fluxos novos. São perguntas a mais na MESMA chamada

  • Priorização por SLA: usa o valor contínuo do Score de urgência em vez do rótulo. Ticket que cai entre alta e critica entra na frente de quem está firme em alta
  • Separação entre bug, dúvida e financeiro: o Choice de categoria já resolve, e você ganha a distribuição pra auditar depois quais tipos de ticket vivem em cima do corte
  • Detecção de pedido de cancelamento: Noul direto, e o disparo pro time de retenção independe da fila escolhida
  • Roteamento pro time de segurança: Noul do tipo "o ticket menciona acesso indevido à conta?", com corte próprio e bem conservador

E por que sai mais barato perguntar tudo de uma vez? Porque cada pergunta extra custa apenas os próprios tokens. No cookbook de perguntas paralelas da TypeSafe, agrupar 13 perguntas numa única chamada saiu 12,2 vezes mais barato e 10,0 vezes mais rápido do que perguntar uma de cada vez, com respostas idênticas

Soma a isso o preço: US$ 0,042 por milhão de tokens de entrada, e a saída não é cobrada. A TypeSafe reporta tempos de resposta ponta a ponta de 70 a 500 milissegundos e, em tarefas de classificação, até 200 vezes mais velocidade e 400 vezes menos custo que LLMs comparáveis, com 0% de erro de saída estruturada e 0% de erro de chamada de ferramenta, já que a resposta fica restrita ao schema definido antes da chamada (esses números são dados da empresa, vale medir no teu cenário)

Pra quem já tem um agente de suporte L1 no WhatsApp rodando, dá pra pensar no Jev como a camada de decisão antes da resposta: ele diz categoria, fila, urgência e sinais binários, e o agente só age

Colocando em produção: erros, limites de taxa e integrações

  1. Trate o 429 desde o começo

Os limites de taxa documentados são 250.000 tokens por segundo e 1.200 requisições por minuto. Passar de qualquer um deles devolve 429 Too Many Requests

A boa notícia: os SDKs oficiais já tratam os códigos 429 e 529 com retentativa em backoff exponencial e respeitam o header retry-after quando a resposta traz esse cabeçalho

O erro comum é reimplementar retry por cima do retry do SDK e acabar com duas camadas brigando, o que só ajuda a estourar o limite de novo

  1. Fixe o ID versionado quando o comportamento precisa ser estável
const res = await client.evaluateAll({
  model: "jev-1.13.0",
  state,
  questions
})

Lembra que jev-latest resolve hoje pra jev-1.13.0 e muda quando sai versão nova? Se você calibrou thresholds em cima de uma versão, trocar de modelo sem querer muda a distribuição debaixo dos teus cortes. Em triagem que roteia sozinha, isso é o tipo de surpresa que ninguém quer

  1. Escolha o caminho de acesso

Além da API própria, o Jev está no OpenRouter (incluindo a versão Jev 1.13), na documentação de modelos do Cloudflare AI e no AI Gateway da Netlify

  1. Use os guias de framework se o teu stack já tem um

Tem guia oficial do Pydantic AI para o provedor TypeSafe (Jev) e guia da Vercel pra classificar, rotear e pontuar com Jev no AI SDK. Se o teu backend já vive em um desses dois, começa por ali em vez de escrever cliente HTTP na mão

Vídeo: introdução a roteamento no Next.js

Depois que a decisão vira campo tipado, alguém precisa ver isso numa tela: painel da fila, detalhe do ticket, caixa de revisão dos casos uncertain

Pra começar do zero com criação de páginas e roteamento no Next.js, este vídeo do canal mostra o caminho:

Próximo passo

O ganho central do Jev na triagem de tickets é simples de resumir: a decisão chega tipada, com probabilidade por opção, e o teu código age direto. Some a isso o corte de confiança, que é o que garante que o caso duvidoso vá pra revisão humana em vez de entupir a fila errada

O próximo passo antes de ligar qualquer roteamento automático é sempre o mesmo: pega uma amostra de tickets reais já classificados por humano, roda o fluxo, mede a concordância e calibra os teus thresholds por fila, pesando o custo de errar em cada uma

Só pra situar de onde vem esse modelo: a TypeSafe AI saiu do modo stealth com o Jev e é financiada com US$ 40 milhões, e o early access foi lançado por Diogo Almeida, cocriador dos métodos de instruction tuning do ChatGPT

É cedo, é early access por lista de espera e ainda não tem GA anunciada. Mas a ideia de parar de dar parse em string pra tomar decisão já vale o teste… 😀

Até o próximo post!

Perguntas frequentes

Dá pra misturar Choice, Score e Noul na mesma chamada de triagem de tickets?

Sim. As três primitivas do Jev (Choice, Score e Noul) podem aparecer na mesma requisição, avaliadas de forma independente contra o mesmo estado. Na prática você pergunta categoria, fila, urgência e sinais binários de uma vez só, sem precisar de chamadas separadas.

Quanto custa rodar o Jev pra triagem de tickets em volume alto?

O preço é de US$ 0,042 por milhão de tokens de entrada, e a saída não é cobrada. Como perguntas extras na mesma chamada custam só os próprios tokens (o tal speculative fan-out), o cookbook da TypeSafe registrou 13 perguntas em lote saindo 12,2 vezes mais barato e 10,0 vezes mais rápido do que perguntar uma por vez.

O que fazer quando a probabilidade do Choice fica baixa na triagem?

No cookbook de consistência de Choice da TypeSafe, quando a probabilidade da opção do topo fica abaixo de 0,60 o resultado vira uncertain e vai pra revisão humana (em exatamente 0,60 o rótulo do topo é aceito). Com esse corte específico a concordância subiu pra 99,2% e 74,2% das respostas foram rotuladas automaticamente, mas a própria TypeSafe avisa que esse threshold é exemplo de cookbook, não regra universal: calibra com os teus dados.

O Jev funciona fora da API própria da TypeSafe pra rotear tickets?

Sim, o Jev está listado no OpenRouter (incluindo a versão Jev 1.13), na documentação de modelos do Cloudflare AI e no AI Gateway da Netlify. Também tem suporte documentado em frameworks de terceiros: guia oficial do Pydantic AI pro provedor TypeSafe e guia da Vercel pra classificar, rotear e pontuar com Jev no AI SDK.

Quantas perguntas dá pra fazer numa única chamada de triagem de tickets?

O limite por requisição do Jev é de 32 perguntas e 64 KiB de JSON. Se a tua triagem precisar de mais perguntas do que isso sobre o mesmo ticket, a chamada evaluateAll aceita qualquer número de perguntas e faz o chunking automaticamente em lotes acima de 32.

Qual a diferença entre confidence no Choice/Score e no Noul na hora de decidir o roteamento?

Choice e Score retornam probabilities mais um campo de confidence separado, então tu enxerga a distribuição inteira entre as opções ou níveis. O Noul devolve só a probabilidade da proposição ser verdadeira, sem campo de confidence próprio, porque essa probabilidade já descreve a incerteza da resposta binária.




Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares