Como usar o Jev para decidir qual ferramenta o agente vai chamar?

O Jev é o primeiro modelo público da classe System One da TypeSafe AI: ele avalia um estado e devolve resposta tipada com probabilidades e confiança, em vez de gerar texto. Para roteamento de ferramentas, isso vira uma pergunta do tipo choice: você define as opções antes, monta o state como objeto JSON, faz um POST em https://api.typesafe.ai/v1/systemone e lê choice, probabilities e confidence. Com uma opção de escape tipo "other" e um limiar de confiança por risco, o dispatcher para de torcer pra string bater e passa a decidir com número na mão
Fala aí, beleza? Roteamento de ferramenta em agente ainda é, na maioria dos projetos, uma aposta: o LLM escreve o nome da tool em texto livre e o dispatcher fica torcendo pra string bater com alguma chave do dicionário
Quando bate, ótimo
Quando não bate, você descobre em produção, com um KeyError bonito no log ou, pior, com a ferramenta errada rodando calada
O Jev ataca exatamente essa etapa. Ele é o primeiro modelo público da classe System One da TypeSafe AI: avalia um estado e devolve respostas tipadas com probabilidades e confiança, em vez de gerar texto
Ou seja: a escolha da ferramenta deixa de ser uma frase que você precisa parsear e vira uma decisão entre opções que VOCÊ definiu antes, com um número dizendo o quanto o modelo confia naquilo
Bora montar isso na prática?
O que você precisa antes de começar
A barreira de entrada aqui é baixa. O Jev entrou em early access com lista de espera em 15 de setembro de 2026, mas a waitlist já foi removida e o acesso está aberto pra qualquer pessoa: cadastro no console em console.typesafe.ai, com crédito inicial gratuito de US$ 5
O checklist é curto:
- Conta criada no console e uma chave de API gerada
- A chave exportada na variável de ambiente
TYPESAFE_API_KEY(é dela que o client dos SDKs oficiais lê) - SDK instalado, se você for usar um:
pip install typesafe-sdk(ouuv add typesafe-sdk), que pede Python >= 3.10, ounpm install @typesafe-ai/sdkno lado JS/TS
Sobre custo, pra você dimensionar o roteador antes de sair plugando em tudo: o Jev cobra US$ 0,042 por milhão de tokens de entrada, e os tokens de saída não são cobrados
Isso muda o cálculo mental. Um roteador que roda em TODO turno do agente normalmente é a parte que você tem medo de deixar ligada… aqui o peso vai quase todo pro tamanho do state e das perguntas que você manda
Passo a passo: roteando a chamada de ferramenta com uma pergunta choice
A API do System One expõe três tipos de pergunta, definidos pelo campo type: noul (sim/não), choice (uma opção de um conjunto) e score (posição em uma escala)
Os três compartilham type e instructions, e cada um acrescenta o seu próprio criteria

Domine o Jev e coloque decisões de IA dentro do seu sistema
Você vai aprender a usar o Jev, o System One Model da TypeSafe AI, pra automatizar decisões com resposta tipada e confiança medida, sem depender de chat nem de alguém revisando cada passo. Entre na lista de espera para garantir a condição de lançamento!
Pro nosso caso, escolha de ferramenta é choice. Sempre
- Desenhe o state como objeto JSON, com subcampos nomeados
O campo state aceita string, objeto JSON ou array de textos. A documentação recomenda objeto na maioria das requisições, pra cada parte do estado ter um nome descritivo, e orienta passar os subcampos relevantes em vez de serializar tudo em um template de string
{
"user_turn": "quanto eu gastei em anuncios no mes passado?",
"last_tool_used": "none",
"user_plan": "pro",
"has_connected_billing_account": true
}
O erro comum deste passo: pegar todo o histórico da conversa, jogar dentro de uma f-string gigante e mandar como state. Além de ficar caro à toa, o Jev 1.13 degrada quando há contexto irrelevante no state. Nomeie e recorte
- Escreva a pergunta
choicecominstructionsecriteria
Em um Choice, criteria é um mapa de opção para descrição do critério. A documentação permite passar null quando a opção não precisa de detalhe extra, mas guarde isso pra opção realmente autoexplicativa
Opção de escape (aquela que recebe tudo que não coube nas outras) é o caso oposto: ela SEMPRE merece descrição, e eu volto nesse ponto mais pra frente
"tool": {
"type": "choice",
"instructions": "Qual ferramenta atende o pedido do usuario neste turno?",
"criteria": {
"get_ad_spend": "Gasto com anuncios em um periodo, por conta ou campanha",
"get_invoice": "Faturas emitidas, segunda via, status de pagamento",
"search_docs": "Duvida conceitual sobre o produto, sem dado de conta",
"handoff_human": "Pedido fora do escopo das ferramentas ou que exige atendimento humano"
}
}
O erro comum deste passo: encurtar a lista de opções achando que "menos é mais". Um Choice aceita até 255 opções, e cada opção adicional custa poucos tokens, então a própria documentação orienta passar a lista completa em vez de uma lista curta. Se o agente tem 40 tools, mande as 40
- Monte a requisição
O endpoint é POST https://api.typesafe.ai/v1/systemone, com header Authorization: Bearer <API_KEY> e Content-Type: application/json. O corpo tem três campos: state, model e questions
O questions é um mapa de perguntas tipadas cujas chaves você escolhe, e as respostas voltam sob as mesmas chaves. Isso é ótimo: o nome da chave é o seu contrato
curl -X POST https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "jev-latest",
"state": {
"user_turn": "quanto eu gastei em anuncios no mes passado?",
"user_plan": "pro",
"has_connected_billing_account": true
},
"questions": {
"tool": {
"type": "choice",
"instructions": "Qual ferramenta atende o pedido do usuario neste turno?",
"criteria": {
"get_ad_spend": "Gasto com anuncios em um periodo, por conta ou campanha",
"get_invoice": "Faturas emitidas, segunda via, status de pagamento",
"search_docs": "Duvida conceitual sobre o produto, sem dado de conta",
"handoff_human": "Pedido fora do escopo das ferramentas ou que exige atendimento humano"
}
}
}
}'
No campo model, jev-latest é o padrão do SDK, e IDs versionados como jev-1.13.0 também são aceitos. Em roteador de produção eu fixaria a versão, pra sua decisão não mudar de comportamento sem você saber
O erro comum deste passo: ignorar que a ordem das opções faz parte do que o Jev enxerga. Reordenar as opções pode mudar a resposta, então não gere esse mapa a partir de um set do Python nem de um dicionário que você monta em ordem aleatória a cada deploy
- Leia a resposta
A resposta de um Choice traz a opção escolhida em choice, a distribuição de probabilidade em probabilities (uma por opção) e um confidence entre 0 e 1 para a opção selecionada
{
"tool": {
"choice": "get_ad_spend",
"probabilities": {
"get_ad_spend": 0.91,
"get_invoice": 0.05,
"search_docs": 0.02,
"handoff_human": 0.01
},
"confidence": 0.91
}
}
Repare na soma do exemplo: ela não fecha em 1.0, e isso não é bug
O erro comum deste passo: tratar probabilities como se fosse uma distribuição fechada. A própria TypeSafe documenta que probabilidades complementares não somam necessariamente 1.0 no Jev 1.13, então não escreva lógica do tipo "pego 1 menos a soma das outras"
- Despache
Agora o dispatcher fica chato de tão simples: ele recebe uma chave que só pode ser uma das que você mesmo escreveu
HANDLERS = {
"get_ad_spend": get_ad_spend,
"get_invoice": get_invoice,
"search_docs": search_docs,
"handoff_human": handoff_human,
}
answer = response["tool"]
HANDLERS[answer["choice"]](state)
Sem regex, sem "será que ele escreveu get_ad_spend ou getAdSpend?", sem retry porque o modelo inventou uma tool que não existe
Como tratar o caso em que nenhuma ferramenta serve
Esse é o ponto onde a maioria dos roteadores quebra na vida real. O usuário manda "bom dia", ou pede uma coisa que nenhuma tool cobre, e o modelo escolhe a opção menos pior porque você o obrigou a escolher alguma
- Coloque uma opção de escape na lista
A documentação do Choice recomenda adicionar uma opção do tipo other ou none of the above quando a lista pode não cobrir todos os casos, justamente pro modelo poder dizer que nenhuma das outras serve
"criteria": {
"get_ad_spend": "Gasto com anuncios em um periodo",
"get_invoice": "Faturas, segunda via, status de pagamento",
"search_docs": "Duvida conceitual, sem dado de conta",
"none": "Nenhuma ferramenta se aplica: conversa social, ruido ou pedido fora de escopo"
}
O erro comum deste passo: deixar o escape sem descrição. Lembra do null lá do passo 2? Ele serve pra opção autoexplicativa, não pra essa aqui. Um other com null vira lixeira de tudo que o modelo não entendeu. Descreva QUANDO ele deve ser usado
- Corte por confiança
O padrão documentado de roteamento por intenção é direto: cheque o confidence da escolha e roteie para um humano quando estiver abaixo de um limiar (o exemplo da documentação usa 0.5), senão despache pro handler correspondente
answer = response["tool"]
if answer["confidence"] < 0.5:
handoff_human(state)
else:
HANDLERS[answer["choice"]](state)
- Use um limiar por ação, proporcional ao risco
Um limiar único pra tudo é preguiça. A documentação traz o padrão de limiar por ação: mais baixo pra ações reversíveis e somente leitura, mais alto pra ações arriscadas
| Tipo de ação | Comportamento sugerido na documentação |
|---|---|
| Reversível / somente leitura | Limiar mais baixo, despacha direto |
| Arriscada | Abaixo de 0.6, roteia para humano |
| Alto risco | Abaixo de 0.5 vai para humano, acima de 0.9 segue com confirmação, no meio verifica antes |
É a mesma lógica de graduar decisão por consequência que aparece quando você usa decisão tipada para qualificar leads: errar pra baixo custa pouco, errar pra cima custa caro
- Escale o caso incerto, não force o palpite
A documentação de arquitetura recomenda escalar casos incertos para uma pessoa ou para um modelo de raciocínio mais caro
E recomenda testar os limiares plotando confiança contra acurácia nos seus próprios dados. Não herde o 0.5 do exemplo e durma tranquilo: o número certo é o que sai do SEU histórico
Escolher a ferramenta e os argumentos na mesma requisição
Aqui fica mais interessante. O cookbook oficial de function calling mostra que a escolha da função E os argumentos de conjunto fechado podem virar perguntas tipadas com confiança, tudo na mesma ida
O desenho é: uma requisição carrega a escolha da função e os argumentos de TODAS as funções, e o dispatcher lê apenas as respostas da função escolhida
Parece desperdício? É o contrário de um round-trip extra por argumento
- Mapeie cada argumento de conjunto fechado pro primitivo certo
O cookbook mapeia argumento de conjunto fechado como choice (um valor), set (vários valores) ou flag (booleano)
Se o argumento é texto aberto, ele não cabe nesse desenho: lembre que o Jev não gera texto
- Monte o mapa de perguntas com prefixo por função
Como as chaves de questions são suas, dá pra namespacear e depois filtrar só o ramo vencedor
chosen = response["function"]["choice"]
args = {
key.split(".", 1)[1]: value["choice"]
for key, value in response.items()
if key.startswith(f"{chosen}.")
}
- Leia a confiança por argumento, não só a da função
O exemplo numérico do cookbook deixa isso claro: a frase "is amd tracking nvidia lately" retorna rolling_correlation(symbol='AMD', benchmark='NVDA') com confiança geral de 0.82, sendo p 0.87 para symbol igual a ‘AMD’ e p 0.78 para benchmark igual a ‘NVDA’
Repare que a confiança não é uniforme dentro da mesma chamada. Dá pra confirmar só o argumento fraco em vez de descartar a chamada inteira
O erro comum deste passo: tentar preencher todo argumento opcional na marra. No cookbook, argumentos opcionais que não foram citados simplesmente ficam de fora, e a função usa seus defaults
Quando o catálogo de ferramentas é grande: o padrão de duas requisições
Mandar 40 tools em um Choice é tranquilo. E quando o roster tem centenas?
O cookbook oficial de sugestão de skill descreve exatamente o problema do roteamento por lista de nomes e propõe um padrão de duas requisições:
- Primeira requisição: ranqueia o roster inteiro e pergunta se precisa de alguma skill
No exemplo do cookbook são 182 skills. A primeira ida ranqueia todas e também responde se o turno precisa de alguma skill
- Segunda requisição: relê só o topo, com descrição completa
A segunda pega apenas as três primeiras, agora com a descrição completa de cada uma, e pode rejeitar todas
O resultado publicado no cookbook: as cargas de skill errada e as cargas quando nada serve caem mais da metade
- Respeite o orçamento de contexto
Esse padrão existe porque contexto não é infinito. No Jev 1.13, 64k cobre o state somado a todas as perguntas, e 32k se aplica ao state somado à pergunta mais longa
Ou seja: a lista completa de nomes curtos cabe fácil na primeira requisição, as descrições longas só cabem quando você já filtrou o topo. O padrão de duas idas não é firula, é o jeito de caber
Onde esse roteamento tipado já está plugado (Pydantic AI, LangChain, Cloudflare)
Se você não quer montar o cliente na mão, já tem caminho pronto em três lugares bem diferentes da stack
Pydantic AI
O Pydantic AI tem integração oficial com o Jev via TypeSafeModel, instalada pelo extra typesafe, que traz a dependência typesafe-sdk
O perfil do modelo declara supports_text_output=False, o que é honesto e evita que você tente usar aquilo como chat
O detalhe elegante: um output_type com vários tipos estruturados funciona como conjunto de rotas, e uma segunda requisição pergunta apenas os campos do tipo escolhido. É o mesmo padrão de duas idas, só que embrulhado
LangChain
A LangChain publicou um middleware que usa o Jev dentro do harness do agente: o AutoModeMiddleware usa o Jev pra checar chamadas de ferramenta arriscadas e bloquear a chamada antes da execução
Tome cuidado com um detalhe importante: ele RECUSA, não pede aprovação. Se o que você quer é aprovação humana, precisa combinar com o human-in-the-loop middleware
No mesmo material, a LangChain reporta os números divulgados pela TypeSafe: inferência até 200x mais rápida e custo até 400x menor que LLMs comparáveis em tarefas de classificação
Cloudflare
O Jev também está na plataforma de IA da Cloudflare, com model ID typesafe/jev, invocável pelo binding AI com env.AI.run(). A versão documentada lá é jev-1.13.0
Pra quem já roda o agente em Worker, isso tira uma chamada externa do caminho
Limites: onde o roteamento pelo Jev quebra
Agora a parte honesta, porque esse desenho tem custo
A própria TypeSafe publica as fraquezas do Jev 1.13, e várias delas batem em cheio em roteamento de ferramenta:
- Leitura literal: negações, escopo e condições implícitas são lidas ao pé da letra. "Não quero ver a fatura, quero o gasto" é o tipo de turno que merece teste
- Matemática e contagem fracas, e ordenação de datas fraca. Se a sua escolha de tool depende de comparar períodos, não delegue a comparação pro modelo
- Indireção multi-hop é difícil pra ele
- Degradação com contexto irrelevante no state: mais um motivo pra recortar o state em vez de despejar a conversa inteira
- Quebra sob instruções contraditórias
- Sem geração de texto: argumento de texto livre não sai daqui
- Probabilidades complementares que não somam necessariamente 1.0
E tem o ponto de segurança, que é o mais sério quando você usa isso como guarda. Conteúdo escrito de forma adversarial pode mover a resposta: injeção de instrução, enquadramento enganoso ou texto que argumenta pela própria classificação conseguem mudar a decisão
Soma isso ao fato de que reordenar as opções pode mudar a resposta, e a conclusão é uma só: uma guarda construída sobre o Jev fica AO LADO de checagens determinísticas, nunca no lugar delas
Vale a pena onde? Roteamento de conjunto fechado, com opções que você define, com confiança lida e limiar por risco. É o mesmo terreno de quando o Jev é usado pra moderar conteúdo enviado por usuários: decisão repetitiva, opções conhecidas, volume alto
Não vale a pena onde? Quando a decisão exige contar, calcular, ordenar data, seguir uma cadeia de referências ou produzir texto. Aí o trabalho continua sendo de outro modelo, e o Jev no máximo decide se vale chamar esse outro modelo
Conclusão
O resumo do desenho cabe em quatro linhas:
statecomo objeto JSON com subcampos nomeados, sem contexto irrelevante- lista COMPLETA de opções no Choice, em ordem estável (cabem até 255)
- uma opção de escape tipo
otherounone, com descrição de quando usar - limiar de confiança por ação, proporcional ao risco, com escalonamento pra pessoa ou pra um modelo mais caro
Próximo passo concreto: cria a conta no console, que o acesso está aberto e vem com US$ 5 de crédito grátis, e porta UM único ponto de roteamento do seu agente, não o agente inteiro
Deixa rodar, guarda o confidence junto com o acerto real, plota um contra o outro e só depois escolhe o seu limiar de verdade
Aí sim tu expande pro resto…
até o próximo post! 😀
Perguntas frequentes
Como decidir o limiar de confiança pra rotear pra um humano em vez da ferramenta escolhida pelo Jev?
A documentação traz um padrão de corte: você checa o confidence da escolha e, se estiver abaixo de um limiar, exemplo 0.5, roteia pra humano em vez de disparar a ferramenta. Esse limiar não é fixo pra todo caso, ele deve ser proporcional ao risco da ação. Ações reversíveis e de somente leitura aceitam limiares mais baixos, enquanto ações arriscadas pedem limiares mais altos, como abaixo de 0.6 rotear pra humano, ou abaixo de 0.5 rotear e acima de 0.9 seguir com confirmação em ação de alto risco. A recomendação é testar isso nos seus próprios dados, plotando confiança contra acurácia.
Dá pra usar o Jev pra escolher os argumentos da ferramenta, não só o nome dela?
Sim, esse é justamente o padrão do cookbook oficial de function calling da TypeSafe. A escolha da função e os argumentos de conjunto fechado viram perguntas tipadas com confiança, tudo numa única requisição que carrega a escolha da função e os argumentos de todas as funções disponíveis. O dispatcher lê só as respostas da função que foi escolhida, e argumentos de conjunto fechado são mapeados como choice para um valor, set para vários valores, ou flag pra booleano.
O Jev funciona bem quando o agente tem centenas de ferramentas ou skills pra escolher?
A TypeSafe documenta esse cenário no cookbook de sugestão de skill, com um roster de 182 skills no exemplo. O padrão é duas requisições: a primeira ranqueia todas as skills e responde se o turno precisa de alguma delas, e a segunda relê apenas as três primeiras com descrição completa, podendo até rejeitar todas. Segundo o cookbook, esse desenho reduz mais da metade das cargas de skill erradas e das cargas quando nada realmente serve.
O Jev substitui checagem de segurança antes de rodar uma ferramenta arriscada?
Não, e a própria TypeSafe é clara sobre isso: conteúdo escrito pra direcionar o modelo de forma adversarial pode mover a resposta, então uma guarda construída sobre o Jev deve ficar ao lado de checagens determinísticas, nunca no lugar delas. A LangChain segue essa linha no AutoModeMiddleware, que usa o Jev pra checar chamadas de ferramenta arriscadas e bloquear a execução antes dela acontecer. Só que ele recusa, não pede aprovação, então se você quer aprovação humana precisa combinar com o middleware de human-in-the-loop.
Existe alguma ferramenta ou framework de agente com integração pronta pro Jev?
Sim, o Pydantic AI tem integração oficial via TypeSafeModel, instalada pelo extra typesafe, que já traz a dependência typesafe-sdk. O perfil desse modelo declara supports_text_output=False, então quando você passa um output_type com vários tipos estruturados, isso funciona como um conjunto de rotas, e uma segunda requisição pergunta só os campos do tipo que foi escolhido. O Jev também está disponível na plataforma de IA da Cloudflare, com model ID typesafe/jev, invocável pelo binding AI usando env.AI.run(), na versão jev-1.13.0.
Quais os limites de contexto que preciso respeitar ao montar o state e as perguntas pro Jev 1.13?
O orçamento documentado pro Jev 1.13 é de 64k somando o state com todas as perguntas da requisição, e de 32k somando o state com a pergunta mais longa isoladamente. Vale lembrar que o modelo degrada quando há contexto irrelevante no state, então o limite técnico não é motivo pra empurrar histórico inteiro de conversa pra dentro do campo.
Formações
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 45min
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.
